diff --git a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas index c6ee3564ae..3cc8dcc901 100644 --- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas +++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas @@ -18,9 +18,9 @@ type FPackage: IKeymanPackageInstalled; const BCP47: string); static; public class function BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean; static; - class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string): Boolean; overload; static; - class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean; overload; static; - class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean; overload; static; + class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string; BaseKeyboardID: Integer): Boolean; overload; static; + class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean; overload; static; + class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean; overload; static; end; implementation @@ -35,29 +35,30 @@ uses Keyman.Configuration.UI.KeymanProtocolHandler, Keyman.Configuration.UI.MitigationForWin10_1803, kmint, + KeymanOptionNames, UfrmHTML, UfrmInstallKeyboard; class function TInstallFile.Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; - const LogFile: string): Boolean; + const LogFile: string; BaseKeyboardID: Integer): Boolean; begin if TKeymanProtocolHandler.CanHandle(FirstKeyboardFileName) then begin - Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile); + Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, BaseKeyboardID); end else if (KeyboardFileNames.Count > 1) or (Pos('=', FirstKeyboardFileName) > 0) then begin - Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent) + Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent, BaseKeyboardID) end // TODO: support bare package ids from command line (if it does not include a file extension, assume it is a .kmp and try and download it) // else if IsNotPackageOrKeyboardFile then else begin - Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, ''); + Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '', BaseKeyboardID); end; end; -class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean; +class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean; var n: Integer; InstalledKeyboards: array of IKeymanKeyboardInstalled; @@ -77,7 +78,7 @@ begin begin if ASilent then begin - InstallKeyboard(LogFile, BCP47); + InstallKeyboard(LogFile, BCP47, BaseKeyboardID); Result := True; end else @@ -139,7 +140,7 @@ end; /// This is the handler for the `-i` parameter, e.g. /// kmshell -i khmer_angkor.kmp c:\temp\sil_euro_latin.kmp=fr /// -class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean; +class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean; var i, j: Integer; FPackage: IKeymanPackageInstalled; @@ -170,7 +171,7 @@ begin end; if IsPackage then begin - FPackage := (kmcom.Packages as IKeymanPackagesInstalled2).Install2(FileName, True); + FPackage := (kmcom.Packages as IKeymanPackagesInstalled3).Install3(FileName, True, BaseKeyboardID); if Length(FilenameBCP47) > 1 then RegisterKeyboardPackageLanguage(FPackage, FilenameBCP47[1]) else RegisterKeyboardPackageLanguage(FPackage, ''); @@ -178,7 +179,7 @@ begin end else begin - FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled2).Install2(FileName, True); + FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled3).Install3(FileName, True, BaseKeyboardID); if (Length(FilenameBCP47) > 1) and (Trim(FilenameBCP47[1]) <> '') then BCP47Tag := FilenameBCP47[1] else BCP47Tag := TTIPMaintenance.GetFirstLanguage(FKeyboard); @@ -209,6 +210,7 @@ end; class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean; var dlgOpen: TOpenDialog; + BaseKeyboardID : Integer; begin dlgOpen := TOpenDialog.Create(nil); try @@ -216,9 +218,9 @@ begin 'Keyman files (*.kmx, *.kxx, *.kmp)|*.kmx;*.kxx;*.kmp|Keyman keyboards (*.kmx,*.kxx)' + '|*.kmx;*.kxx|Keyman packages (*.kmp)|*.kmp|All files (*.*)|*.*'; dlgOpen.Title := 'Install Keyman Keyboard'; - + BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value; if dlgOpen.Execute then - Result := Execute(Owner, dlgOpen.FileName, False, False, '', '') + Result := Execute(Owner, dlgOpen.FileName, False, False, '', '', BaseKeyboardID) else Result := False; finally diff --git a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas index 6f13f6777b..60ac8ae43c 100644 --- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas +++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas @@ -17,13 +17,13 @@ type FDownloadURL: string; frmDownloadProgress: TfrmDownloadProgress; function DoHandle(Owner: TComponent; const url: string; ASilent, - ANoWelcome: Boolean; const ALogFile: string): Boolean; + ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean; procedure DoDownload(AOwner: TfrmDownloadProgress; var Result: Boolean); procedure HttpReceiveData(const Sender: TObject; AContentLength, AReadCount: Int64; var Abort: Boolean); public class function CanHandle(const url: string): Boolean; static; - class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string): Boolean; static; + class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean; static; end; implementation @@ -51,13 +51,13 @@ end; class function TKeymanProtocolHandler.Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; - const ALogFile: string): Boolean; + const ALogFile: string; BaseKeyboardID: Integer): Boolean; var h: TKeymanProtocolHandler; begin h := TKeymanProtocolHandler.Create; try - Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile); + Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile, BaseKeyboardID); finally h.Free; end; @@ -65,7 +65,7 @@ end; function TKeymanProtocolHandler.DoHandle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; - const ALogFile: string): Boolean; + const ALogFile: string; BaseKeyboardID: Integer): Boolean; var FTempDir: string; PackageID, BCP47: string; @@ -98,7 +98,7 @@ begin end; // TODO: this makes a circular dependency, refactor it out! - Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47); + Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID); finally if FileExists(FDownloadFilename) then diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas index 6d79811a80..775aa1ca2e 100644 --- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas +++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas @@ -74,6 +74,7 @@ uses Vcl.StdCtrls, keymanapi_TLB, + KeymanOptionNames, UfrmKeymanBase, UfrmWebContainer; @@ -102,7 +103,7 @@ type protected procedure FireCommand(const command: WideString; params: TStringList); override; public - procedure InstallKeyboard(const ALogFile, BCP47Tag: string); + procedure InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer); property DefaultBCP47Tag: string read FDefaultBCP47Tag write SetDefaultBCP47Tag; property InstallFile: string read FInstallFile write SetInstallFile; property Silent: Boolean read FSilent write FSilent; @@ -271,6 +272,7 @@ end; procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TStringList); var BCP47Tag: string; + BaseKeyboardID :Integer; begin BCP47Tag := ''; if (command = 'keyboard_install') and kmcom.SystemInfo.IsAdministrator then // I4172 @@ -283,7 +285,8 @@ begin Manager.Title := 'Installing Keyboard'; Manager.CanCancel := False; Manager.UpdateProgress('Installing Keyboard', 0, 0); - InstallKeyboard('', BCP47Tag); + BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value; + InstallKeyboard('', BCP47Tag, BaseKeyboardID); Result := True; end ); @@ -299,6 +302,7 @@ begin var t: TTempFile; ExecParams: string; + BaseKeyboardString :string; begin KL.MethodEnter(Self, '"keyboard_install"', [params.Text]); try @@ -306,8 +310,9 @@ begin Manager.CanCancel := False; Manager.UpdateProgress('Installing Keyboard', 0, 0); t := TTempFileManager.Get('.log'); + BaseKeyboardString := IntToHex(kmcom.Options[KeymanOptionName(koBaseLayout)].Value, 8); try - ExecParams := '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+ + ExecParams := '-log "'+t.Name+'" -bkd "'+BaseKeyboardString+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+ ' -nowelcome '+TTIPMaintenance.GetUserDefaultLangParameterString; KL.Log('Calling elevated kmshell %s', [ExecParams]); if WaitForElevatedConfiguration(GetForegroundWindow, ExecParams) = 0 then @@ -358,7 +363,7 @@ end; ------------------------------------------------------------------------------} // TODO: move this to TInstallFile -procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string); +procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer); var i: Integer; kbd: IKeymanKeyboardInstalled; @@ -400,7 +405,7 @@ begin kbd := nil; kmcom.Keyboards.Apply; kmcom.Keyboards.Refresh; - FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile2).Install2(True); + FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile3).Install3(True, BaseKeyboardID); if not InstallTipForKeyboard(BCP47Tag) then begin // TODO can we return a failure code? @@ -461,7 +466,7 @@ begin kmcom.Keyboards.Apply; kmcom.Keyboards.Refresh; // I2169 - (FPackage as IKeymanPackageFile2).Install2(True); + (FPackage as IKeymanPackageFile3).Install3(True, BaseKeyboardID); kmcom.Refresh; diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas index aff3251037..ed236d489d 100644 --- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas +++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas @@ -87,6 +87,7 @@ uses Keyman.Configuration.UI.InstallFile, Keyman.System.LocaleStrings, kmint, + KeymanOptionNames, MessageIdentifierConsts, Upload_Settings, utilfiletypes, @@ -213,6 +214,7 @@ end; procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string); var FTempDir: string; + BaseKeyboardID: Integer; begin FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679 try @@ -230,8 +232,8 @@ begin finally frmDownloadProgress.Free; end; - - if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47) then + BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value; + if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID) then ModalResult := mrOk; finally diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas index f9b5f9ac9b..0f0cc6f367 100644 --- a/windows/src/desktop/kmshell/main/initprog.pas +++ b/windows/src/desktop/kmshell/main/initprog.pas @@ -206,7 +206,7 @@ end; function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean; var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean; - var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean; + var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID, FBaseKeyboard: Integer): Boolean; var s: string; i: Integer; @@ -263,6 +263,7 @@ begin else if s = '-bd' then FMode := fmBackgroundDownload else if s = '-an' then FMode := fmApplyInstallNow else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169 + else if s = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end else if s = '-mcompilekbds' then begin FMode := fmMCompileKbds; @@ -329,7 +330,7 @@ end; procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean; FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle; - const FDefaultBCP47: string; FDefaultLangID: Integer); forward; + const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward; procedure Run; var @@ -340,7 +341,7 @@ var FForce: Boolean; FParentWindow: THandle; FLogFile: string; - FDefaultLangID: Integer; + FDefaultLangID, FBaseKeyboard: Integer; FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; begin @@ -349,7 +350,7 @@ begin KeyboardFileNames := TStringList.Create; try FParentWindow := 0; - if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then + if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard) then begin //TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL); Exit; @@ -357,7 +358,7 @@ begin if not LoadKMCOM then Exit; try - RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID); + RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard); finally kmcom := nil; end; @@ -396,7 +397,7 @@ end; procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean; FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; - FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer); + FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); var kdl: IKeymanDefaultLanguage; FIcon: string; @@ -559,7 +560,7 @@ begin else ExitCode := 1; fmInstall: - if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile) + if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile, FBaseKeyboard) then ExitCode := 0 else ExitCode := 1; diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas index 5ea1e74265..b7255869b7 100644 --- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas +++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas @@ -37,7 +37,7 @@ uses keymankeyboard, keymancontext, Classes, PackageInfo, keymankeyboardlanguagesfile; type - TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2) + TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2, IKeymanKeyboardFile3) private FFileName: WideString; FError: Boolean; @@ -52,6 +52,7 @@ type { IKeymanKeyboardFile } procedure Install(Force: WordBool); safecall; function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall; + function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall; { IKeymanKeyboard } function Get_Copyright: WideString; override; safecall; @@ -252,7 +253,7 @@ procedure TKeymanKeyboardFile.Install(Force: WordBool); begin with TKPInstallKeyboard.Create(Context) do try - Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force); + Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0); finally Free; end; @@ -264,7 +265,23 @@ var begin with TKPInstallKeyboard.Create(Context) do try - Execute(FFileName, '', [], nil, Force); + Execute(FFileName, '', [], nil, Force, 0); + finally + Free; + end; + + kki := Context.Keyboards as IKeymanKeyboardsInstalled; + kki.Refresh; + Result := kki.Items[FFileName]; +end; + +function TKeymanKeyboardFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; +var + kki: IKeymanKeyboardsInstalled; +begin + with TKPInstallKeyboard.Create(Context) do + try + Execute(FFileName, '', [], nil, Force, BaseKeyboardID); finally Free; end; diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas index f5f8b74448..b37e0dfce0 100644 --- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas +++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas @@ -37,7 +37,8 @@ uses keymanerrorcodes, keymankeyboardinstalled, keymankeyboard, internalinterfaces; type - TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled) // I4376 + TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled, + IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled3) // I4376 private FKeyboards: TKeyboardList; procedure TriggerWindowsLanguageSync; @@ -55,6 +56,7 @@ type procedure Install(const Filename: WideString; Force: WordBool); safecall; procedure Apply; safecall; function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; safecall; + function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall; procedure RefreshInstalledKeyboards; safecall; { IIntKeymanKeyboardsInstalled } @@ -101,7 +103,7 @@ procedure TKeymanKeyboardsInstalled.Install(const Filename: WideString; Force: W begin with TKPInstallKeyboard.Create(Context) do try - Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force); + Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0); finally Free; end; @@ -112,7 +114,21 @@ function TKeymanKeyboardsInstalled.Install2(const Filename: WideString; begin with TKPInstallKeyboard.Create(Context) do try - Execute(FileName, '', [], nil, Force); + Execute(FileName, '', [], nil, Force, 0); + finally + Free; + end; + + DoRefresh; + Result := Get_Items(FileName); +end; + +function TKeymanKeyboardsInstalled.Install3(const Filename: WideString; + Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; +begin + with TKPInstallKeyboard.Create(Context) do + try + Execute(FileName, '', [], nil, Force, BaseKeyboardID); finally Free; end; diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas index 14b207e229..28ef2d064a 100644 --- a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas +++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas @@ -1,18 +1,18 @@ (* Name: keymanpackagefile Copyright: Copyright (C) SIL International. - Documentation: - Description: + Documentation: + Description: Create Date: 20 Jun 2006 Modified Date: 29 Mar 2010 Authors: mcdurdin - Related Files: - Dependencies: + Related Files: + Dependencies: - Bugs: - Todo: - Notes: + Bugs: + Todo: + Notes: History: 20 Jun 2006 - mcdurdin - Initial version 01 Aug 2006 - mcdurdin - Avoid processmessages in unzip 04 Dec 2006 - mcdurdin - Add Serialize function, support ShortcutRootPath in installation @@ -37,7 +37,7 @@ uses keymanpackagecontentfiles, StdVcl, kmpinffile, KeymanContext, Graphics, Classes, internalinterfaces; type - TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2) + TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2, IKeymanPackageFile3) private FSourcePath: string; FSubFiles: IKeymanPackageContentFiles; @@ -74,6 +74,7 @@ type { IKeymanPackageFile } procedure Install(Force: WordBool); safecall; function Install2(Force: WordBool): IKeymanPackageInstalled; safecall; + function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall; public constructor Create(AContext: TKeymanContext; const Filename: Widestring); destructor Destroy; override; @@ -175,7 +176,7 @@ begin o := [ipLegacyRegisterAndInstallProfiles]; if Force then Include(o, ipForce); - Execute(FFileName, o); + Execute(FFileName, o, 0); finally Free; end; @@ -191,7 +192,27 @@ begin o := []; if Force then Include(o, ipForce); - Execute(FFileName, o); + Execute(FFileName, o, 0); + finally + Free; + end; + + kpi := Context.Packages as IKeymanPackagesInstalled; + kpi.Refresh; + Result := kpi.Items[FFileName]; +end; + +function TKeymanPackageFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; +var + o: TKPInstallPackageOptions; + kpi: IKeymanPackagesInstalled; +begin + with TKPInstallPackage.Create(Context) do + try + o := []; + if Force then + Include(o, ipForce); + Execute(FFileName, o, BaseKeyboardID); finally Free; end; @@ -211,7 +232,7 @@ var begin if not FileExists(FFileName) then raise Exception.Create('File '+FFileName+' does not exist.'); - + if GetTempPath(260, buf) = 0 then raise Exception.Create('Unable to get temporary path: ' + IntToHex(GetLastError, 8) + ' ' + SysErrorMessage(GetLastError)); FTempOutPath := buf; diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas index 9dd9f1a52a..821a38bdc5 100644 --- a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas +++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas @@ -38,7 +38,8 @@ type property Items[Index: Integer]: IIntKeymanPackageInstalled read GetItem write SetItem; default; end; - TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, IKeymanPackagesInstalled, IKeymanPackagesInstalled2) + TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, + IKeymanPackagesInstalled, IKeymanPackagesInstalled2, IKeymanPackagesInstalled3) private FPackages: TPackageList; protected @@ -51,6 +52,7 @@ type function IndexOf(const ID: WideString): Integer; safecall; procedure Install(const Filename: WideString; Force: WordBool); safecall; function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall; + function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall; public constructor Create(AContext: TKeymanContext); destructor Destroy; override; @@ -118,7 +120,7 @@ begin o := [ipLegacyRegisterAndInstallProfiles]; if Force then Include(o, ipForce); - Execute(Filename, o); + Execute(Filename, o, 0); finally Free; end; @@ -136,7 +138,29 @@ begin o := []; if Force then Include(o, ipForce); - Execute(Filename, o); + Execute(Filename, o, 0); + finally + Free; + end; + + DoRefresh; + Result := Get_Items(Filename); + + KL.MethodExit(Self, 'Install2'); +end; + +function TKeymanPackagesInstalled.Install3(const Filename: WideString; + Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; +var + o: TKPInstallPackageOptions; +begin + KL.MethodEnter(Self, 'Install2', [Filename, Force]); + with TKPInstallPackage.Create(Context) do + try + o := []; + if Force then + Include(o, ipForce); + Execute(Filename, o, BaseKeyboardID); finally Free; end; diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas index 786ce6c9b2..7246c9173f 100644 --- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas +++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas @@ -1569,6 +1569,17 @@ type procedure RefreshInstalledKeyboards; safecall; end; +// *********************************************************************// +// Interface: IKeymanKeyboardsInstalled3 +// Flags: (4416) Dual OleAutomation Dispatchable +// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641} +// *********************************************************************// + IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled) + ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}'] + function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall; + procedure RefreshInstalledKeyboards; safecall; + end; + // *********************************************************************// // Interface: IKeymanKeyboardInstalled2 // Flags: (4416) Dual OleAutomation Dispatchable @@ -1610,6 +1621,16 @@ type function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall; end; +// *********************************************************************// +// Interface: IKeymanPackagesInstalled3 +// Flags: (4416) Dual OleAutomation Dispatchable +// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458} +// *********************************************************************// + IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled) + ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}'] + function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall; + end; + // *********************************************************************// // DispIntf: IKeymanPackagesInstalled2Disp // Flags: (4416) Dual OleAutomation Dispatchable @@ -1639,6 +1660,16 @@ type function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall; end; +// *********************************************************************// +// Interface: IKeymanKeyboardFile3 +// Flags: (4416) Dual OleAutomation Dispatchable +// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8} +// *********************************************************************// + IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile) + ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}'] + function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall; + end; + // *********************************************************************// // DispIntf: IKeymanKeyboardFile2Disp // Flags: (4416) Dual OleAutomation Dispatchable @@ -1677,6 +1708,17 @@ type function Install2(Force: WordBool): IKeymanPackageInstalled; safecall; end; +// *********************************************************************// +// Interface: IKeymanPackageFile3 +// Flags: (4416) Dual OleAutomation Dispatchable +// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7} +// *********************************************************************// + IKeymanPackageFile3 = interface(IKeymanPackageFile) + ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}'] + function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall; + end; + + // *********************************************************************// // DispIntf: IKeymanPackageFile2Disp // Flags: (4416) Dual OleAutomation Dispatchable diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl index 9eb63fbd68..91f49822b5 100644 --- a/windows/src/engine/kmcomapi/kmcomapi.ridl +++ b/windows/src/engine/kmcomapi/kmcomapi.ridl @@ -66,6 +66,10 @@ library keymanapi interface IKeymanPackageFile2; interface IKeymanKeyboardLanguageInstalled2; interface IKeymanKeyboardLanguagesInstalled2; + interface IKeymanKeyboardFile3; + interface IKeymanPackageFile3; + interface IKeymanKeyboardsInstalled3; + interface IKeymanPackagesInstalled3; interface IKeymanBCP47Canonicalization; interface IKeymanDefaultLanguage; @@ -976,6 +980,60 @@ library keymanapi HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanKeyboardInstalled** KeyboardResult); }; + [ + uuid(8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4), + version(19.0), + helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanKeyboardFile3"), + dual, + oleautomation + ] + interface IKeymanKeyboardFile3: IKeymanKeyboardFile + { + [id(0x00000121)] + HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult); + }; + + [ + uuid(C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7), + version(19.0), + helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackageFile3"), + dual, + oleautomation + ] + + interface IKeymanPackageFile3: IKeymanPackageFile + { + [id(0x00000124)] + HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageFile** Package); + }; + + + [ + uuid(B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641), + version(19.0), + helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2\3"), + dual, + oleautomation + ] + interface IKeymanKeyboardsInstalled3: IKeymanKeyboardsInstalled + { + [id(0x00000122)] + HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult); + }; + + [ + uuid(3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458), + version(19.0), + helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackagesInstalled3"), + dual, + oleautomation + ] + interface IKeymanPackagesInstalled3: IKeymanPackagesInstalled + { + [id(0x00000123)] + HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageInstalled** PackageResult); + }; + [ uuid(9B43B6BC-C622-47EF-915E-6780CF53BAAA), version(14.0), diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas index 1df237b0c6..6d3bd1f3ed 100644 --- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas +++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas @@ -64,7 +64,7 @@ type ikLegacyRegisterAndInstallProfiles); TKPInstallKeyboard = class(TKPBase) - procedure Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean); + procedure Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer); procedure RegisterProfiles(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; PackageLanguageMetadata: TPackageKeyboardLanguageList); private procedure LegacyRegisterAndInstallLanguageProfile(Langs: array of Integer; @@ -112,7 +112,7 @@ uses utiltsf, keymanapi_TLB; -procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean); +procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer); var ki: TKeyboardInfo; FDestPath: string; @@ -125,7 +125,9 @@ var FExitCode: Integer; FKVKName: WideString; FCreatedIcon: Boolean; - BaseKeyboardID: Integer; + ElevatedBaseKeyboardID: Integer; + KeymanContext: TKeymanContext; + RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard; begin KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]); try @@ -246,14 +248,19 @@ begin KL.Log(FLogText); end; - // Recompile a mnemonic layout to the user's selected base layout + // Recompile a mnemonic layout to the user's selected base layout. If + // the baselayout has not been passed through (=0) then use the current + // process configured value which is likely the Admin user if ki.MnemonicLayout then // I4169 begin - with Context as TKeymanContext do - BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value; - with TKPRecompileMnemonicKeyboard.Create(Context) do + KeymanContext := Context as TKeymanContext; + ElevatedBaseKeyboardID := (KeymanContext.Options as IKeymanOptions).Items['koBaseLayout'].Value; + RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context); try - Execute(FDestFileName, PackageID, BaseKeyboardID); + if (BaseKeyboardID = 0) then + RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, ElevatedBaseKeyboardID) + else + RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, BaseKeyboardID); finally Free; end; diff --git a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas index 98edfbf3fb..4ab33cdfee 100644 --- a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas +++ b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas @@ -50,7 +50,7 @@ type TKPInstallPackage = class(TKPBase) public - procedure Execute(const FileName: string; Options: TKPInstallPackageOptions); + procedure Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer); end; implementation @@ -85,7 +85,7 @@ uses { TKPInstallPackage } -procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions); +procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer); function GetHHIcon: string; var buf: array[0..260] of char; @@ -112,7 +112,7 @@ var FErrorValue: Cardinal; FSrcFileName: string; - procedure InstallKeyboard(FileName: string); + procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer); var FOptions: TKPInstallKeyboardOptions; kbd: TPackageKeyboard; @@ -132,7 +132,7 @@ var with TKPInstallKeyboard.Create(Context) do try - Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options); + Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options, BaseKeyboardID); finally Free; end; @@ -253,12 +253,12 @@ begin begin case inf.Files[i].FileType of ftKeymanFile: - InstallKeyboard(dest + inf.Files[i].FileName); + InstallKeyboard(dest + inf.Files[i].FileName, BaseKeyboardID); ftPackageFile: with TKPInstallPackage.Create(Context) do try - Execute(dest + inf.Files[i].FileName, Options); + Execute(dest + inf.Files[i].FileName, Options, BaseKeyboardID); finally Free; end;