spiegel-keyman/developer/src/tike/project/Keyman.Developer.System.Project.kmnProjectFile.pas

267 lines
10 KiB
ObjectPascal

(*
Name: Keyman.Developer.System.Project.kmnProjectFile
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 1 Aug 2006
Modified Date: 24 Aug 2015
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 01 Aug 2006 - mcdurdin - Add loading and saving from XML
23 Aug 2006 - mcdurdin - Add CompileKeyboardToWeb function
28 Sep 2006 - mcdurdin - Editions
06 Oct 2006 - mcdurdin - Add TestKeymanWeb
04 Dec 2006 - mcdurdin - WideString all properties; Add TestKeymanWeb function
04 Jan 2007 - mcdurdin - Clear messages before compiling
16 May 2007 - mcdurdin - I759 - Compiler did not say 'complete' when finished
16 May 2007 - mcdurdin - I791 - Unicode characters not rendering in Project
30 May 2007 - mcdurdin - I791 - Non-ascii characters not rendering correctly in Project (keyboard name only)
19 Nov 2007 - mcdurdin - I1153 - Crash when closing file
27 Mar 2008 - mcdurdin - I1370 - Rename files to avoid invalid characters during compile of KeymanWeb keyboards
16 Jan 2009 - mcdurdin - Add font helper call
26 Jul 2010 - mcdurdin - I2468 - Eliminate KeymanWeb Pack
18 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support
13 Dec 2012 - mcdurdin - I3681 - V9.0 - KeymanWeb compiler should output formatted js when debug=1
10 Jan 2014 - mcdurdin - I4021 - V9.0 - Redesign Keyboard Wizard to integrate V9 features
21 Feb 2014 - mcdurdin - I4057 - V9.0 - Keyman Developer Keyboard Font dialog helpful to reduce font confusion
21 Feb 2014 - mcdurdin - I4063 - V9.0 - Web Debugger needs to embed fonts for OSK and text area
27 Feb 2014 - mcdurdin - I4087 - V9.0 - KeymanWeb compiler does not clear messages before starting
19 Mar 2014 - mcdurdin - I4140 - V9.0 - Add keyboard version information to keyboards
25 Sep 2014 - mcdurdin - I4409 - V9.0 - Wrong font selected in keyboard debugger touch layout
04 Nov 2014 - mcdurdin - I4504 - V9.0 - Consolidate the compile action into single command
04 May 2015 - mcdurdin - I4687 - V9.0 - Split project UI actions into separate classes
04 May 2015 - mcdurdin - I4688 - V9.0 - Add build path to project settings
04 May 2015 - mcdurdin - I4692 - V9.0 - Add Clean as project action
04 May 2015 - mcdurdin - I4694 - V9.0 - Split UI actions from non-UI actions in projects
05 May 2015 - mcdurdin - I4698 - V9.0 - Split project and user preferences files
06 May 2015 - mcdurdin - I4701 - V9.0 - If version is not specified in keyboard file, it gets blank instead of 1.0 in kmcomp .kpj
11 May 2015 - mcdurdin - I4706 - V9.0 - Update compile logging for silent and warning-as-error cleanness
27 May 2015 - mcdurdin - I4564 - V9.0 - If only web/touch targets are selected, compiler does not run
27 May 2015 - mcdurdin - I4720 - Compiling a standalone keyboard crashes Developer [CrashID:tike.exe_9.0.503.0_00A4316C_EAccessViolation]
03 Aug 2015 - mcdurdin - I4823 - Note in compile log if symbols are included in build
24 Aug 2015 - mcdurdin - I4865 - Add treat hints and warnings as errors into project
24 Aug 2015 - mcdurdin - I4866 - Add warn on deprecated features to project and compile
*)
unit Keyman.Developer.System.Project.kmnProjectFile; // I3306 // I4687 // I4688 // I4692
interface
uses
System.SysUtils,
Xml.XMLIntf,
Keyman.Developer.System.Project.ProjectFile,
Keyman.Developer.System.Project.ProjectFiles,
Keyman.Developer.System.Project.ProjectFileType,
UKeymanTargets;
type
TkmnProjectFile = class;
TkmnProjectFile = class(TOpenableProjectFile)
private
FDebug: Boolean;
FHeader_Name: WideString;
FHeader_Message: WideString;
FHeader_Copyright: WideString;
FTargets: TKeymanTargets;
FKVKFileName: string;
function GetOutputFilename: string;
function GetTargetFilename: string;
function GetJSTargetFilename: string;
protected
function GetRelativeOrder: Integer; override;
procedure GetFileParameters; override;
property KVKFileName: string read FKVKFileName;
property IsDebug: Boolean read FDebug;
public
function IsCompilable: Boolean; override;
procedure Load(node: IXMLNode); override; // I4698
procedure Save(node: IXMLNode); override; // I4698
procedure LoadState(node: IXMLNode); override; // I4698
procedure SaveState(node: IXMLNode); override; // I4698
property Debug: Boolean read FDebug write FDebug;
property OutputFilename: string read GetOutputFilename;
property TargetFilename: string read GetTargetFilename;
property JSTargetFilename: string read GetJSTargetFilename;
property Header_Name: WideString read FHeader_Name;
property Header_Copyright: WideString read FHeader_Copyright;
property Header_Message: WideString read FHeader_Message;
property Targets: TKeymanTargets read FTargets;
end;
implementation
uses
System.Classes,
System.Variants,
Winapi.Windows,
KeyboardParser,
kmxfileconsts,
KeyboardFonts,
Keyman.System.KeyboardUtils,
utilsystem;
{-------------------------------------------------------------------------------
- TkmnProjectFile -
-------------------------------------------------------------------------------}
procedure TkmnProjectFile.Save(node: IXMLNode); // I4698
begin
inherited Save(node); // I4698
node := node.AddChild('Details');
if FHeader_Name <> '' then node.AddChild('Name').NodeValue := FHeader_Name;
if FHeader_Copyright <> '' then node.AddChild('Copyright').NodeValue := FHeader_Copyright;
if FHeader_Message <> '' then node.AddChild('Message').NodeValue := FHeader_Message;
end;
procedure TkmnProjectFile.SaveState(node: IXMLNode); // I4698
begin
inherited SaveState(node);
node.AddChild('Debug').NodeValue := FDebug;
end;
procedure TkmnProjectFile.Load(node: IXMLNode); // I4698
begin
inherited Load(node);
if node.ChildNodes.IndexOf('Details') < 0 then Exit;
node := node.ChildNodes['Details'];
if node.ChildNodes.IndexOf('Name') >= 0 then FHeader_Name := VarToWideStr(node.ChildValues['Name']);
if node.ChildNodes.IndexOf('Copyright') >= 0 then FHeader_Copyright := VarToWideStr(node.ChildValues['Copyright']);
if node.ChildNodes.IndexOf('Message') >= 0 then FHeader_Message := VarToWideStr(node.ChildValues['Message']);
end;
procedure TkmnProjectFile.LoadState(node: IXMLNode); // I4698
begin
inherited LoadState(node);
try
if node.ChildNodes.IndexOf('Debug') >= 0 then FDebug := node.ChildValues['Debug'];
except
FDebug := False;
end;
end;
function TkmnProjectFile.GetRelativeOrder: Integer;
begin
Result := 20;
end;
function TkmnProjectFile.GetTargetFilename: string;
var
FTempFileVersion: string;
begin
// https://github.com/keymanapp/keyman/issues/631
// This appears to be a Delphi compiler bug (RSP-20457)
// Workaround is to make a copy of the parameter locally
// which fixes the reference counting.
FTempFileVersion := FileVersion;
Result := OwnerProject.GetTargetFilename(OutputFileName, FileName, FTempFileVersion);
end;
function TkmnProjectFile.IsCompilable: Boolean;
begin
Result := True;
end;
procedure TkmnProjectFile.GetFileParameters;
var
j: Integer;
value: WideString;
FVersion: string; // I4701
begin
FHeader_Message := '';
FHeader_Copyright := '';
FHeader_Name := '';
FKVKFileName := '';
SetFileVersion('1.0'); // I4701
if not FileExists(FileName) then Exit;
with TKeyboardParser.Create do // I4720
try
LoadFromFile(Self.FileName);
FHeader_Name := GetSystemStoreValue(ssName);
FHeader_Copyright := GetSystemStoreValue(ssCopyright);
FHeader_Message := GetSystemStoreValue(ssMessage);
FVersion := GetSystemStoreValue(ssKeyboardVersion); // I4701
if FVersion = '' then
FVersion := '1.0';
SetFileVersion(FVersion);
FKVKFileName := GetSystemStoreValue(ssVisualKeyboard);
// Compile targets
FTargets := StringToKeymanTargets(GetSystemStoreValue(ssTargets));
if ktAny in FTargets then FTargets := AllKeymanTargets;
if FTargets = [] then FTargets := [ktWindows];
if Assigned(Project) then // I4720
begin
// Get sub files
value := GetSystemStoreValue(ssBitmap);
if (value <> '') then
begin
if ExtractFileExt(value) = '' then value := value + '.bmp';
value := ExpandFileNameClean(Self.FileName, value);
if Project.Files.IndexOfFileName(value) < 0 then
begin
for j := Project.Files.Count - 1 downto 0 do
if Project.Files[j].Parent = Self then
Project.Files.Delete(j);
CreateProjectFile(Project, value, Self);
end
end
else
for j := Project.Files.Count - 1 downto 0 do
if Project.Files[j].Parent = Self then
Project.Files.Delete(j);
end;
finally
Free;
end;
end;
function TkmnProjectFile.GetJSTargetFilename: string;
begin
if FTargets = [] then
GetFileParameters;
// There is no JS target if no target is specified
if FTargets * KMWKeymanTargets = [] then
Exit('');
Result := OwnerProject.GetTargetFilename(TKeyboardUtils.GetKeymanWebCompiledFileName(FileName), FileName, FileVersion);
end;
function TkmnProjectFile.GetOutputFilename: string;
begin
if FTargets = [] then
GetFileParameters;
// If no target is specified, we'll fall back to .kmx
// so we always have at least one target filename
if (FTargets <> []) and (FTargets * KMXKeymanTargets = []) then
Exit('');
Result := ChangeFileExt(FileName, '.kmx');
end;
initialization
RegisterProjectFileType('.kmn', TkmnProjectFile);
end.