From 65335ecaf5057c234816c8fcd1c9aa4f8b2955ed Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 24 Jul 2026 12:07:22 +1000
Subject: [PATCH 01/26] fix(windows): initial commit
---
windows/src/desktop/kmshell/main/UfrmMain.pas | 2 ++
1 file changed, 2 insertions(+)
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index 6a631fb5461..a469db480c3 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -661,6 +661,8 @@ procedure TfrmMain.cefBeforeBrowseSync(Sender: TObject; const Url: string;
procedure TfrmMain.Options_BaseKeyboard; // I4169
begin
+ // TODO change this dialog to run as current user and elevate on "ok" button:wq
+
WaitForElevatedConfiguration(Handle, '-basekeyboard');
// Refresh will be triggered by elevated process
end;
From 92643e35692c0678153472cb6a33a11427a1c288 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 29 Jul 2026 14:47:00 +1000
Subject: [PATCH 02/26] fix(windows): handle basekeyboard change non-admin user
---
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 135 ++++++++++++++++--
windows/src/desktop/kmshell/main/UfrmMain.pas | 11 +-
windows/src/desktop/kmshell/main/initprog.pas | 16 ++-
.../com/keyboards/keymankeyboardinstalled.pas | 6 +-
.../kmcomapi/com/options/keymanoptions.pas | 24 ++--
.../processes/keyboard/kpinstallkeyboard.pas | 5 +-
.../keyboard/kprecompilemnemonickeyboard.pas | 10 +-
.../kmcomapi/util/internalinterfaces.pas | 2 +-
8 files changed, 174 insertions(+), 35 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 40a65e31ce1..b3f60a5067b 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -11,13 +11,16 @@ interface
TfrmBaseKeyboard = class(TfrmWebContainer)
procedure TntFormCreate(Sender: TObject);
private
+ FBaseKeyboardID: Integer;
procedure Footer_Cancel;
procedure Footer_OK(params: TStringList);
protected
procedure FireCommand(const command: WideString; params: TStringList); override;
end;
-function ConfigureBaseKeyboard: Boolean;
+function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
+function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
+function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
implementation
@@ -25,15 +28,18 @@ implementation
uses
BaseKeyboards,
- kmint;
+ ErrorControlledRegistry,
+ RegistryKeys,
+ keymanapi_TLB,
+ kmint,
+ utilkmshell;
-function ConfigureBaseKeyboard: Boolean;
-begin
- with TfrmBaseKeyboard.Create(nil) do
+function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
+begin with TfrmBaseKeyboard.Create(nil) do
try
Result := ShowModal = mrOk;
if Result then
- kmcom.Apply;
+ BaseKeyboardID := FBaseKeyboardID;
finally
Free;
end;
@@ -65,9 +71,122 @@ procedure TfrmBaseKeyboard.Footer_OK(params: TStringList);
v: Integer;
begin
if not TryStrToInt('$'+params.Values['id'], v) then Exit;
- kmcom.Options['koBaseLayout'].Value := v;
- kmcom.Options.Apply;
+ FBaseKeyboardID := v;
ModalResult := mrOk;
end;
+function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
+var
+ BaseKeyboardID: Integer;
+ PreviousBaseKeyboardID: Integer;
+ PreviousBaseKeyboardValue: string;
+ PreviousBaseKeyboardValueExists: Boolean;
+
+ procedure SavePreviousRegistryBaseKeyboardValue;
+ var
+ Reg: TRegistryErrorControlled;
+ begin
+ PreviousBaseKeyboardValueExists := False;
+ PreviousBaseKeyboardValue := '';
+
+ Reg := TRegistryErrorControlled.Create;
+ try
+ if Reg.OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and Reg.ValueExists(SRegValue_UnderlyingLayout) then
+ begin
+ PreviousBaseKeyboardValueExists := True;
+ PreviousBaseKeyboardValue := Reg.ReadString(SRegValue_UnderlyingLayout);
+ end;
+ finally
+ Reg.Free;
+ end;
+ end;
+
+ procedure RestorePreviousBaseKeyboardValue;
+ var
+ Reg: TRegistryErrorControlled;
+ begin
+ Reg := TRegistryErrorControlled.Create;
+ try
+ if Reg.OpenKey(SRegKey_KeymanEngine_CU, True) then
+ if PreviousBaseKeyboardValueExists then
+ Reg.WriteString(SRegValue_UnderlyingLayout, PreviousBaseKeyboardValue)
+ else if Reg.ValueExists(SRegValue_UnderlyingLayout) then
+ Reg.DeleteValue(SRegValue_UnderlyingLayout);
+ finally
+ Reg.Free;
+ end;
+ end;
+
+ procedure ForceBaseLayoutChange;
+ var
+ Reg: TRegistryErrorControlled;
+ begin
+ // This is hacky, maybe just remove the registry value, however that
+ // would not force a recompile if the was the default base layout.
+ // Options.Apply re-compiles only when it observes a changed base layout.
+ // The caller may be repairing missing files for the already-selected layout.
+ Reg := TRegistryErrorControlled.Create;
+ try
+ if Reg.OpenKey(SRegKey_KeymanEngine_CU, True) then
+ Reg.WriteString(SRegValue_UnderlyingLayout, '00000000');
+ finally
+ Reg.Free;
+ end;
+ end;
+
+begin
+ Result := False;
+ if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
+ not kmcom.SystemInfo.IsAdministrator then
+ Exit;
+
+ SavePreviousRegistryBaseKeyboardValue;
+ PreviousBaseKeyboardID := kmcom.Options['koBaseLayout'].Value;
+ kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
+ try
+ if PreviousBaseKeyboardID = BaseKeyboardID then
+ ForceBaseLayoutChange;
+ kmcom.Options.Apply;
+ Result := True;
+ finally
+ kmcom.Options['koBaseLayout'].Value := PreviousBaseKeyboardID;
+ RestorePreviousBaseKeyboardValue;
+ end;
+end;
+
+function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
+var
+ I: Integer;
+ Keyboard: IKeymanKeyboardInstalled;
+ BaseFileName: string;
+ BaseKeyboardIDHex: string;
+begin
+ BaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
+ for I := 0 to kmcom.Keyboards.Count - 1 do
+ begin
+ Keyboard := kmcom.Keyboards.Items[I];
+ BaseFileName := Keyboard.Filename;
+ if FileExists(BaseFileName) and
+ (not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx') or
+ not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx')) then
+ Exit(True);
+ end;
+ Result := False;
+end;
+
+function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
+var
+ MCompileResult: Boolean;
+begin
+ MCompileResult := True;
+ Result := False;
+ if BaseKeyboardNeedsMCompile(BaseKeyboardID) and not kmcom.SystemInfo.IsAdministrator then
+ MCompileResult := WaitForElevatedConfiguration(WindowHandle, '-mcompile ' + IntToHex(BaseKeyboardID, 8)) = 0;
+ if not MCompileResult then
+ Exit;
+ kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
+ kmcom.Options.Apply; // This will trigger a recompile if needed
+ Result := True;
+end;
+
end.
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index a469db480c3..a556019abd2 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -197,6 +197,7 @@ implementation
Keyman.Configuration.UI.UfrmStartInstall,
RegistryKeys,
SupportXMLRenderer,
+ UfrmBaseKeyboard,
UfrmChangeHotkey,
UfrmHTML,
UfrmInstallKeyboardFromWeb,
@@ -660,11 +661,15 @@ procedure TfrmMain.cefBeforeBrowseSync(Sender: TObject; const Url: string;
------------------------------------------------------------------------------}
procedure TfrmMain.Options_BaseKeyboard; // I4169
+var
+ BaseKeyboardID: Integer;
begin
- // TODO change this dialog to run as current user and elevate on "ok" button:wq
+ if ConfigureBaseKeyboard(BaseKeyboardID) then
+ begin
+ SetBaseKeyboard(Handle, BaseKeyboardID)
+ // Refresh will be triggered by elevated process
+ end;
- WaitForElevatedConfiguration(Handle, '-basekeyboard');
- // Refresh will be triggered by elevated process
end;
procedure TfrmMain.Options_SettingsManager;
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 359130f27e7..8ea4331995f 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -90,6 +90,7 @@ function Main(Owner: TComponent = nil): TModalResult;
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
+ fmMCompile,
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
@@ -262,6 +263,13 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 = '-mcompile' then
+ begin
+ FMode := fmMCompile;
+ Inc(i);
+ if i > ParamCount then Exit;
+ FQuery := ParamStr(i);
+ end
else if s = '-nowelcome' then FNoWelcome := True
else if s = '-kw' then FMode := fmKeyboardWelcome // I2569
else if s = '-kp' then FMode := fmKeyboardPrint // I2329
@@ -393,6 +401,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
+ BaseKeyboardID: Integer;
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
@@ -540,7 +549,12 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
end;
fmBaseKeyboard: // I4169
- if ConfigureBaseKeyboard
+ if ConfigureBaseKeyboard(BaseKeyboardID) and SetBaseKeyboard(0, BaseKeyboardID)
+ then ExitCode := 0
+ else ExitCode := 1;
+
+ fmMCompile:
+ if MCompileBaseKeyboard(FQuery)
then ExitCode := 0
else ExitCode := 1;
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
index 051d399b6ec..91ecaa9b5f8 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -109,7 +109,7 @@ TKeymanKeyboardInstalled = class( // I3581
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
+ procedure UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
procedure RefreshInstallation;
public
@@ -151,12 +151,12 @@ procedure TKeymanKeyboardInstalled.Uninstall;
end;
end;
-procedure TKeymanKeyboardInstalled.UpdateBaseLayout; // I4169
+procedure TKeymanKeyboardInstalled.UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
begin
if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then // I4615
with TKPRecompileMnemonicKeyboard.Create(Context) do
try
- Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName);
+ Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
index 7bea91450bc..8635a748083 100644
--- a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
+++ b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
@@ -1,18 +1,18 @@
(*
Name: keymanoptions
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 20 Jun 2006
Modified Date: 6 Feb 2015
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 - Add AutoRefershKeyman call
12 Aug 2008 - mcdurdin - Avoid crash with missing options
@@ -67,6 +67,7 @@ implementation
ErrorControlledRegistry,
RegistryKeys,
Glossary,
+ isadmin,
Keyman.System.BaseKeyboard,
KeymanOptionNames,
keymanerrorcodes;
@@ -112,7 +113,9 @@ function TKeymanOptions.IndexOf(const ID: WideString): Integer;
procedure TKeymanOptions.Apply;
var
- I, FOldBaseLayout: Integer;
+ I: Integer;
+ FOldBaseLayout: Integer;
+ FNewBaseLayout: Integer;
begin
with TRegistryErrorControlled.Create do // I3717
try
@@ -130,9 +133,10 @@ procedure TKeymanOptions.Apply;
FInternalOptions.Save(Context);
- if FOldBaseLayout <> Get_Items('koBaseLayout').Value then
+ FNewBaseLayout := Get_Items('koBaseLayout').Value;
+ if IsAdministrator and (FOldBaseLayout <> FNewBaseLayout) then
for I := 0 to Context.Keyboards.Count - 1 do // I4169
- (Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout;
+ (Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout(FNewBaseLayout);
Context.Control.AutoApplyKeyman;
end;
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
index 26c92faa90a..1df237b0c60 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -125,6 +125,7 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
+ BaseKeyboardID: Integer;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
@@ -248,9 +249,11 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
// Recompile a mnemonic layout to the user's selected base layout
if ki.MnemonicLayout then // I4169
begin
+ with Context as TKeymanContext do
+ BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;
with TKPRecompileMnemonicKeyboard.Create(Context) do
try
- Execute(FDestFileName, PackageID);
+ Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
index 30d0c275cc2..7a4d5a2b395 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -27,7 +27,7 @@ interface
type
TKPRecompileMnemonicKeyboard = class(TKPBase)
- procedure Execute(const FileName: string; const PackageName: string);
+ procedure Execute(const FileName: string; const PackageName: string; BaseKeyboardID: Cardinal);
end;
implementation
@@ -42,10 +42,8 @@ implementation
Winapi.Windows,
errorcontrolledregistry,
- keymancontext,
keymanerrorcodes,
KeymanPaths,
- keymanapi_TLB,
RegistryKeys,
utilexecute,
utilkeyman,
@@ -67,7 +65,7 @@ function GetKeyboardLayoutFileName(id: Integer): string;
Result := '';
end;
-procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: string);
+procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: string; BaseKeyboardID: Cardinal);
var
FDestPath, FDestFileName: string;
FBaseKeyboardIDHex: string;
@@ -76,7 +74,6 @@ procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: strin
FExitCode: Integer;
FMCompilePath: string;
FBaseKeyboardFileName: string;
- BaseKeyboardID: Cardinal;
FDestDeadkeyFileName: string;
FCommand: string;
begin
@@ -84,9 +81,6 @@ procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: strin
then FDestPath := GetPackageInstallPath(PackageName) // I3581
else FDestPath := GetKeyboardInstallPath(FileName); // I3581
- with Context as TKeymanContext do
- BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;
-
FBaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
FBaseFileName := FDestPath + '\' + ExtractFileName(FileName); // I3581
FDestFileName := ChangeFileExt(FBaseFileName, '') + '-'+FBaseKeyboardIDHex + '.kmx';
diff --git a/windows/src/engine/kmcomapi/util/internalinterfaces.pas b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
index 1759468e006..11093ac89a1 100644
--- a/windows/src/engine/kmcomapi/util/internalinterfaces.pas
+++ b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
@@ -67,7 +67,7 @@ interface
['{4876E6DF-C557-46E2-84F4-787BE5F55DDA}']
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
+ procedure UpdateBaseLayout(BaseKeyboardID: Cardinal); // I4169
procedure RefreshInstallation;
end;
From 2f4c428b13bbb5215745df9454b6f5c4a3beb851 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 29 Jul 2026 15:03:57 +1000
Subject: [PATCH 03/26] fix(windows): restore UpdateBaseLayout interface
The original change, changed the InKeymanKyboardInstalled
UpdateBaseLayout inteface and it didn't need to. This
change restores it.
---
.../com/keyboards/keymankeyboardinstalled.pas | 9 +++++++--
.../engine/kmcomapi/com/options/keymanoptions.pas | 2 +-
.../keyboard/kprecompilemnemonickeyboard.pas | 14 +++++++-------
.../engine/kmcomapi/util/internalinterfaces.pas | 2 +-
4 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
index 91ecaa9b5f8..52fd6984354 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -109,7 +109,7 @@ TKeymanKeyboardInstalled = class( // I3581
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
+ procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
public
@@ -151,15 +151,20 @@ procedure TKeymanKeyboardInstalled.Uninstall;
end;
end;
-procedure TKeymanKeyboardInstalled.UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
+procedure TKeymanKeyboardInstalled.UpdateBaseLayout; // I4169
+var
+ BaseKeyboardID: Integer;
begin
if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then // I4615
+ begin
+ BaseKeyboardID := (Context.Options as IKeymanOptions).Items['koBaseLayout'].Value;
with TKPRecompileMnemonicKeyboard.Create(Context) do
try
Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, BaseKeyboardID);
finally
Free;
end;
+ end;
end;
function TKeymanKeyboardInstalled.Get_Copyright: WideString;
diff --git a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
index 8635a748083..a60c5da0416 100644
--- a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
+++ b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
@@ -136,7 +136,7 @@ procedure TKeymanOptions.Apply;
FNewBaseLayout := Get_Items('koBaseLayout').Value;
if IsAdministrator and (FOldBaseLayout <> FNewBaseLayout) then
for I := 0 to Context.Keyboards.Count - 1 do // I4169
- (Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout(FNewBaseLayout);
+ (Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout;
Context.Control.AutoApplyKeyman;
end;
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
index 7a4d5a2b395..3d806afda2e 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -1,18 +1,18 @@
(*
Name: kprecompilemnemonickeyboard
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 24 Apr 2014
Modified Date: 13 Mar 2015
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 24 Apr 2014 - mcdurdin - I4174 - V9 - mcompile logs should be stored in diag folder
06 Feb 2015 - mcdurdin - I4552 - V9.0 - Add mnemonic recompile option to ignore deadkeys
13 Mar 2015 - mcdurdin - I4615 - CrashID:kmshell.exe_9.0.481.0_2C6795CE_EOleException
diff --git a/windows/src/engine/kmcomapi/util/internalinterfaces.pas b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
index 11093ac89a1..1759468e006 100644
--- a/windows/src/engine/kmcomapi/util/internalinterfaces.pas
+++ b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
@@ -67,7 +67,7 @@ interface
['{4876E6DF-C557-46E2-84F4-787BE5F55DDA}']
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout(BaseKeyboardID: Cardinal); // I4169
+ procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
end;
From 27970c671e4bc45c3b24da667d8824b071547fb0 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 3 Aug 2026 15:22:21 +1000
Subject: [PATCH 04/26] fix(windows): refresh UI after basekbd change
---
windows/src/desktop/kmshell/main/UfrmMain.pas | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index a556019abd2..4ee970cca57 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -666,8 +666,8 @@ procedure TfrmMain.Options_BaseKeyboard; // I4169
begin
if ConfigureBaseKeyboard(BaseKeyboardID) then
begin
- SetBaseKeyboard(Handle, BaseKeyboardID)
- // Refresh will be triggered by elevated process
+ SetBaseKeyboard(Handle, BaseKeyboardID);
+ DoRefresh;
end;
end;
From 62dd0de7868abe931d01428034fc43deabd8ba7f Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 21 Aug 2026 13:53:26 +1000
Subject: [PATCH 05/26] fix(windows): add compile for base keyoard to api
What we was needed was the ability to recompile
installed keyboards against a basekeyboard id.
MCompileForBaseKeyboard which will take the
base keyboard id. This allows the call to be done
elevated and seperates out the actuall selecting
the base keyboard.
---
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 97 +++++--------------
windows/src/desktop/kmshell/main/initprog.pas | 8 +-
.../com/keyboards/keymankeyboardinstalled.pas | 22 ++++-
.../kmcomapi/com/options/keymanoptions.pas | 24 -----
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 10 ++
windows/src/engine/kmcomapi/kmcomapi.ridl | 14 +++
6 files changed, 74 insertions(+), 101 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index b3f60a5067b..e9ce67d5e34 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -21,6 +21,7 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
+function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;
implementation
@@ -78,80 +79,12 @@ procedure TfrmBaseKeyboard.Footer_OK(params: TStringList);
function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
var
BaseKeyboardID: Integer;
- PreviousBaseKeyboardID: Integer;
- PreviousBaseKeyboardValue: string;
- PreviousBaseKeyboardValueExists: Boolean;
-
- procedure SavePreviousRegistryBaseKeyboardValue;
- var
- Reg: TRegistryErrorControlled;
- begin
- PreviousBaseKeyboardValueExists := False;
- PreviousBaseKeyboardValue := '';
-
- Reg := TRegistryErrorControlled.Create;
- try
- if Reg.OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and Reg.ValueExists(SRegValue_UnderlyingLayout) then
- begin
- PreviousBaseKeyboardValueExists := True;
- PreviousBaseKeyboardValue := Reg.ReadString(SRegValue_UnderlyingLayout);
- end;
- finally
- Reg.Free;
- end;
- end;
-
- procedure RestorePreviousBaseKeyboardValue;
- var
- Reg: TRegistryErrorControlled;
- begin
- Reg := TRegistryErrorControlled.Create;
- try
- if Reg.OpenKey(SRegKey_KeymanEngine_CU, True) then
- if PreviousBaseKeyboardValueExists then
- Reg.WriteString(SRegValue_UnderlyingLayout, PreviousBaseKeyboardValue)
- else if Reg.ValueExists(SRegValue_UnderlyingLayout) then
- Reg.DeleteValue(SRegValue_UnderlyingLayout);
- finally
- Reg.Free;
- end;
- end;
-
- procedure ForceBaseLayoutChange;
- var
- Reg: TRegistryErrorControlled;
- begin
- // This is hacky, maybe just remove the registry value, however that
- // would not force a recompile if the was the default base layout.
- // Options.Apply re-compiles only when it observes a changed base layout.
- // The caller may be repairing missing files for the already-selected layout.
- Reg := TRegistryErrorControlled.Create;
- try
- if Reg.OpenKey(SRegKey_KeymanEngine_CU, True) then
- Reg.WriteString(SRegValue_UnderlyingLayout, '00000000');
- finally
- Reg.Free;
- end;
- end;
-
begin
Result := False;
if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
not kmcom.SystemInfo.IsAdministrator then
Exit;
-
- SavePreviousRegistryBaseKeyboardValue;
- PreviousBaseKeyboardID := kmcom.Options['koBaseLayout'].Value;
- kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
- try
- if PreviousBaseKeyboardID = BaseKeyboardID then
- ForceBaseLayoutChange;
- kmcom.Options.Apply;
- Result := True;
- finally
- kmcom.Options['koBaseLayout'].Value := PreviousBaseKeyboardID;
- RestorePreviousBaseKeyboardValue;
- end;
+ Result := CompileForBaseKeyboard(BaseKeyboardID);
end;
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
@@ -180,13 +113,33 @@ function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolea
begin
MCompileResult := True;
Result := False;
- if BaseKeyboardNeedsMCompile(BaseKeyboardID) and not kmcom.SystemInfo.IsAdministrator then
- MCompileResult := WaitForElevatedConfiguration(WindowHandle, '-mcompile ' + IntToHex(BaseKeyboardID, 8)) = 0;
+ if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
+ begin
+ if not kmcom.SystemInfo.IsAdministrator then
+ begin
+ MCompileResult := WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8)) = 0;
+ end
+ else
+ MCompileResult := CompileForBaseKeyboard(BaseKeyboardID);
+ end;
if not MCompileResult then
Exit;
+
kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
- kmcom.Options.Apply; // This will trigger a recompile if needed
+ kmcom.Options.Apply;
Result := True;
end;
+function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;
+var
+ i: Integer;
+ kbd: IKeymanKeyboardInstalled;
+begin
+ for i := 0 to kmcom.Keyboards.Count - 1 do
+ begin
+ kbd := kmcom.Keyboards[i];
+ (kbd as IKeymanKeyboardInstalled2).MCompileForBaseKeyboard(BaseKeyboardID);
+ end;
+end;
+
end.
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 3444e7ce538..f9b5f9ac9b8 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -90,7 +90,7 @@ function Main(Owner: TComponent = nil): TModalResult;
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
- fmMCompile,
+ fmMCompileKbds,
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
@@ -263,9 +263,9 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 = '-mcompile' then
+ else if s = '-mcompilekbds' then
begin
- FMode := fmMCompile;
+ FMode := fmMCompileKbds;
Inc(i);
if i > ParamCount then Exit;
FQuery := ParamStr(i);
@@ -553,7 +553,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
then ExitCode := 0
else ExitCode := 1;
- fmMCompile:
+ fmMCompileKbds:
if MCompileBaseKeyboard(FQuery)
then ExitCode := 0
else ExitCode := 1;
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
index 52fd6984354..01b03ae3fc8 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -63,7 +63,8 @@ TKeymanKeyboardInstalled = class;
TKeymanKeyboardInstalled = class( // I3581
TKeymanKeyboard,
IIntKeymanKeyboardInstalled,
- IKeymanKeyboardInstalled)
+ IKeymanKeyboardInstalled,
+ IKeymanKeyboardInstalled2)
private
FRegKeyboard: TRegKeyboard;
FVisualKeyboard: IKeymanVisualKeyboard;
@@ -112,6 +113,9 @@ TKeymanKeyboardInstalled = class( // I3581
procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
+ { IKeymanKeyboardInstalled2 }
+ procedure MCompileForBaseKeyboard(KLID: Integer); safecall;
+
public
constructor Create(AContext: TKeymanContext; const Name: string);
destructor Destroy; override;
@@ -476,5 +480,21 @@ function TKeymanKeyboardInstalled.RegKeyboard: TRegKeyboard;
Result := FRegKeyboard;
end;
+{ IKeymanKeyboardInstalled2 }
+procedure TKeymanKeyboardInstalled.MCompileForBaseKeyboard(KLID: Integer); safecall;
+var
+ RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard;
+begin
+ if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then
+ begin
+ RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context);
+ try
+ RecompileMnemonicKeyboard.Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, KLID);
+ finally
+ RecompileMnemonicKeyboard.Free;
+ end;
+ end;
+end;
+
end.
diff --git a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
index a60c5da0416..1848428033c 100644
--- a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
+++ b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
@@ -112,32 +112,8 @@ function TKeymanOptions.IndexOf(const ID: WideString): Integer;
end;
procedure TKeymanOptions.Apply;
-var
- I: Integer;
- FOldBaseLayout: Integer;
- FNewBaseLayout: Integer;
begin
- with TRegistryErrorControlled.Create do // I3717
- try
- if OpenKey(SRegKey_KeymanEngine_CU, True) then
- begin
- if ValueExists(SRegValue_UnderlyingLayout)
- then FOldBaseLayout := StrToIntDef('$'+ReadString(SRegValue_UnderlyingLayout),0) // I3759
- else FOldBaseLayout := TBaseKeyboard.GetDefaultBaseLayoutID;
- end
- else
- FOldBaseLayout := TBaseKeyboard.GetDefaultBaseLayoutID;
- finally
- Free;
- end;
-
FInternalOptions.Save(Context);
-
- FNewBaseLayout := Get_Items('koBaseLayout').Value;
- if IsAdministrator and (FOldBaseLayout <> FNewBaseLayout) then
- for I := 0 to Context.Keyboards.Count - 1 do // I4169
- (Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout;
-
Context.Control.AutoApplyKeyman;
end;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 3ceb5b15cd7..786ce6c9b2d 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,6 +1569,16 @@ interface
procedure RefreshInstalledKeyboards; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardInstalled2
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
+// *********************************************************************//
+ IKeymanKeyboardInstalled2 = interface(IKeymanKeyboardInstalled)
+ ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
+ procedure MCompileForBaseKeyboard(KLID: Integer); safecall;
+ end;
+
// *********************************************************************//
// DispIntf: IKeymanKeyboardsInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index ac20310a871..9eb63fbd68d 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -60,6 +60,7 @@ library keymanapi
interface IKeymanKeyboardLanguagesInstalled;
interface IKeymanKeyboardLanguagesFile;
interface IKeymanKeyboardsInstalled2;
+ interface IKeymanKeyboardInstalled2;
interface IKeymanPackagesInstalled2;
interface IKeymanKeyboardFile2;
interface IKeymanPackageFile2;
@@ -936,6 +937,19 @@ library keymanapi
HRESULT _stdcall RefreshInstalledKeyboards(void);
};
+ [
+ uuid(3086C85C-932A-4726-BF76-2D74DD133AC9),
+ version(19.0),
+ helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardInstalled2: IKeymanKeyboardInstalled
+ {
+ [id(0x00000120)]
+ HRESULT _stdcall MCompileForBaseKeyboard(long KLID);
+ };
+
[
uuid(F23B9848-2AEF-4A2B-BC3A-292E3A00D691),
version(14.0),
From 82fb40002b980a243edd7a9c647f7d3ca585c422 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 31 Aug 2026 15:34:45 +1000
Subject: [PATCH 06/26] fix(windows): pass basekeyboardid to installation api
The updates all the apis so that the basekeyboardid or klid
can be passed in as an argument. This in needed so that
elevated process required to compile the keyboard has
the call users keyboard base id.
---
.../Keyman.Configuration.UI.InstallFile.pas | 30 +++++-----
...Configuration.UI.KeymanProtocolHandler.pas | 12 ++--
.../kmshell/install/UfrmInstallKeyboard.pas | 17 ++++--
.../install/UfrmInstallKeyboardFromWeb.pas | 6 +-
windows/src/desktop/kmshell/main/initprog.pas | 15 ++---
.../com/keyboards/keymankeyboardfile.pas | 23 +++++++-
.../keyboards/keymankeyboardsinstalled.pas | 22 ++++++-
.../com/packages/keymanpackagefile.pas | 43 ++++++++++----
.../com/packages/keymanpackagesinstalled.pas | 30 +++++++++-
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 42 ++++++++++++++
windows/src/engine/kmcomapi/kmcomapi.ridl | 58 +++++++++++++++++++
.../processes/keyboard/kpinstallkeyboard.pas | 23 +++++---
.../processes/package/kpinstallpackage.pas | 12 ++--
13 files changed, 264 insertions(+), 69 deletions(-)
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 c6ee3564ae7..3cc8dcc9016 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 @@ TInstallFile = class sealed
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 @@ implementation
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 @@ class function TInstallFile.Execute(Owner: TComponent; const FileName: string; A
begin
if ASilent then
begin
- InstallKeyboard(LogFile, BCP47);
+ InstallKeyboard(LogFile, BCP47, BaseKeyboardID);
Result := True;
end
else
@@ -139,7 +140,7 @@ class function TInstallFile.Execute(Owner: TComponent; const FileName: string; A
/// 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 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
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 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
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 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean;
var
dlgOpen: TOpenDialog;
+ BaseKeyboardID : Integer;
begin
dlgOpen := TOpenDialog.Create(nil);
try
@@ -216,9 +218,9 @@ class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent):
'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 6f13f6777bd..60ac8ae43c5 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 @@ TKeymanProtocolHandler = class sealed
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 @@ class function TKeymanProtocolHandler.CanHandle(const url: string): Boolean;
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 @@ class function TKeymanProtocolHandler.Handle(Owner: TComponent;
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 @@ function TKeymanProtocolHandler.DoHandle(Owner: TComponent;
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 6d79811a80a..775aa1ca2eb 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
@@ -74,6 +74,7 @@ interface
Vcl.StdCtrls,
keymanapi_TLB,
+ KeymanOptionNames,
UfrmKeymanBase,
UfrmWebContainer;
@@ -102,7 +103,7 @@ TfrmInstallKeyboard = class(TfrmWebContainer)
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 @@ procedure TfrmInstallKeyboard.DeleteFileReferences;
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 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
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 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
var
t: TTempFile;
ExecParams: string;
+ BaseKeyboardString :string;
begin
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
@@ -306,8 +310,9 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
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 @@ procedure TfrmInstallKeyboard.CheckLogFileForWarnings(const Filename: string; Si
------------------------------------------------------------------------------}
// 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 @@ procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string);
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 @@ procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string);
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 aff32510372..ed236d489d6 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
@@ -87,6 +87,7 @@ implementation
Keyman.Configuration.UI.InstallFile,
Keyman.System.LocaleStrings,
kmint,
+ KeymanOptionNames,
MessageIdentifierConsts,
Upload_Settings,
utilfiletypes,
@@ -213,6 +214,7 @@ procedure TfrmInstallKeyboardFromWeb.cefBeforeBrowseEx(Sender: TObject; const Ur
procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string);
var
FTempDir: string;
+ BaseKeyboardID: Integer;
begin
FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679
try
@@ -230,8 +232,8 @@ procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID,
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 f9b5f9ac9b8..0f0cc6f3671 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -206,7 +206,7 @@ function Show_frmHTML(AParent: TComponent; const ACaption, AText, AFileName: str
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 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 @@ procedure RegisterControlClasses;
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 @@ procedure Run;
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID: Integer;
+ FDefaultLangID, FBaseKeyboard: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -349,7 +350,7 @@ procedure Run;
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 @@ procedure Run;
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 @@ function DoCheckTIPInstallStatus(FSilent: Boolean): Boolean;
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 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
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 5ea1e74265c..b7255869b7b 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
@@ -37,7 +37,7 @@ interface
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 @@ TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeybo
{ 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 @@ function TKeymanKeyboardFile.Install2(Force: WordBool): IKeymanKeyboardInstalled
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 f5f8b744483..b37e0dfce0e 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
@@ -37,7 +37,8 @@ interface
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 @@ TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboard
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 14b207e2299..28ef2d064a4 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 @@ interface
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 @@ TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFi
{ 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 @@ procedure TKeymanPackageFile.Install(Force: WordBool);
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(FFileName, o);
+ Execute(FFileName, o, 0);
finally
Free;
end;
@@ -191,7 +192,27 @@ function TKeymanPackageFile.Install2(Force: WordBool): IKeymanPackageInstalled;
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 @@ procedure TKeymanPackageFile.LoadPackage;
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 9dd9f1a52ad..821a38bdc5f 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
@@ -38,7 +38,8 @@ TPackageList = class(TAutoObjectList)
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 @@ TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, IKeymanPackagesI
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 @@ procedure TKeymanPackagesInstalled.Install(const Filename: WideString; Force: Wo
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(Filename, o);
+ Execute(Filename, o, 0);
finally
Free;
end;
@@ -136,7 +138,29 @@ function TKeymanPackagesInstalled.Install2(const Filename: WideString;
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 786ce6c9b2d..7246c9173f7 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,6 +1569,17 @@ interface
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 @@ interface
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 @@ interface
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 @@ interface
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 9eb63fbd68d..91f49822b52 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 1df237b0c60..6d3bd1f3ed8 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -64,7 +64,7 @@ interface
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 @@ implementation
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 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
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 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
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 98edfbf3fb1..4ab33cdfeec 100644
--- a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
+++ b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
@@ -50,7 +50,7 @@ interface
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 @@ implementation
{ 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 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
FErrorValue: Cardinal;
FSrcFileName: string;
- procedure InstallKeyboard(FileName: string);
+ procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer);
var
FOptions: TKPInstallKeyboardOptions;
kbd: TPackageKeyboard;
@@ -132,7 +132,7 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
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 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
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;
From 155b8e15edab819bde11b564423a950366a05812 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Tue, 1 Sep 2026 15:53:48 +1000
Subject: [PATCH 07/26] fix(windows): strtoint for command line basekeyboardid
Also rebuild kmcomapi_TLB.pas
---
windows/src/desktop/kmshell/main/initprog.pas | 2 +-
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 249 ++++++++++++++----
windows/src/engine/kmcomapi/kmcomapi.ridl | 98 ++++---
3 files changed, 246 insertions(+), 103 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 0f0cc6f3671..b1afe4e10f7 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -263,7 +263,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 = 'bkd' then begin Inc(i); FBaseKeyboard := StrToInt('$' + ParamStr(i)); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 7246c9173f7..3c436dc5d98 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@
// ************************************************************************ //
// $Rev: 52393 $
-// File generated on 16/09/2021 6:54:44 PM from Type Library described below.
+// File generated on 31/08/2026 5:28:13 PM from Type Library described below.
// ************************************************************************ //
// Type Lib: C:\Projects\keyman\app\windows\src\engine\kmcomapi\kmcomapi (1)
@@ -87,11 +87,16 @@ interface
IID_IKeymanKeyboardLanguagesInstalled: TGUID = '{7DC22BC0-85BB-45C0-8EDB-A2F4BD1D500B}';
IID_IKeymanKeyboardLanguagesFile: TGUID = '{5F90BCDA-F1C1-433A-8FD0-B498299D3C30}';
IID_IKeymanKeyboardsInstalled2: TGUID = '{EA57C94F-C140-485E-941A-3F1D5A229024}';
+ IID_IKeymanKeyboardInstalled2: TGUID = '{3086C85C-932A-4726-BF76-2D74DD133AC9}';
IID_IKeymanPackagesInstalled2: TGUID = '{F23B9848-2AEF-4A2B-BC3A-292E3A00D691}';
IID_IKeymanKeyboardFile2: TGUID = '{EDE4326B-51F4-42D5-8251-B20B71993EC8}';
IID_IKeymanPackageFile2: TGUID = '{9B43B6BC-C622-47EF-915E-6780CF53BAAA}';
IID_IKeymanKeyboardLanguageInstalled2: TGUID = '{414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E}';
IID_IKeymanKeyboardLanguagesInstalled2: TGUID = '{628FF2E6-B490-462E-8FC7-7AE53B9D392C}';
+ IID_IKeymanKeyboardFile3: TGUID = '{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}';
+ IID_IKeymanPackageFile3: TGUID = '{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}';
+ IID_IKeymanKeyboardsInstalled3: TGUID = '{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}';
+ IID_IKeymanPackagesInstalled3: TGUID = '{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}';
CLASS_Keyman: TGUID = '{CF46549D-4D2D-4679-A2E1-23A815F172F8}';
IID_IKeymanDefaultLanguage: TGUID = '{77BAB934-B7DF-4304-AFA6-B8F6BEC16516}';
@@ -248,6 +253,8 @@ interface
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
+ IKeymanKeyboardInstalled2 = interface;
+ IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -258,6 +265,14 @@ interface
IKeymanKeyboardLanguageInstalled2Disp = dispinterface;
IKeymanKeyboardLanguagesInstalled2 = interface;
IKeymanKeyboardLanguagesInstalled2Disp = dispinterface;
+ IKeymanKeyboardFile3 = interface;
+ IKeymanKeyboardFile3Disp = dispinterface;
+ IKeymanPackageFile3 = interface;
+ IKeymanPackageFile3Disp = dispinterface;
+ IKeymanKeyboardsInstalled3 = interface;
+ IKeymanKeyboardsInstalled3Disp = dispinterface;
+ IKeymanPackagesInstalled3 = interface;
+ IKeymanPackagesInstalled3Disp = dispinterface;
IKeymanDefaultLanguage = interface;
IKeymanDefaultLanguageDisp = dispinterface;
@@ -1570,14 +1585,24 @@ interface
end;
// *********************************************************************//
-// Interface: IKeymanKeyboardsInstalled3
+// DispIntf: IKeymanKeyboardsInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
+// GUID: {EA57C94F-C140-485E-941A-3F1D5A229024}
// *********************************************************************//
- IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
- ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
- function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
- procedure RefreshInstalledKeyboards; safecall;
+ IKeymanKeyboardsInstalled2Disp = dispinterface
+ ['{EA57C94F-C140-485E-941A-3F1D5A229024}']
+ function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; dispid 19;
+ procedure RefreshInstalledKeyboards; dispid 601;
+ property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
+ function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
+ procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
+ procedure Apply; dispid 18;
+ function IndexOf(const ID: WideString): Integer; dispid 5;
+ property Count: Integer readonly dispid 1;
+ property _NewEnum: IUnknown readonly dispid -4;
+ procedure Refresh; dispid 2;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
end;
// *********************************************************************//
@@ -1591,22 +1616,36 @@ interface
end;
// *********************************************************************//
-// DispIntf: IKeymanKeyboardsInstalled2Disp
+// DispIntf: IKeymanKeyboardInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {EA57C94F-C140-485E-941A-3F1D5A229024}
+// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
// *********************************************************************//
- IKeymanKeyboardsInstalled2Disp = dispinterface
- ['{EA57C94F-C140-485E-941A-3F1D5A229024}']
- function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; dispid 19;
- procedure RefreshInstalledKeyboards; dispid 601;
- property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
- function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
- procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
- procedure Apply; dispid 18;
- function IndexOf(const ID: WideString): Integer; dispid 5;
- property Count: Integer readonly dispid 1;
- property _NewEnum: IUnknown readonly dispid -4;
- procedure Refresh; dispid 2;
+ IKeymanKeyboardInstalled2Disp = dispinterface
+ ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
+ procedure MCompileForBaseKeyboard(KLID: Integer); dispid 288;
+ property IconFilename: WideString readonly dispid 257;
+ procedure InstallVisualKeyboard(const Filename: WideString); dispid 258;
+ property KeymanID: Integer readonly dispid 259;
+ property Languages: IKeymanKeyboardLanguagesInstalled readonly dispid 260;
+ property Loaded: WordBool dispid 261;
+ property Options: IKeymanKeyboardOptions readonly dispid 262;
+ property OwnerPackage: IKeymanPackageInstalled readonly dispid 263;
+ property VisualKeyboard: IKeymanVisualKeyboard readonly dispid 264;
+ procedure Uninstall; dispid 265;
+ property Bitmap: IPicture readonly dispid 1;
+ property Copyright: WideString readonly dispid 2;
+ property DefaultBCP47Languages: WideString readonly dispid 3;
+ property DefaultPrimaryLanguage: Integer readonly dispid 4;
+ property DefaultWindowsLanguages: WideString readonly dispid 5;
+ property DefaultHotkey: IKeymanHotkey readonly dispid 6;
+ property Encodings: KeymanKeyboardEncodings readonly dispid 7;
+ property Filename: WideString readonly dispid 8;
+ function GetCharsUsed: WideString; dispid 9;
+ property ID: WideString readonly dispid 10;
+ property LayoutType: KeymanKeyboardLayoutType readonly dispid 11;
+ property Message: WideString readonly dispid 12;
+ property Name: WideString readonly dispid 13;
+ property Version: WideString readonly dispid 14;
function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
out References: OleVariant): WideString; dispid 401;
end;
@@ -1621,16 +1660,6 @@ interface
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
@@ -1660,16 +1689,6 @@ interface
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
@@ -1708,17 +1727,6 @@ interface
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
@@ -1820,6 +1828,143 @@ interface
out References: OleVariant): WideString; dispid 401;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardFile3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}
+// *********************************************************************//
+ IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
+ ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
+ end;
+
+// *********************************************************************//
+// DispIntf: IKeymanKeyboardFile3Disp
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}
+// *********************************************************************//
+ IKeymanKeyboardFile3Disp = dispinterface
+ ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; dispid 289;
+ procedure Install(Force: WordBool); dispid 256;
+ property Languages: IKeymanKeyboardLanguagesFile readonly dispid 402;
+ property Bitmap: IPicture readonly dispid 1;
+ property Copyright: WideString readonly dispid 2;
+ property DefaultBCP47Languages: WideString readonly dispid 3;
+ property DefaultPrimaryLanguage: Integer readonly dispid 4;
+ property DefaultWindowsLanguages: WideString readonly dispid 5;
+ property DefaultHotkey: IKeymanHotkey readonly dispid 6;
+ property Encodings: KeymanKeyboardEncodings readonly dispid 7;
+ property Filename: WideString readonly dispid 8;
+ function GetCharsUsed: WideString; dispid 9;
+ property ID: WideString readonly dispid 10;
+ property LayoutType: KeymanKeyboardLayoutType readonly dispid 11;
+ property Message: WideString readonly dispid 12;
+ property Name: WideString readonly dispid 13;
+ property Version: WideString readonly dispid 14;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
+ 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): IKeymanPackageFile; safecall;
+ end;
+
+// *********************************************************************//
+// DispIntf: IKeymanPackageFile3Disp
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
+// *********************************************************************//
+ IKeymanPackageFile3Disp = dispinterface
+ ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; dispid 292;
+ procedure Install(Force: WordBool); dispid 256;
+ property Author: WideString readonly dispid 1;
+ property AuthorEmail: WideString readonly dispid 2;
+ property Copyright: WideString readonly dispid 3;
+ property Filename: WideString readonly dispid 4;
+ property Files: IKeymanPackageContentFiles readonly dispid 5;
+ property Fonts: IKeymanPackageContentFonts readonly dispid 6;
+ property Graphic: IPicture readonly dispid 7;
+ property GraphicFile: IKeymanPackageContentFile readonly dispid 8;
+ property ID: WideString readonly dispid 9;
+ property KeyboardOptionsFile: IKeymanPackageContentFile readonly dispid 10;
+ property Keyboards: IKeymanPackageContentKeyboards readonly dispid 11;
+ property Name: WideString readonly dispid 12;
+ property ReadmeFile: IKeymanPackageContentFile readonly dispid 13;
+ property UsageFile: IKeymanPackageContentFile readonly dispid 14;
+ property Version: WideString readonly dispid 15;
+ property WelcomeFile: IKeymanPackageContentFile readonly dispid 16;
+ property Website: WideString readonly dispid 17;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
+ 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; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
+ end;
+
+// *********************************************************************//
+// DispIntf: IKeymanKeyboardsInstalled3Disp
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
+// *********************************************************************//
+ IKeymanKeyboardsInstalled3Disp = dispinterface
+ ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
+ function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; dispid 290;
+ property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
+ function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
+ procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
+ procedure Apply; dispid 18;
+ function IndexOf(const ID: WideString): Integer; dispid 5;
+ property Count: Integer readonly dispid 1;
+ property _NewEnum: IUnknown readonly dispid -4;
+ procedure Refresh; dispid 2;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
+ 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; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
+ end;
+
+// *********************************************************************//
+// DispIntf: IKeymanPackagesInstalled3Disp
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
+// *********************************************************************//
+ IKeymanPackagesInstalled3Disp = dispinterface
+ ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
+ function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; dispid 291;
+ property Items[Index: OleVariant]: IKeymanPackageInstalled readonly dispid 0; default;
+ function GetPackageFromFile(const Filename: WideString): IKeymanPackageFile; dispid 16;
+ procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
+ function IndexOf(const ID: WideString): Integer; dispid 18;
+ property Count: Integer readonly dispid 1;
+ property _NewEnum: IUnknown readonly dispid -4;
+ procedure Refresh; dispid 2;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
+ end;
+
// *********************************************************************//
// Interface: IKeymanDefaultLanguage
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index 91f49822b52..ecfff3d7074 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -6,7 +6,7 @@
// However, when applying changes via the Editor this file will be regenerated
// and comments or formatting changes will be lost.
// ************************************************************************ //
-// File generated on 16/09/2021 6:54:45 PM (- $Rev: 12980 $, 32940875).
+// File generated on 31/08/2026 5:28:15 PM (- $Rev: 12980 $, 11059984).
[
uuid(F16E2A9A-DA46-4EA3-BFF3-BA46B480C961),
@@ -980,6 +980,51 @@ library keymanapi
HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
+ [
+ uuid(9B43B6BC-C622-47EF-915E-6780CF53BAAA),
+ version(14.0),
+ helpstring("https://help.keyman.com/developer/engine/desktop/14.0/api/IKeymanPackageFile2"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanPackageFile2: IKeymanPackageFile
+ {
+ [id(0x00000101)]
+ HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanPackageInstalled** PackageResult);
+ };
+
+ [
+ uuid(414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E),
+ version(14.0),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardLanguageInstalled2: IKeymanKeyboardLanguageInstalled
+ {
+ [id(0x00000194)]
+ HRESULT _stdcall FindInstallationLangID([out] long* LangID, [out] BSTR* TemporaryKeyboardID, [out] VARIANT_BOOL* RegistrationRequired, [in] enum tagKeymanInstallFlags Flags, [out, retval] VARIANT_BOOL* Result);
+ [id(0x00000195)]
+ HRESULT _stdcall RegisterTip([in] long LangID);
+ [id(0x00000196)]
+ HRESULT _stdcall InstallTip([in] long LangID, [in] BSTR TemporaryKeyboardToRemove);
+ [propget, id(0x000001F5)]
+ HRESULT _stdcall IsRegistered([out, retval] VARIANT_BOOL* Value);
+ [propget, id(0x000001F6)]
+ HRESULT _stdcall WindowsBCP47Code([out, retval] BSTR* Value);
+ };
+
+ [
+ uuid(628FF2E6-B490-462E-8FC7-7AE53B9D392C),
+ version(14.0),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardLanguagesInstalled2: IKeymanKeyboardLanguagesInstalled
+ {
+ [id(0x00000259)]
+ HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
+ };
+
[
uuid(8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4),
version(19.0),
@@ -1000,18 +1045,16 @@ library keymanapi
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"),
+ helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2\x03"),
dual,
oleautomation
]
@@ -1034,51 +1077,6 @@ library keymanapi
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),
- helpstring("https://help.keyman.com/developer/engine/desktop/14.0/api/IKeymanPackageFile2"),
- dual,
- oleautomation
- ]
- interface IKeymanPackageFile2: IKeymanPackageFile
- {
- [id(0x00000101)]
- HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanPackageInstalled** PackageResult);
- };
-
- [
- uuid(414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E),
- version(14.0),
- dual,
- oleautomation
- ]
- interface IKeymanKeyboardLanguageInstalled2: IKeymanKeyboardLanguageInstalled
- {
- [id(0x00000194)]
- HRESULT _stdcall FindInstallationLangID([out] long* LangID, [out] BSTR* TemporaryKeyboardID, [out] VARIANT_BOOL* RegistrationRequired, [in] enum tagKeymanInstallFlags Flags, [out, retval] VARIANT_BOOL* Result);
- [id(0x00000195)]
- HRESULT _stdcall RegisterTip([in] long LangID);
- [id(0x00000196)]
- HRESULT _stdcall InstallTip([in] long LangID, [in] BSTR TemporaryKeyboardToRemove);
- [propget, id(0x000001F5)]
- HRESULT _stdcall IsRegistered([out, retval] VARIANT_BOOL* Value);
- [propget, id(0x000001F6)]
- HRESULT _stdcall WindowsBCP47Code([out, retval] BSTR* Value);
- };
-
- [
- uuid(628FF2E6-B490-462E-8FC7-7AE53B9D392C),
- version(14.0),
- dual,
- oleautomation
- ]
- interface IKeymanKeyboardLanguagesInstalled2: IKeymanKeyboardLanguagesInstalled
- {
- [id(0x00000259)]
- HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
- };
-
[
uuid(CA3B3B00-EA42-4EED-9043-D1A1F1842D52),
dual,
From 0c68b1e0314086b94deb9ed0a5bf6e2697196ab6 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 2 Sep 2026 10:10:16 +1000
Subject: [PATCH 08/26] fix(windows): typos and return type in interface
declaration
---
windows/src/desktop/kmshell/main/initprog.pas | 2 +-
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 4 ++--
windows/src/engine/kmcomapi/kmcomapi.ridl | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index b1afe4e10f7..f4d2a4161d5 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -263,7 +263,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 := StrToInt('$' + ParamStr(i)); end
+ else if s = '-bkd' then begin Inc(i); FBaseKeyboard := StrToInt('$' + ParamStr(i)); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 3c436dc5d98..b0530cb94a0 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1873,7 +1873,7 @@ interface
// *********************************************************************//
IKeymanPackageFile3 = interface(IKeymanPackageFile)
['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; safecall;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
end;
// *********************************************************************//
@@ -1883,7 +1883,7 @@ interface
// *********************************************************************//
IKeymanPackageFile3Disp = dispinterface
['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; dispid 292;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; dispid 292;
procedure Install(Force: WordBool); dispid 256;
property Author: WideString readonly dispid 1;
property AuthorEmail: WideString readonly dispid 2;
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index ecfff3d7074..0b2366c144f 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -1048,7 +1048,7 @@ library keymanapi
interface IKeymanPackageFile3: IKeymanPackageFile
{
[id(0x00000124)]
- HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageFile** Package);
+ HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageInstalled** PackageResult);
};
[
From 3c1b47eedc2bc9d8422fee659fddbdd2edbf4432 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 2 Sep 2026 12:37:03 +1000
Subject: [PATCH 09/26] fix(windows): Free the correct object
---
.../engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
index 6d3bd1f3ed8..1d198264cb9 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -262,7 +262,7 @@ procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: st
else
RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
- Free;
+ RecompileMnemonicKeyboard.Free;
end;
end;
finally
From 8e77a5779a992f970b2a8f59caa0980b2c7f4af2 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 2 Sep 2026 17:54:26 +1000
Subject: [PATCH 10/26] fix(windows): CompileForBaseKeyboard doesn't return
a value
---
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index e9ce67d5e34..1f136871e67 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -21,7 +21,7 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
-function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;
+procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
implementation
@@ -84,7 +84,9 @@ function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
not kmcom.SystemInfo.IsAdministrator then
Exit;
- Result := CompileForBaseKeyboard(BaseKeyboardID);
+ CompileForBaseKeyboard(BaseKeyboardID);
+ // TODO: sort out whether we need todo return a result
+ Result := True;
end;
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
@@ -108,29 +110,24 @@ function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
end;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
-var
- MCompileResult: Boolean;
begin
- MCompileResult := True;
Result := False;
if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
begin
if not kmcom.SystemInfo.IsAdministrator then
begin
- MCompileResult := WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8)) = 0;
+ WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
end
else
- MCompileResult := CompileForBaseKeyboard(BaseKeyboardID);
+ CompileForBaseKeyboard(BaseKeyboardID);
end;
- if not MCompileResult then
- Exit;
kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
kmcom.Options.Apply;
Result := True;
end;
-function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;
+procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
From 314dea4bacf1dbbedbeaa2064984e0ea6a583bef Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 3 Sep 2026 16:17:21 +1000
Subject: [PATCH 11/26] fix(windows): move non ui function from
ufrmbasekeyboard
---
windows/src/desktop/kmshell/kmshell.dpr | 3 +-
windows/src/desktop/kmshell/kmshell.dproj | 13 +--
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 65 ---------------
windows/src/desktop/kmshell/main/UfrmMain.pas | 1 +
windows/src/desktop/kmshell/main/initprog.pas | 1 +
...an.Configuration.Settings.BaseKeyboard.pas | 83 +++++++++++++++++++
6 files changed, 94 insertions(+), 72 deletions(-)
create mode 100644 windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas
diff --git a/windows/src/desktop/kmshell/kmshell.dpr b/windows/src/desktop/kmshell/kmshell.dpr
index e2d28b88d2b..e4ce8316d31 100644
--- a/windows/src/desktop/kmshell/kmshell.dpr
+++ b/windows/src/desktop/kmshell/kmshell.dpr
@@ -183,7 +183,8 @@ uses
Keyman.System.DownloadUpdate in 'main\Keyman.System.DownloadUpdate.pas',
Keyman.System.ExecutionHistory in '..\..\..\..\common\windows\delphi\general\Keyman.System.ExecutionHistory.pas',
Keyman.Configuration.UI.UfrmStartInstall in 'main\Keyman.Configuration.UI.UfrmStartInstall.pas' {frmStartInstall},
- Keyman.Configuration.Util.NetworkConnection in 'util\Keyman.Configuration.Util.NetworkConnection.pas';
+ Keyman.Configuration.Util.NetworkConnection in 'util\Keyman.Configuration.Util.NetworkConnection.pas',
+ Keyman.Configuration.Settings.BaseKeyboard in 'settings\Keyman.Configuration.Settings.BaseKeyboard.pas';
{$R VERSION.RES}
{$R manifest.res}
diff --git a/windows/src/desktop/kmshell/kmshell.dproj b/windows/src/desktop/kmshell/kmshell.dproj
index 371ce4cd495..ca611b40e44 100644
--- a/windows/src/desktop/kmshell/kmshell.dproj
+++ b/windows/src/desktop/kmshell/kmshell.dproj
@@ -358,6 +358,7 @@
+
Cfg_2
@@ -419,21 +420,21 @@
False
-
+
- .\
+ kmshell.exe
true
-
+
- kmshell.rsm
+ .\
true
-
+
- kmshell.exe
+ kmshell.rsm
true
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 1f136871e67..56e7c442b4f 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -19,9 +19,6 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
end;
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
-function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
-function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
-procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
implementation
@@ -76,67 +73,5 @@ procedure TfrmBaseKeyboard.Footer_OK(params: TStringList);
ModalResult := mrOk;
end;
-function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
-var
- BaseKeyboardID: Integer;
-begin
- Result := False;
- if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
- not kmcom.SystemInfo.IsAdministrator then
- Exit;
- CompileForBaseKeyboard(BaseKeyboardID);
- // TODO: sort out whether we need todo return a result
- Result := True;
-end;
-
-function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
-var
- I: Integer;
- Keyboard: IKeymanKeyboardInstalled;
- BaseFileName: string;
- BaseKeyboardIDHex: string;
-begin
- BaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
- for I := 0 to kmcom.Keyboards.Count - 1 do
- begin
- Keyboard := kmcom.Keyboards.Items[I];
- BaseFileName := Keyboard.Filename;
- if FileExists(BaseFileName) and
- (not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx') or
- not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx')) then
- Exit(True);
- end;
- Result := False;
-end;
-
-function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
-begin
- Result := False;
- if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
- begin
- if not kmcom.SystemInfo.IsAdministrator then
- begin
- WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
- end
- else
- CompileForBaseKeyboard(BaseKeyboardID);
- end;
-
- kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
- kmcom.Options.Apply;
- Result := True;
-end;
-
-procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
-var
- i: Integer;
- kbd: IKeymanKeyboardInstalled;
-begin
- for i := 0 to kmcom.Keyboards.Count - 1 do
- begin
- kbd := kmcom.Keyboards[i];
- (kbd as IKeymanKeyboardInstalled2).MCompileForBaseKeyboard(BaseKeyboardID);
- end;
-end;
end.
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index 100fd24fd2f..599566b91cb 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -174,6 +174,7 @@ implementation
Hints,
HotkeyUtils,
initprog,
+ Keyman.Configuration.Settings.BaseKeyboard,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.UI.UfrmDiagnosticTests,
KeymanOptionNames,
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index f4d2a4161d5..2d6cc1e6d2f 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -115,6 +115,7 @@ implementation
GetOsVersion,
help,
HTMLHelpViewer,
+ Keyman.Configuration.Settings.BaseKeyboard,
Keyman.Configuration.UI.InstallFile,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.System.UImportOlderVersionKeyboards11To13,
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas b/windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas
new file mode 100644
index 00000000000..44488179c9d
--- /dev/null
+++ b/windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas
@@ -0,0 +1,83 @@
+unit Keyman.Configuration.Settings.BaseKeyboard;
+
+interface
+
+uses
+ Winapi.Windows,
+ System.SysUtils,
+ keymanapi_TLB;
+
+function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
+function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
+procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
+
+implementation
+
+uses
+ kmint,
+ utilkmshell;
+
+function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
+var
+ I: Integer;
+ Keyboard: IKeymanKeyboardInstalled;
+ BaseFileName: string;
+ BaseKeyboardIDHex: string;
+begin
+ BaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
+ for I := 0 to kmcom.Keyboards.Count - 1 do
+ begin
+ Keyboard := kmcom.Keyboards.Items[I];
+ BaseFileName := Keyboard.Filename;
+ if FileExists(BaseFileName) and
+ (not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx') or
+ not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx')) then
+ Exit(True);
+ end;
+ Result := False;
+end;
+
+function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
+begin
+ Result := False;
+ if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
+ begin
+ if not kmcom.SystemInfo.IsAdministrator then
+ begin
+ WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
+ end
+ else
+ CompileForBaseKeyboard(BaseKeyboardID);
+ end;
+
+ kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
+ kmcom.Options.Apply;
+ Result := True;
+end;
+
+function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
+var
+ BaseKeyboardID: Integer;
+begin
+ Result := False;
+ if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
+ not kmcom.SystemInfo.IsAdministrator then
+ Exit;
+ CompileForBaseKeyboard(BaseKeyboardID);
+ // TODO: sort out whether we need todo return a result
+ Result := True;
+end;
+
+procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
+var
+ i: Integer;
+ kbd: IKeymanKeyboardInstalled;
+begin
+ for i := 0 to kmcom.Keyboards.Count - 1 do
+ begin
+ kbd := kmcom.Keyboards[i];
+ (kbd as IKeymanKeyboardInstalled2).MCompileForBaseKeyboard(BaseKeyboardID);
+ end;
+end;
+
+end.
From c3160944e5f2cb2277d6580a9c931883277cbf3d Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 3 Sep 2026 17:29:04 +1000
Subject: [PATCH 12/26] chore(windows): Revert "fix(windows): typos and return
type in interface declaration"
This reverts commit 0c68b1e0314086b94deb9ed0a5bf6e2697196ab6.
---
windows/src/desktop/kmshell/main/initprog.pas | 2 +-
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 4 ++--
windows/src/engine/kmcomapi/kmcomapi.ridl | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 2d6cc1e6d2f..6457542bcac 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -264,7 +264,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 := StrToInt('$' + ParamStr(i)); end
+ else if s = 'bkd' then begin Inc(i); FBaseKeyboard := StrToInt('$' + ParamStr(i)); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index b0530cb94a0..3c436dc5d98 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1873,7 +1873,7 @@ interface
// *********************************************************************//
IKeymanPackageFile3 = interface(IKeymanPackageFile)
['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; safecall;
end;
// *********************************************************************//
@@ -1883,7 +1883,7 @@ interface
// *********************************************************************//
IKeymanPackageFile3Disp = dispinterface
['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; dispid 292;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; dispid 292;
procedure Install(Force: WordBool); dispid 256;
property Author: WideString readonly dispid 1;
property AuthorEmail: WideString readonly dispid 2;
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index 0b2366c144f..ecfff3d7074 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -1048,7 +1048,7 @@ library keymanapi
interface IKeymanPackageFile3: IKeymanPackageFile
{
[id(0x00000124)]
- HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageInstalled** PackageResult);
+ HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageFile** Package);
};
[
From 5e89946c004c0e1f6b83a2109d26d2e06bddd39e Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 3 Sep 2026 17:29:51 +1000
Subject: [PATCH 13/26] chore(windows): Revert "fix(windows): strtoint for
command line basekeyboardid"
This reverts commit 155b8e15edab819bde11b564423a950366a05812.
---
windows/src/desktop/kmshell/main/initprog.pas | 2 +-
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 249 ++++--------------
windows/src/engine/kmcomapi/kmcomapi.ridl | 98 +++----
3 files changed, 103 insertions(+), 246 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 6457542bcac..3143d728288 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -264,7 +264,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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 := StrToInt('$' + ParamStr(i)); end
+ else if s = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 3c436dc5d98..7246c9173f7 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@
// ************************************************************************ //
// $Rev: 52393 $
-// File generated on 31/08/2026 5:28:13 PM from Type Library described below.
+// File generated on 16/09/2021 6:54:44 PM from Type Library described below.
// ************************************************************************ //
// Type Lib: C:\Projects\keyman\app\windows\src\engine\kmcomapi\kmcomapi (1)
@@ -87,16 +87,11 @@ interface
IID_IKeymanKeyboardLanguagesInstalled: TGUID = '{7DC22BC0-85BB-45C0-8EDB-A2F4BD1D500B}';
IID_IKeymanKeyboardLanguagesFile: TGUID = '{5F90BCDA-F1C1-433A-8FD0-B498299D3C30}';
IID_IKeymanKeyboardsInstalled2: TGUID = '{EA57C94F-C140-485E-941A-3F1D5A229024}';
- IID_IKeymanKeyboardInstalled2: TGUID = '{3086C85C-932A-4726-BF76-2D74DD133AC9}';
IID_IKeymanPackagesInstalled2: TGUID = '{F23B9848-2AEF-4A2B-BC3A-292E3A00D691}';
IID_IKeymanKeyboardFile2: TGUID = '{EDE4326B-51F4-42D5-8251-B20B71993EC8}';
IID_IKeymanPackageFile2: TGUID = '{9B43B6BC-C622-47EF-915E-6780CF53BAAA}';
IID_IKeymanKeyboardLanguageInstalled2: TGUID = '{414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E}';
IID_IKeymanKeyboardLanguagesInstalled2: TGUID = '{628FF2E6-B490-462E-8FC7-7AE53B9D392C}';
- IID_IKeymanKeyboardFile3: TGUID = '{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}';
- IID_IKeymanPackageFile3: TGUID = '{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}';
- IID_IKeymanKeyboardsInstalled3: TGUID = '{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}';
- IID_IKeymanPackagesInstalled3: TGUID = '{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}';
CLASS_Keyman: TGUID = '{CF46549D-4D2D-4679-A2E1-23A815F172F8}';
IID_IKeymanDefaultLanguage: TGUID = '{77BAB934-B7DF-4304-AFA6-B8F6BEC16516}';
@@ -253,8 +248,6 @@ interface
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
- IKeymanKeyboardInstalled2 = interface;
- IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -265,14 +258,6 @@ interface
IKeymanKeyboardLanguageInstalled2Disp = dispinterface;
IKeymanKeyboardLanguagesInstalled2 = interface;
IKeymanKeyboardLanguagesInstalled2Disp = dispinterface;
- IKeymanKeyboardFile3 = interface;
- IKeymanKeyboardFile3Disp = dispinterface;
- IKeymanPackageFile3 = interface;
- IKeymanPackageFile3Disp = dispinterface;
- IKeymanKeyboardsInstalled3 = interface;
- IKeymanKeyboardsInstalled3Disp = dispinterface;
- IKeymanPackagesInstalled3 = interface;
- IKeymanPackagesInstalled3Disp = dispinterface;
IKeymanDefaultLanguage = interface;
IKeymanDefaultLanguageDisp = dispinterface;
@@ -1585,24 +1570,14 @@ interface
end;
// *********************************************************************//
-// DispIntf: IKeymanKeyboardsInstalled2Disp
+// Interface: IKeymanKeyboardsInstalled3
// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {EA57C94F-C140-485E-941A-3F1D5A229024}
+// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
// *********************************************************************//
- IKeymanKeyboardsInstalled2Disp = dispinterface
- ['{EA57C94F-C140-485E-941A-3F1D5A229024}']
- function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; dispid 19;
- procedure RefreshInstalledKeyboards; dispid 601;
- property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
- function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
- procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
- procedure Apply; dispid 18;
- function IndexOf(const ID: WideString): Integer; dispid 5;
- property Count: Integer readonly dispid 1;
- property _NewEnum: IUnknown readonly dispid -4;
- procedure Refresh; dispid 2;
- function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
- out References: OleVariant): WideString; dispid 401;
+ IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
+ ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
+ function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
+ procedure RefreshInstalledKeyboards; safecall;
end;
// *********************************************************************//
@@ -1616,36 +1591,22 @@ interface
end;
// *********************************************************************//
-// DispIntf: IKeymanKeyboardInstalled2Disp
+// DispIntf: IKeymanKeyboardsInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
+// GUID: {EA57C94F-C140-485E-941A-3F1D5A229024}
// *********************************************************************//
- IKeymanKeyboardInstalled2Disp = dispinterface
- ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
- procedure MCompileForBaseKeyboard(KLID: Integer); dispid 288;
- property IconFilename: WideString readonly dispid 257;
- procedure InstallVisualKeyboard(const Filename: WideString); dispid 258;
- property KeymanID: Integer readonly dispid 259;
- property Languages: IKeymanKeyboardLanguagesInstalled readonly dispid 260;
- property Loaded: WordBool dispid 261;
- property Options: IKeymanKeyboardOptions readonly dispid 262;
- property OwnerPackage: IKeymanPackageInstalled readonly dispid 263;
- property VisualKeyboard: IKeymanVisualKeyboard readonly dispid 264;
- procedure Uninstall; dispid 265;
- property Bitmap: IPicture readonly dispid 1;
- property Copyright: WideString readonly dispid 2;
- property DefaultBCP47Languages: WideString readonly dispid 3;
- property DefaultPrimaryLanguage: Integer readonly dispid 4;
- property DefaultWindowsLanguages: WideString readonly dispid 5;
- property DefaultHotkey: IKeymanHotkey readonly dispid 6;
- property Encodings: KeymanKeyboardEncodings readonly dispid 7;
- property Filename: WideString readonly dispid 8;
- function GetCharsUsed: WideString; dispid 9;
- property ID: WideString readonly dispid 10;
- property LayoutType: KeymanKeyboardLayoutType readonly dispid 11;
- property Message: WideString readonly dispid 12;
- property Name: WideString readonly dispid 13;
- property Version: WideString readonly dispid 14;
+ IKeymanKeyboardsInstalled2Disp = dispinterface
+ ['{EA57C94F-C140-485E-941A-3F1D5A229024}']
+ function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; dispid 19;
+ procedure RefreshInstalledKeyboards; dispid 601;
+ property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
+ function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
+ procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
+ procedure Apply; dispid 18;
+ function IndexOf(const ID: WideString): Integer; dispid 5;
+ property Count: Integer readonly dispid 1;
+ property _NewEnum: IUnknown readonly dispid -4;
+ procedure Refresh; dispid 2;
function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
out References: OleVariant): WideString; dispid 401;
end;
@@ -1660,6 +1621,16 @@ interface
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
@@ -1689,6 +1660,16 @@ interface
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
@@ -1727,6 +1708,17 @@ interface
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
@@ -1828,143 +1820,6 @@ interface
out References: OleVariant): WideString; dispid 401;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardFile3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}
-// *********************************************************************//
- IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
- ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
- end;
-
-// *********************************************************************//
-// DispIntf: IKeymanKeyboardFile3Disp
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}
-// *********************************************************************//
- IKeymanKeyboardFile3Disp = dispinterface
- ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; dispid 289;
- procedure Install(Force: WordBool); dispid 256;
- property Languages: IKeymanKeyboardLanguagesFile readonly dispid 402;
- property Bitmap: IPicture readonly dispid 1;
- property Copyright: WideString readonly dispid 2;
- property DefaultBCP47Languages: WideString readonly dispid 3;
- property DefaultPrimaryLanguage: Integer readonly dispid 4;
- property DefaultWindowsLanguages: WideString readonly dispid 5;
- property DefaultHotkey: IKeymanHotkey readonly dispid 6;
- property Encodings: KeymanKeyboardEncodings readonly dispid 7;
- property Filename: WideString readonly dispid 8;
- function GetCharsUsed: WideString; dispid 9;
- property ID: WideString readonly dispid 10;
- property LayoutType: KeymanKeyboardLayoutType readonly dispid 11;
- property Message: WideString readonly dispid 12;
- property Name: WideString readonly dispid 13;
- property Version: WideString readonly dispid 14;
- function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
- out References: OleVariant): WideString; dispid 401;
- 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): IKeymanPackageFile; safecall;
- end;
-
-// *********************************************************************//
-// DispIntf: IKeymanPackageFile3Disp
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
-// *********************************************************************//
- IKeymanPackageFile3Disp = dispinterface
- ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageFile; dispid 292;
- procedure Install(Force: WordBool); dispid 256;
- property Author: WideString readonly dispid 1;
- property AuthorEmail: WideString readonly dispid 2;
- property Copyright: WideString readonly dispid 3;
- property Filename: WideString readonly dispid 4;
- property Files: IKeymanPackageContentFiles readonly dispid 5;
- property Fonts: IKeymanPackageContentFonts readonly dispid 6;
- property Graphic: IPicture readonly dispid 7;
- property GraphicFile: IKeymanPackageContentFile readonly dispid 8;
- property ID: WideString readonly dispid 9;
- property KeyboardOptionsFile: IKeymanPackageContentFile readonly dispid 10;
- property Keyboards: IKeymanPackageContentKeyboards readonly dispid 11;
- property Name: WideString readonly dispid 12;
- property ReadmeFile: IKeymanPackageContentFile readonly dispid 13;
- property UsageFile: IKeymanPackageContentFile readonly dispid 14;
- property Version: WideString readonly dispid 15;
- property WelcomeFile: IKeymanPackageContentFile readonly dispid 16;
- property Website: WideString readonly dispid 17;
- function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
- out References: OleVariant): WideString; dispid 401;
- 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; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
- end;
-
-// *********************************************************************//
-// DispIntf: IKeymanKeyboardsInstalled3Disp
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
-// *********************************************************************//
- IKeymanKeyboardsInstalled3Disp = dispinterface
- ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
- function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; dispid 290;
- property Items[Index: OleVariant]: IKeymanKeyboardInstalled readonly dispid 0; default;
- function GetKeyboardFromFile(const Filename: WideString): IKeymanKeyboardFile; dispid 16;
- procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
- procedure Apply; dispid 18;
- function IndexOf(const ID: WideString): Integer; dispid 5;
- property Count: Integer readonly dispid 1;
- property _NewEnum: IUnknown readonly dispid -4;
- procedure Refresh; dispid 2;
- function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
- out References: OleVariant): WideString; dispid 401;
- 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; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
- end;
-
-// *********************************************************************//
-// DispIntf: IKeymanPackagesInstalled3Disp
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
-// *********************************************************************//
- IKeymanPackagesInstalled3Disp = dispinterface
- ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
- function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; dispid 291;
- property Items[Index: OleVariant]: IKeymanPackageInstalled readonly dispid 0; default;
- function GetPackageFromFile(const Filename: WideString): IKeymanPackageFile; dispid 16;
- procedure Install(const Filename: WideString; Force: WordBool); dispid 17;
- function IndexOf(const ID: WideString): Integer; dispid 18;
- property Count: Integer readonly dispid 1;
- property _NewEnum: IUnknown readonly dispid -4;
- procedure Refresh; dispid 2;
- function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
- out References: OleVariant): WideString; dispid 401;
- end;
-
// *********************************************************************//
// Interface: IKeymanDefaultLanguage
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index ecfff3d7074..91f49822b52 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -6,7 +6,7 @@
// However, when applying changes via the Editor this file will be regenerated
// and comments or formatting changes will be lost.
// ************************************************************************ //
-// File generated on 31/08/2026 5:28:15 PM (- $Rev: 12980 $, 11059984).
+// File generated on 16/09/2021 6:54:45 PM (- $Rev: 12980 $, 32940875).
[
uuid(F16E2A9A-DA46-4EA3-BFF3-BA46B480C961),
@@ -980,51 +980,6 @@ library keymanapi
HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
- [
- uuid(9B43B6BC-C622-47EF-915E-6780CF53BAAA),
- version(14.0),
- helpstring("https://help.keyman.com/developer/engine/desktop/14.0/api/IKeymanPackageFile2"),
- dual,
- oleautomation
- ]
- interface IKeymanPackageFile2: IKeymanPackageFile
- {
- [id(0x00000101)]
- HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanPackageInstalled** PackageResult);
- };
-
- [
- uuid(414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E),
- version(14.0),
- dual,
- oleautomation
- ]
- interface IKeymanKeyboardLanguageInstalled2: IKeymanKeyboardLanguageInstalled
- {
- [id(0x00000194)]
- HRESULT _stdcall FindInstallationLangID([out] long* LangID, [out] BSTR* TemporaryKeyboardID, [out] VARIANT_BOOL* RegistrationRequired, [in] enum tagKeymanInstallFlags Flags, [out, retval] VARIANT_BOOL* Result);
- [id(0x00000195)]
- HRESULT _stdcall RegisterTip([in] long LangID);
- [id(0x00000196)]
- HRESULT _stdcall InstallTip([in] long LangID, [in] BSTR TemporaryKeyboardToRemove);
- [propget, id(0x000001F5)]
- HRESULT _stdcall IsRegistered([out, retval] VARIANT_BOOL* Value);
- [propget, id(0x000001F6)]
- HRESULT _stdcall WindowsBCP47Code([out, retval] BSTR* Value);
- };
-
- [
- uuid(628FF2E6-B490-462E-8FC7-7AE53B9D392C),
- version(14.0),
- dual,
- oleautomation
- ]
- interface IKeymanKeyboardLanguagesInstalled2: IKeymanKeyboardLanguagesInstalled
- {
- [id(0x00000259)]
- HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
- };
-
[
uuid(8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4),
version(19.0),
@@ -1045,16 +1000,18 @@ library keymanapi
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\x03"),
+ helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2\3"),
dual,
oleautomation
]
@@ -1077,6 +1034,51 @@ library keymanapi
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),
+ helpstring("https://help.keyman.com/developer/engine/desktop/14.0/api/IKeymanPackageFile2"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanPackageFile2: IKeymanPackageFile
+ {
+ [id(0x00000101)]
+ HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanPackageInstalled** PackageResult);
+ };
+
+ [
+ uuid(414C26E6-BFAC-4A70-9EA1-E525BA9BBA7E),
+ version(14.0),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardLanguageInstalled2: IKeymanKeyboardLanguageInstalled
+ {
+ [id(0x00000194)]
+ HRESULT _stdcall FindInstallationLangID([out] long* LangID, [out] BSTR* TemporaryKeyboardID, [out] VARIANT_BOOL* RegistrationRequired, [in] enum tagKeymanInstallFlags Flags, [out, retval] VARIANT_BOOL* Result);
+ [id(0x00000195)]
+ HRESULT _stdcall RegisterTip([in] long LangID);
+ [id(0x00000196)]
+ HRESULT _stdcall InstallTip([in] long LangID, [in] BSTR TemporaryKeyboardToRemove);
+ [propget, id(0x000001F5)]
+ HRESULT _stdcall IsRegistered([out, retval] VARIANT_BOOL* Value);
+ [propget, id(0x000001F6)]
+ HRESULT _stdcall WindowsBCP47Code([out, retval] BSTR* Value);
+ };
+
+ [
+ uuid(628FF2E6-B490-462E-8FC7-7AE53B9D392C),
+ version(14.0),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardLanguagesInstalled2: IKeymanKeyboardLanguagesInstalled
+ {
+ [id(0x00000259)]
+ HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
+ };
+
[
uuid(CA3B3B00-EA42-4EED-9043-D1A1F1842D52),
dual,
From 48923665d9f6c3270d0ebc4bbe77f70e27b01ba5 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 3 Sep 2026 17:30:21 +1000
Subject: [PATCH 14/26] chore(windows): Revert "fix(windows): pass
basekeyboardid to installation api"
This reverts commit 82fb40002b980a243edd7a9c647f7d3ca585c422.
---
.../Keyman.Configuration.UI.InstallFile.pas | 30 +++++-----
...Configuration.UI.KeymanProtocolHandler.pas | 12 ++--
.../kmshell/install/UfrmInstallKeyboard.pas | 17 ++----
.../install/UfrmInstallKeyboardFromWeb.pas | 6 +-
windows/src/desktop/kmshell/main/initprog.pas | 15 +++--
.../com/keyboards/keymankeyboardfile.pas | 23 +-------
.../keyboards/keymankeyboardsinstalled.pas | 22 +------
.../com/packages/keymanpackagefile.pas | 43 ++++----------
.../com/packages/keymanpackagesinstalled.pas | 30 +---------
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 42 --------------
windows/src/engine/kmcomapi/kmcomapi.ridl | 58 -------------------
.../processes/keyboard/kpinstallkeyboard.pas | 23 +++-----
.../processes/package/kpinstallpackage.pas | 12 ++--
13 files changed, 69 insertions(+), 264 deletions(-)
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 3cc8dcc9016..c6ee3564ae7 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 @@ TInstallFile = class sealed
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; 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;
+ 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;
end;
implementation
@@ -35,30 +35,29 @@ implementation
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; BaseKeyboardID: Integer): Boolean;
+ const LogFile: string): Boolean;
begin
if TKeymanProtocolHandler.CanHandle(FirstKeyboardFileName) then
begin
- Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, BaseKeyboardID);
+ Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile);
end
else if (KeyboardFileNames.Count > 1) or (Pos('=', FirstKeyboardFileName) > 0) then
begin
- Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent, BaseKeyboardID)
+ Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent)
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, '', BaseKeyboardID);
+ Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '');
end;
end;
-class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean;
+class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean;
var
n: Integer;
InstalledKeyboards: array of IKeymanKeyboardInstalled;
@@ -78,7 +77,7 @@ class function TInstallFile.Execute(Owner: TComponent; const FileName: string; A
begin
if ASilent then
begin
- InstallKeyboard(LogFile, BCP47, BaseKeyboardID);
+ InstallKeyboard(LogFile, BCP47);
Result := True;
end
else
@@ -140,7 +139,7 @@ class function TInstallFile.Execute(Owner: TComponent; const FileName: string; A
/// 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; BaseKeyboardID: Integer): Boolean;
+class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean;
var
i, j: Integer;
FPackage: IKeymanPackageInstalled;
@@ -171,7 +170,7 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
end;
if IsPackage then
begin
- FPackage := (kmcom.Packages as IKeymanPackagesInstalled3).Install3(FileName, True, BaseKeyboardID);
+ FPackage := (kmcom.Packages as IKeymanPackagesInstalled2).Install2(FileName, True);
if Length(FilenameBCP47) > 1
then RegisterKeyboardPackageLanguage(FPackage, FilenameBCP47[1])
else RegisterKeyboardPackageLanguage(FPackage, '');
@@ -179,7 +178,7 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
end
else
begin
- FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled3).Install3(FileName, True, BaseKeyboardID);
+ FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled2).Install2(FileName, True);
if (Length(FilenameBCP47) > 1) and (Trim(FilenameBCP47[1]) <> '')
then BCP47Tag := FilenameBCP47[1]
else BCP47Tag := TTIPMaintenance.GetFirstLanguage(FKeyboard);
@@ -210,7 +209,6 @@ class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings
class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean;
var
dlgOpen: TOpenDialog;
- BaseKeyboardID : Integer;
begin
dlgOpen := TOpenDialog.Create(nil);
try
@@ -218,9 +216,9 @@ class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent):
'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, '', '', BaseKeyboardID)
+ Result := Execute(Owner, dlgOpen.FileName, False, False, '', '')
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 60ac8ae43c5..6f13f6777bd 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 @@ TKeymanProtocolHandler = class sealed
FDownloadURL: string;
frmDownloadProgress: TfrmDownloadProgress;
function DoHandle(Owner: TComponent; const url: string; ASilent,
- ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean;
+ ANoWelcome: Boolean; const ALogFile: string): 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; BaseKeyboardID: Integer): Boolean; static;
+ class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string): Boolean; static;
end;
implementation
@@ -51,13 +51,13 @@ class function TKeymanProtocolHandler.CanHandle(const url: string): Boolean;
class function TKeymanProtocolHandler.Handle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
- const ALogFile: string; BaseKeyboardID: Integer): Boolean;
+ const ALogFile: string): Boolean;
var
h: TKeymanProtocolHandler;
begin
h := TKeymanProtocolHandler.Create;
try
- Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile, BaseKeyboardID);
+ Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile);
finally
h.Free;
end;
@@ -65,7 +65,7 @@ class function TKeymanProtocolHandler.Handle(Owner: TComponent;
function TKeymanProtocolHandler.DoHandle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
- const ALogFile: string; BaseKeyboardID: Integer): Boolean;
+ const ALogFile: string): Boolean;
var
FTempDir: string;
PackageID, BCP47: string;
@@ -98,7 +98,7 @@ function TKeymanProtocolHandler.DoHandle(Owner: TComponent;
end;
// TODO: this makes a circular dependency, refactor it out!
- Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID);
+ Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47);
finally
if FileExists(FDownloadFilename) then
diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
index 775aa1ca2eb..6d79811a80a 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
@@ -74,7 +74,6 @@ interface
Vcl.StdCtrls,
keymanapi_TLB,
- KeymanOptionNames,
UfrmKeymanBase,
UfrmWebContainer;
@@ -103,7 +102,7 @@ TfrmInstallKeyboard = class(TfrmWebContainer)
protected
procedure FireCommand(const command: WideString; params: TStringList); override;
public
- procedure InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
+ procedure InstallKeyboard(const ALogFile, BCP47Tag: string);
property DefaultBCP47Tag: string read FDefaultBCP47Tag write SetDefaultBCP47Tag;
property InstallFile: string read FInstallFile write SetInstallFile;
property Silent: Boolean read FSilent write FSilent;
@@ -272,7 +271,6 @@ procedure TfrmInstallKeyboard.DeleteFileReferences;
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
@@ -285,8 +283,7 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
Manager.Title := 'Installing Keyboard';
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
- BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
- InstallKeyboard('', BCP47Tag, BaseKeyboardID);
+ InstallKeyboard('', BCP47Tag);
Result := True;
end
);
@@ -302,7 +299,6 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
var
t: TTempFile;
ExecParams: string;
- BaseKeyboardString :string;
begin
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
@@ -310,9 +306,8 @@ procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TSt
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+'" -bkd "'+BaseKeyboardString+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
+ ExecParams := '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
' -nowelcome '+TTIPMaintenance.GetUserDefaultLangParameterString;
KL.Log('Calling elevated kmshell %s', [ExecParams]);
if WaitForElevatedConfiguration(GetForegroundWindow, ExecParams) = 0 then
@@ -363,7 +358,7 @@ procedure TfrmInstallKeyboard.CheckLogFileForWarnings(const Filename: string; Si
------------------------------------------------------------------------------}
// TODO: move this to TInstallFile
-procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
+procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string);
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
@@ -405,7 +400,7 @@ procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string;
kbd := nil;
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh;
- FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile3).Install3(True, BaseKeyboardID);
+ FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile2).Install2(True);
if not InstallTipForKeyboard(BCP47Tag) then
begin
// TODO can we return a failure code?
@@ -466,7 +461,7 @@ procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string;
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh; // I2169
- (FPackage as IKeymanPackageFile3).Install3(True, BaseKeyboardID);
+ (FPackage as IKeymanPackageFile2).Install2(True);
kmcom.Refresh;
diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
index ed236d489d6..aff32510372 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
@@ -87,7 +87,6 @@ implementation
Keyman.Configuration.UI.InstallFile,
Keyman.System.LocaleStrings,
kmint,
- KeymanOptionNames,
MessageIdentifierConsts,
Upload_Settings,
utilfiletypes,
@@ -214,7 +213,6 @@ procedure TfrmInstallKeyboardFromWeb.cefBeforeBrowseEx(Sender: TObject; const Ur
procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string);
var
FTempDir: string;
- BaseKeyboardID: Integer;
begin
FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679
try
@@ -232,8 +230,8 @@ procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID,
finally
frmDownloadProgress.Free;
end;
- BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
- if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID) then
+
+ if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47) then
ModalResult := mrOk;
finally
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 3143d728288..64fc2cd2142 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -207,7 +207,7 @@ function Show_frmHTML(AParent: TComponent; const ACaption, AText, AFileName: str
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, FBaseKeyboard: Integer): Boolean;
+ var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
var
s: string;
i: Integer;
@@ -264,7 +264,6 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
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;
@@ -331,7 +330,7 @@ procedure RegisterControlClasses;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
- const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward;
+ const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
procedure Run;
var
@@ -342,7 +341,7 @@ procedure Run;
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID, FBaseKeyboard: Integer;
+ FDefaultLangID: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -351,7 +350,7 @@ procedure Run;
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
- if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard) then
+ if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
@@ -359,7 +358,7 @@ procedure Run;
if not LoadKMCOM then Exit;
try
- RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard);
+ RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
finally
kmcom := nil;
end;
@@ -398,7 +397,7 @@ function DoCheckTIPInstallStatus(FSilent: Boolean): Boolean;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
- FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer);
+ FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
@@ -561,7 +560,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
else ExitCode := 1;
fmInstall:
- if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile, FBaseKeyboard)
+ if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile)
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 b7255869b7b..5ea1e74265c 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
@@ -37,7 +37,7 @@ interface
keymankeyboard, keymancontext, Classes, PackageInfo, keymankeyboardlanguagesfile;
type
- TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2, IKeymanKeyboardFile3)
+ TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2)
private
FFileName: WideString;
FError: Boolean;
@@ -52,7 +52,6 @@ TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeybo
{ 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;
@@ -253,7 +252,7 @@ procedure TKeymanKeyboardFile.Install(Force: WordBool);
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
+ Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
finally
Free;
end;
@@ -265,23 +264,7 @@ function TKeymanKeyboardFile.Install2(Force: WordBool): IKeymanKeyboardInstalled
begin
with TKPInstallKeyboard.Create(Context) do
try
- 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);
+ Execute(FFileName, '', [], nil, Force);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
index b37e0dfce0e..f5f8b744483 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
@@ -37,8 +37,7 @@ interface
keymanerrorcodes, keymankeyboardinstalled, keymankeyboard, internalinterfaces;
type
- TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled,
- IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled3) // I4376
+ TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled) // I4376
private
FKeyboards: TKeyboardList;
procedure TriggerWindowsLanguageSync;
@@ -56,7 +55,6 @@ TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboard
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 }
@@ -103,7 +101,7 @@ procedure TKeymanKeyboardsInstalled.Install(const Filename: WideString; Force: W
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
+ Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
finally
Free;
end;
@@ -114,21 +112,7 @@ function TKeymanKeyboardsInstalled.Install2(const Filename: WideString;
begin
with TKPInstallKeyboard.Create(Context) do
try
- 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);
+ Execute(FileName, '', [], nil, Force);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
index 28ef2d064a4..14b207e2299 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 @@ interface
keymanpackagecontentfiles, StdVcl, kmpinffile, KeymanContext, Graphics, Classes, internalinterfaces;
type
- TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2, IKeymanPackageFile3)
+ TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2)
private
FSourcePath: string;
FSubFiles: IKeymanPackageContentFiles;
@@ -74,7 +74,6 @@ TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFi
{ 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;
@@ -176,7 +175,7 @@ procedure TKeymanPackageFile.Install(Force: WordBool);
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(FFileName, o, 0);
+ Execute(FFileName, o);
finally
Free;
end;
@@ -192,27 +191,7 @@ function TKeymanPackageFile.Install2(Force: WordBool): IKeymanPackageInstalled;
o := [];
if Force then
Include(o, ipForce);
- 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);
+ Execute(FFileName, o);
finally
Free;
end;
@@ -232,7 +211,7 @@ procedure TKeymanPackageFile.LoadPackage;
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 821a38bdc5f..9dd9f1a52ad 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
@@ -38,8 +38,7 @@ TPackageList = class(TAutoObjectList)
property Items[Index: Integer]: IIntKeymanPackageInstalled read GetItem write SetItem; default;
end;
- TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject,
- IKeymanPackagesInstalled, IKeymanPackagesInstalled2, IKeymanPackagesInstalled3)
+ TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, IKeymanPackagesInstalled, IKeymanPackagesInstalled2)
private
FPackages: TPackageList;
protected
@@ -52,7 +51,6 @@ TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject,
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;
@@ -120,7 +118,7 @@ procedure TKeymanPackagesInstalled.Install(const Filename: WideString; Force: Wo
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(Filename, o, 0);
+ Execute(Filename, o);
finally
Free;
end;
@@ -138,29 +136,7 @@ function TKeymanPackagesInstalled.Install2(const Filename: WideString;
o := [];
if Force then
Include(o, ipForce);
- 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);
+ Execute(Filename, o);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 7246c9173f7..786ce6c9b2d 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,17 +1569,6 @@ interface
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
@@ -1621,16 +1610,6 @@ interface
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
@@ -1660,16 +1639,6 @@ interface
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
@@ -1708,17 +1677,6 @@ interface
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 91f49822b52..9eb63fbd68d 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -66,10 +66,6 @@ library keymanapi
interface IKeymanPackageFile2;
interface IKeymanKeyboardLanguageInstalled2;
interface IKeymanKeyboardLanguagesInstalled2;
- interface IKeymanKeyboardFile3;
- interface IKeymanPackageFile3;
- interface IKeymanKeyboardsInstalled3;
- interface IKeymanPackagesInstalled3;
interface IKeymanBCP47Canonicalization;
interface IKeymanDefaultLanguage;
@@ -980,60 +976,6 @@ 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 1d198264cb9..1205d77f720 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -64,7 +64,7 @@ interface
ikLegacyRegisterAndInstallProfiles);
TKPInstallKeyboard = class(TKPBase)
- procedure Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
+ procedure Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
procedure RegisterProfiles(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; PackageLanguageMetadata: TPackageKeyboardLanguageList);
private
procedure LegacyRegisterAndInstallLanguageProfile(Langs: array of Integer;
@@ -112,7 +112,7 @@ implementation
utiltsf,
keymanapi_TLB;
-procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
+procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
var
ki: TKeyboardInfo;
FDestPath: string;
@@ -125,9 +125,7 @@ procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: st
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
- ElevatedBaseKeyboardID: Integer;
- KeymanContext: TKeymanContext;
- RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard;
+ BaseKeyboardID: Integer;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
@@ -248,19 +246,14 @@ procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: st
KL.Log(FLogText);
end;
- // 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
+ // Recompile a mnemonic layout to the user's selected base layout
if ki.MnemonicLayout then // I4169
begin
- KeymanContext := Context as TKeymanContext;
- ElevatedBaseKeyboardID := (KeymanContext.Options as IKeymanOptions).Items['koBaseLayout'].Value;
- RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context);
+ with Context as TKeymanContext do
+ BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;
+ with TKPRecompileMnemonicKeyboard.Create(Context) do
try
- if (BaseKeyboardID = 0) then
- RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, ElevatedBaseKeyboardID)
- else
- RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, BaseKeyboardID);
+ Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
RecompileMnemonicKeyboard.Free;
end;
diff --git a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
index 4ab33cdfeec..98edfbf3fb1 100644
--- a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
+++ b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
@@ -50,7 +50,7 @@ interface
TKPInstallPackage = class(TKPBase)
public
- procedure Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
+ procedure Execute(const FileName: string; Options: TKPInstallPackageOptions);
end;
implementation
@@ -85,7 +85,7 @@ implementation
{ TKPInstallPackage }
-procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
+procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions);
function GetHHIcon: string;
var
buf: array[0..260] of char;
@@ -112,7 +112,7 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
FErrorValue: Cardinal;
FSrcFileName: string;
- procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer);
+ procedure InstallKeyboard(FileName: string);
var
FOptions: TKPInstallKeyboardOptions;
kbd: TPackageKeyboard;
@@ -132,7 +132,7 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options, BaseKeyboardID);
+ Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options);
finally
Free;
end;
@@ -253,12 +253,12 @@ procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallP
begin
case inf.Files[i].FileType of
ftKeymanFile:
- InstallKeyboard(dest + inf.Files[i].FileName, BaseKeyboardID);
+ InstallKeyboard(dest + inf.Files[i].FileName);
ftPackageFile:
with TKPInstallPackage.Create(Context) do
try
- Execute(dest + inf.Files[i].FileName, Options, BaseKeyboardID);
+ Execute(dest + inf.Files[i].FileName, Options);
finally
Free;
end;
From b9743d277b69077de9b6a934504eef56e8346479 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 3 Sep 2026 17:37:22 +1000
Subject: [PATCH 15/26] fix(windows): fix indentation
---
windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 56e7c442b4f..91a6710112b 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -33,7 +33,8 @@ implementation
utilkmshell;
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
-begin with TfrmBaseKeyboard.Create(nil) do
+begin
+ with TfrmBaseKeyboard.Create(nil) do
try
Result := ShowModal = mrOk;
if Result then
From d67c4911af9b5431cda22eb9a13e36e8574386ad Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 4 Sep 2026 13:48:49 +1000
Subject: [PATCH 16/26] fix(windows): rename Setting System
Also update the command line to use FBaseKeyboardID instead of
FQuery.
---
windows/src/desktop/kmshell/kmshell.dpr | 2 +-
windows/src/desktop/kmshell/kmshell.dproj | 2 +-
...man.Configuration.System.BaseKeyboard.pas} | 27 +++++++------------
windows/src/desktop/kmshell/main/UfrmMain.pas | 2 +-
windows/src/desktop/kmshell/main/initprog.pas | 18 ++++++-------
5 files changed, 21 insertions(+), 30 deletions(-)
rename windows/src/desktop/kmshell/{settings/Keyman.Configuration.Settings.BaseKeyboard.pas => main/Keyman.Configuration.System.BaseKeyboard.pas} (72%)
diff --git a/windows/src/desktop/kmshell/kmshell.dpr b/windows/src/desktop/kmshell/kmshell.dpr
index e4ce8316d31..124b0357ce2 100644
--- a/windows/src/desktop/kmshell/kmshell.dpr
+++ b/windows/src/desktop/kmshell/kmshell.dpr
@@ -184,7 +184,7 @@ uses
Keyman.System.ExecutionHistory in '..\..\..\..\common\windows\delphi\general\Keyman.System.ExecutionHistory.pas',
Keyman.Configuration.UI.UfrmStartInstall in 'main\Keyman.Configuration.UI.UfrmStartInstall.pas' {frmStartInstall},
Keyman.Configuration.Util.NetworkConnection in 'util\Keyman.Configuration.Util.NetworkConnection.pas',
- Keyman.Configuration.Settings.BaseKeyboard in 'settings\Keyman.Configuration.Settings.BaseKeyboard.pas';
+ Keyman.Configuration.System.BaseKeyboard in 'main\Keyman.Configuration.System.BaseKeyboard.pas';
{$R VERSION.RES}
{$R manifest.res}
diff --git a/windows/src/desktop/kmshell/kmshell.dproj b/windows/src/desktop/kmshell/kmshell.dproj
index ca611b40e44..abcb5215972 100644
--- a/windows/src/desktop/kmshell/kmshell.dproj
+++ b/windows/src/desktop/kmshell/kmshell.dproj
@@ -358,7 +358,7 @@
-
+
Cfg_2
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
similarity index 72%
rename from windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas
rename to windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index 44488179c9d..c47d90a1a57 100644
--- a/windows/src/desktop/kmshell/settings/Keyman.Configuration.Settings.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -1,4 +1,4 @@
-unit Keyman.Configuration.Settings.BaseKeyboard;
+unit Keyman.Configuration.System.BaseKeyboard;
interface
@@ -8,8 +8,7 @@ interface
keymanapi_TLB;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
-function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
-procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
+function MCompileBaseKeyboard(BaseKeyboardID: Integer): Boolean;
implementation
@@ -47,7 +46,7 @@ function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolea
WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
end
else
- CompileForBaseKeyboard(BaseKeyboardID);
+ MCompileBaseKeyboard(BaseKeyboardID);
end;
kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
@@ -55,29 +54,21 @@ function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolea
Result := True;
end;
-function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
-var
- BaseKeyboardID: Integer;
-begin
- Result := False;
- if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
- not kmcom.SystemInfo.IsAdministrator then
- Exit;
- CompileForBaseKeyboard(BaseKeyboardID);
- // TODO: sort out whether we need todo return a result
- Result := True;
-end;
-
-procedure CompileForBaseKeyboard(BaseKeyboardID: Integer);
+function MCompileBaseKeyboard(BaseKeyboardID: Integer): Boolean;
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
begin
+ Result := False;
+ // can be called from command line so test for admin
+ if not kmcom.SystemInfo.IsAdministrator then
+ Exit;
for i := 0 to kmcom.Keyboards.Count - 1 do
begin
kbd := kmcom.Keyboards[i];
(kbd as IKeymanKeyboardInstalled2).MCompileForBaseKeyboard(BaseKeyboardID);
end;
+ Result := True;
end;
end.
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index 599566b91cb..9c4478283e9 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -174,7 +174,7 @@ implementation
Hints,
HotkeyUtils,
initprog,
- Keyman.Configuration.Settings.BaseKeyboard,
+ Keyman.Configuration.System.BaseKeyboard,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.UI.UfrmDiagnosticTests,
KeymanOptionNames,
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 64fc2cd2142..54f4a73f65d 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -115,7 +115,7 @@ implementation
GetOsVersion,
help,
HTMLHelpViewer,
- Keyman.Configuration.Settings.BaseKeyboard,
+ Keyman.Configuration.System.BaseKeyboard,
Keyman.Configuration.UI.InstallFile,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.System.UImportOlderVersionKeyboards11To13,
@@ -207,7 +207,7 @@ function Show_frmHTML(AParent: TComponent; const ACaption, AText, AFileName: str
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;
@@ -269,7 +269,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
FMode := fmMCompileKbds;
Inc(i);
if i > ParamCount then Exit;
- FQuery := ParamStr(i);
+ FBaseKeyboard := StrToInt('$' + ParamStr(i));
end
else if s = '-nowelcome' then FNoWelcome := True
else if s = '-kw' then FMode := fmKeyboardWelcome // I2569
@@ -330,7 +330,7 @@ procedure RegisterControlClasses;
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
@@ -341,7 +341,7 @@ procedure Run;
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID: Integer;
+ FDefaultLangID, FBaseKeyboard: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -350,7 +350,7 @@ procedure Run;
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;
@@ -358,7 +358,7 @@ procedure Run;
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;
@@ -397,7 +397,7 @@ function DoCheckTIPInstallStatus(FSilent: Boolean): Boolean;
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;
@@ -555,7 +555,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
else ExitCode := 1;
fmMCompileKbds:
- if MCompileBaseKeyboard(FQuery)
+ if MCompileBaseKeyboard(FBaseKeyboard)
then ExitCode := 0
else ExitCode := 1;
From 0409cda1201fa4c9ff296d148ceeacbebb689b89 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 7 Sep 2026 13:03:29 +1000
Subject: [PATCH 17/26] fix(windows): add comments for new functions
---
...yman.Configuration.System.BaseKeyboard.pas | 31 ++++++++++++++++---
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 8 +++++
2 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index c47d90a1a57..d91b439f336 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -7,7 +7,28 @@ interface
System.SysUtils,
keymanapi_TLB;
+(**
+ Returns true if the keyboard files need to be compiled for the specified KLID.
+ @param BaseKeyboardID KLID of the base keyboard to compile.
+ @returns True If the keyboard files need to be compiled.
+*)
+function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
+
+(**
+ Sets the base keyboard KLID for the current user and compiles the keyboard
+ files if necessary. In the case the compiled keyboard files are not present,
+ it will require elevation.
+ @param WindowHandle Window handle to own the elevation prompt.
+ @param BaseKeyboardID KLID of the base keyboard KLID to set.
+ @returns True when the base keyboard setting has been applied.
+*)
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
+
+(**
+ Compiles the base keyboard files for the specified KLID.
+ @param BaseKeyboardID KLID of the base keyboard to compile.
+ @returns True when the compilation is successful.
+*)
function MCompileBaseKeyboard(BaseKeyboardID: Integer): Boolean;
implementation
@@ -38,20 +59,20 @@ function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
begin
- Result := False;
+ Result := True;
if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
begin
if not kmcom.SystemInfo.IsAdministrator then
begin
- WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
+ Result := WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8)) = 0;
end
else
- MCompileBaseKeyboard(BaseKeyboardID);
+ Result := MCompileBaseKeyboard(BaseKeyboardID);
end;
-
+ if not Result then
+ Exit;
kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
kmcom.Options.Apply;
- Result := True;
end;
function MCompileBaseKeyboard(BaseKeyboardID: Integer): Boolean;
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 91a6710112b..dd298a86421 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -18,6 +18,14 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
procedure FireCommand(const command: WideString; params: TStringList); override;
end;
+
+(**
+ Form for the user to select a base keyboard. If the user selects a base
+ keyboard, the KLID of the selected base keyboard is returned in
+ BaseKeyboardID.
+ @param [out] BaseKeyboardID KLID of the base keyboard selected by the user.
+ @returns True if the user selected a base keyboard.
+*)
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
implementation
From 163806b712d97961b1fa099890a7b828b79149df Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 7 Sep 2026 17:17:39 +1000
Subject: [PATCH 18/26] fix(windows): git revert error fix
---
windows/src/engine/kmcomapi/keymanapi_TLB.pas | 60 +++++++++++++++----
windows/src/engine/kmcomapi/kmcomapi.ridl | 2 +-
.../processes/keyboard/kpinstallkeyboard.pas | 2 +-
3 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 786ce6c9b2d..550a13064d9 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@
// ************************************************************************ //
// $Rev: 52393 $
-// File generated on 16/09/2021 6:54:44 PM from Type Library described below.
+// File generated on 7/09/2026 3:54:23 PM from Type Library described below.
// ************************************************************************ //
// Type Lib: C:\Projects\keyman\app\windows\src\engine\kmcomapi\kmcomapi (1)
@@ -87,6 +87,7 @@ interface
IID_IKeymanKeyboardLanguagesInstalled: TGUID = '{7DC22BC0-85BB-45C0-8EDB-A2F4BD1D500B}';
IID_IKeymanKeyboardLanguagesFile: TGUID = '{5F90BCDA-F1C1-433A-8FD0-B498299D3C30}';
IID_IKeymanKeyboardsInstalled2: TGUID = '{EA57C94F-C140-485E-941A-3F1D5A229024}';
+ IID_IKeymanKeyboardInstalled2: TGUID = '{3086C85C-932A-4726-BF76-2D74DD133AC9}';
IID_IKeymanPackagesInstalled2: TGUID = '{F23B9848-2AEF-4A2B-BC3A-292E3A00D691}';
IID_IKeymanKeyboardFile2: TGUID = '{EDE4326B-51F4-42D5-8251-B20B71993EC8}';
IID_IKeymanPackageFile2: TGUID = '{9B43B6BC-C622-47EF-915E-6780CF53BAAA}';
@@ -248,6 +249,8 @@ interface
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
+ IKeymanKeyboardInstalled2 = interface;
+ IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -1569,16 +1572,6 @@ interface
procedure RefreshInstalledKeyboards; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardInstalled2
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
-// *********************************************************************//
- IKeymanKeyboardInstalled2 = interface(IKeymanKeyboardInstalled)
- ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
- procedure MCompileForBaseKeyboard(KLID: Integer); safecall;
- end;
-
// *********************************************************************//
// DispIntf: IKeymanKeyboardsInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1600,6 +1593,51 @@ interface
out References: OleVariant): WideString; dispid 401;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardInstalled2
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
+// *********************************************************************//
+ IKeymanKeyboardInstalled2 = interface(IKeymanKeyboardInstalled)
+ ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
+ procedure MCompileForBaseKeyboard(KLID: Integer); safecall;
+ end;
+
+// *********************************************************************//
+// DispIntf: IKeymanKeyboardInstalled2Disp
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3086C85C-932A-4726-BF76-2D74DD133AC9}
+// *********************************************************************//
+ IKeymanKeyboardInstalled2Disp = dispinterface
+ ['{3086C85C-932A-4726-BF76-2D74DD133AC9}']
+ procedure MCompileForBaseKeyboard(KLID: Integer); dispid 288;
+ property IconFilename: WideString readonly dispid 257;
+ procedure InstallVisualKeyboard(const Filename: WideString); dispid 258;
+ property KeymanID: Integer readonly dispid 259;
+ property Languages: IKeymanKeyboardLanguagesInstalled readonly dispid 260;
+ property Loaded: WordBool dispid 261;
+ property Options: IKeymanKeyboardOptions readonly dispid 262;
+ property OwnerPackage: IKeymanPackageInstalled readonly dispid 263;
+ property VisualKeyboard: IKeymanVisualKeyboard readonly dispid 264;
+ procedure Uninstall; dispid 265;
+ property Bitmap: IPicture readonly dispid 1;
+ property Copyright: WideString readonly dispid 2;
+ property DefaultBCP47Languages: WideString readonly dispid 3;
+ property DefaultPrimaryLanguage: Integer readonly dispid 4;
+ property DefaultWindowsLanguages: WideString readonly dispid 5;
+ property DefaultHotkey: IKeymanHotkey readonly dispid 6;
+ property Encodings: KeymanKeyboardEncodings readonly dispid 7;
+ property Filename: WideString readonly dispid 8;
+ function GetCharsUsed: WideString; dispid 9;
+ property ID: WideString readonly dispid 10;
+ property LayoutType: KeymanKeyboardLayoutType readonly dispid 11;
+ property Message: WideString readonly dispid 12;
+ property Name: WideString readonly dispid 13;
+ property Version: WideString readonly dispid 14;
+ function SerializeXML(Flags: tagKeymanSerializeFlags; const ImagePath: WideString;
+ out References: OleVariant): WideString; dispid 401;
+ end;
+
// *********************************************************************//
// Interface: IKeymanPackagesInstalled2
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index 9eb63fbd68d..4d65b37777a 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -6,7 +6,7 @@
// However, when applying changes via the Editor this file will be regenerated
// and comments or formatting changes will be lost.
// ************************************************************************ //
-// File generated on 16/09/2021 6:54:45 PM (- $Rev: 12980 $, 32940875).
+// File generated on 7/09/2026 4:05:40 PM (- $Rev: 12980 $, 1707828).
[
uuid(F16E2A9A-DA46-4EA3-BFF3-BA46B480C961),
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
index 1205d77f720..1df237b0c60 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -255,7 +255,7 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
try
Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
- RecompileMnemonicKeyboard.Free;
+ Free;
end;
end;
finally
From 63d12b671a3a06647d11272bdfa8c4e5b2aa7270 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 7 Sep 2026 20:43:26 +1000
Subject: [PATCH 19/26] fix(windows): remove UpdateBaseLayout deadcode
---
.../com/keyboards/keymankeyboardinstalled.pas | 17 -----------------
.../kmcomapi/util/internalinterfaces.pas | 19 +++++++++----------
2 files changed, 9 insertions(+), 27 deletions(-)
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
index 01b03ae3fc8..7077bc12913 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -110,7 +110,6 @@ TKeymanKeyboardInstalled = class( // I3581
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
{ IKeymanKeyboardInstalled2 }
@@ -155,22 +154,6 @@ procedure TKeymanKeyboardInstalled.Uninstall;
end;
end;
-procedure TKeymanKeyboardInstalled.UpdateBaseLayout; // I4169
-var
- BaseKeyboardID: Integer;
-begin
- if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then // I4615
- begin
- BaseKeyboardID := (Context.Options as IKeymanOptions).Items['koBaseLayout'].Value;
- with TKPRecompileMnemonicKeyboard.Create(Context) do
- try
- Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, BaseKeyboardID);
- finally
- Free;
- end;
- end;
-end;
-
function TKeymanKeyboardInstalled.Get_Copyright: WideString;
begin
Result := FRegKeyboard.Copyright;
diff --git a/windows/src/engine/kmcomapi/util/internalinterfaces.pas b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
index 1759468e006..edfc65bf286 100644
--- a/windows/src/engine/kmcomapi/util/internalinterfaces.pas
+++ b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
@@ -1,24 +1,24 @@
(*
Name: internalinterfaces
Copyright: Copyright (C) 2003-2017 SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 25 Jan 2011
Modified Date: 17 Aug 2014
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 25 Jan 2011 - mcdurdin - I2569 - Keyboard welcome should always shown from kmshell
01 Jan 2013 - mcdurdin - I3717 - V9.0 - Need ability to select base keyboard in Keyman Configuration
16 Apr 2014 - mcdurdin - I4169 - V9.0 - Mnemonic layouts should be recompiled to positional based on user-selected base keyboard
17 Aug 2014 - mcdurdin - I4376 - V9.0 - Unticked keyboards in configuration should be removed from language profile
17 Aug 2014 - mcdurdin - I4381 - V9.0 - Keyman keyboards should be removed from language bar when Keyman exits
-
+
*)
unit internalinterfaces;
@@ -41,7 +41,7 @@ interface
IIntKeymanInterface = interface
['{D1EBBED5-B9E3-4807-969D-DCF9E1FFB287}']
function XMLClassName: WideString;
- function Serialize(Flags: TOleEnum; const ImagePath: WideString; References: TStrings): WideString;
+ function Serialize(Flags: TOleEnum; const ImagePath: WideString; References: TStrings): WideString;
function DoSerialize(Flags: TOleEnum; const ImagePath: WideString; References: TStrings): WideString; // Wraps serialize with tag
end;
@@ -67,7 +67,6 @@ interface
['{4876E6DF-C557-46E2-84F4-787BE5F55DDA}']
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
end;
From f80986dedd78c10c182a9c6b7b14782e3222f0c0 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Mon, 14 Sep 2026 14:42:32 +1000
Subject: [PATCH 20/26] fix(windows): apply batched suggestions from code
review
Co-authored-by: Marc Durdin
---
...yman.Configuration.System.BaseKeyboard.pas | 32 ++++++++++---------
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 12 +++----
2 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index d91b439f336..926e766daaf 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -8,27 +8,29 @@ interface
keymanapi_TLB;
(**
- Returns true if the keyboard files need to be compiled for the specified KLID.
- @param BaseKeyboardID KLID of the base keyboard to compile.
- @returns True If the keyboard files need to be compiled.
-*)
+ * Returns true if the keyboard files need to be compiled for the specified KLID.
+ * @param BaseKeyboardID KLID of the base keyboard to compile.
+ * @returns True If the keyboard files need to be compiled.
+ *)
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
(**
- Sets the base keyboard KLID for the current user and compiles the keyboard
- files if necessary. In the case the compiled keyboard files are not present,
- it will require elevation.
- @param WindowHandle Window handle to own the elevation prompt.
- @param BaseKeyboardID KLID of the base keyboard KLID to set.
- @returns True when the base keyboard setting has been applied.
-*)
+ * Sets the base keyboard KLID for the current user and compiles the keyboard
+ * files if necessary. In the case the compiled keyboard files are not present,
+ * it will require elevation.
+ * @param WindowHandle Window handle to own the elevation prompt.
+ * @param BaseKeyboardID KLID of the base keyboard KLID to set.
+ * @returns True when the base keyboard setting has been applied.
+ *)
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
(**
- Compiles the base keyboard files for the specified KLID.
- @param BaseKeyboardID KLID of the base keyboard to compile.
- @returns True when the compilation is successful.
-*)
+ * Compiles the base keyboard files for the specified KLID.
+ * Must run elevated.
+ *
+ * @param BaseKeyboardID KLID of the base keyboard to compile.
+ * @returns True when the compilation is successful.
+ *)
function MCompileBaseKeyboard(BaseKeyboardID: Integer): Boolean;
implementation
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index dd298a86421..1d06e7ca25d 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -20,12 +20,12 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
(**
- Form for the user to select a base keyboard. If the user selects a base
- keyboard, the KLID of the selected base keyboard is returned in
- BaseKeyboardID.
- @param [out] BaseKeyboardID KLID of the base keyboard selected by the user.
- @returns True if the user selected a base keyboard.
-*)
+ * Form for the user to select a base keyboard. If the user selects a base
+ * keyboard, the KLID of the selected base keyboard is returned in
+ * BaseKeyboardID.
+ * @param [out] BaseKeyboardID KLID of the base keyboard selected by the user.
+ * @returns True if the user selected a base keyboard.
+ *)
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
implementation
From babd43ab29d39ea98d452cbe90303324c48f1702 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Tue, 15 Sep 2026 12:11:02 +1000
Subject: [PATCH 21/26] fix(windows): refactor ConfigureBaseKeyboard
Refactor ConfigureBaseKeyboard to ConfigureAndSetBaseKeyboard
call the SetBaseKeyboard from the form rather then from
the initprog module.
---
...yman.Configuration.System.BaseKeyboard.pas | 16 ++++++++++++---
.../desktop/kmshell/main/UfrmBaseKeyboard.pas | 20 ++++++++++---------
windows/src/desktop/kmshell/main/UfrmMain.pas | 3 +--
windows/src/desktop/kmshell/main/initprog.pas | 3 +--
4 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index 926e766daaf..dedea86dae5 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -1,3 +1,13 @@
+(*
+ * Keyman is copyright (C) SIL Global. MIT License.
+ *
+ * Created by Ross Cruickshank on 2026-09-dd-12
+ *
+ *
+ * This unit assists in setting the base keyboard configuration,
+ * including compiling the installed keyboard layouts against
+ * the selected base keyboard.
+ *)
unit Keyman.Configuration.System.BaseKeyboard;
interface
@@ -16,8 +26,8 @@ function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
(**
* Sets the base keyboard KLID for the current user and compiles the keyboard
- * files if necessary. In the case the compiled keyboard files are not present,
- * it will require elevation.
+ * layout files if necessary. In the case the compiled keyboard files are
+ *not present, it will require elevation.
* @param WindowHandle Window handle to own the elevation prompt.
* @param BaseKeyboardID KLID of the base keyboard KLID to set.
* @returns True when the base keyboard setting has been applied.
@@ -25,7 +35,7 @@ function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
(**
- * Compiles the base keyboard files for the specified KLID.
+ * Compiles the installed keyboard layouts for the specified KLID.
* Must run elevated.
*
* @param BaseKeyboardID KLID of the base keyboard to compile.
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 1d06e7ca25d..825088ad0a7 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -18,15 +18,14 @@ TfrmBaseKeyboard = class(TfrmWebContainer)
procedure FireCommand(const command: WideString; params: TStringList); override;
end;
-
(**
- * Form for the user to select a base keyboard. If the user selects a base
- * keyboard, the KLID of the selected base keyboard is returned in
- * BaseKeyboardID.
- * @param [out] BaseKeyboardID KLID of the base keyboard selected by the user.
- * @returns True if the user selected a base keyboard.
+ * Displays a form for the user to select a base keyboard. If the user selects a base
+ * keyboard, the KLID is used to Set the Base Keyboard.
+ *
+ * @returns True if the user selected base keyboard has been set.
*)
-function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
+function ConfigureAndSetBaseKeyboard(WindowHandle: THandle): Boolean;
+
implementation
@@ -37,16 +36,19 @@ implementation
ErrorControlledRegistry,
RegistryKeys,
keymanapi_TLB,
+ Keyman.Configuration.System.BaseKeyboard,
kmint,
utilkmshell;
-function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
+
+function ConfigureAndSetBaseKeyboard(WindowHandle: THandle): Boolean;
+var BaseKeyboardID: Integer;
begin
with TfrmBaseKeyboard.Create(nil) do
try
Result := ShowModal = mrOk;
if Result then
- BaseKeyboardID := FBaseKeyboardID;
+ SetBaseKeyboard(WindowHandle, FBaseKeyboardID)
finally
Free;
end;
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index 9c4478283e9..472353102cf 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -666,9 +666,8 @@ procedure TfrmMain.Options_BaseKeyboard; // I4169
var
BaseKeyboardID: Integer;
begin
- if ConfigureBaseKeyboard(BaseKeyboardID) then
+ if ConfigureAndSetBaseKeyboard(Handle) then
begin
- SetBaseKeyboard(Handle, BaseKeyboardID);
DoRefresh;
end;
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 54f4a73f65d..f2392d69130 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -402,7 +402,6 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
- BaseKeyboardID: Integer;
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
@@ -550,7 +549,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
end;
fmBaseKeyboard: // I4169
- if ConfigureBaseKeyboard(BaseKeyboardID) and SetBaseKeyboard(0, BaseKeyboardID)
+ if ConfigureAndSetBaseKeyboard(0)
then ExitCode := 0
else ExitCode := 1;
From b6f475a382fc763190c489c5f9cf35bf92284d0d Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Wed, 16 Sep 2026 17:37:59 +1000
Subject: [PATCH 22/26] fix(windows): add basekeyboard filename functions
---
common/windows/delphi/general/utilstr.pas | 46 +++++++++++++++----
.../kmshell/install/UpgradeMnemonicLayout.pas | 19 ++++----
...yman.Configuration.System.BaseKeyboard.pas | 13 +++---
.../keyboard/kprecompilemnemonickeyboard.pas | 5 +-
4 files changed, 57 insertions(+), 26 deletions(-)
diff --git a/common/windows/delphi/general/utilstr.pas b/common/windows/delphi/general/utilstr.pas
index 01e085b8a8c..b5bcd32e659 100644
--- a/common/windows/delphi/general/utilstr.pas
+++ b/common/windows/delphi/general/utilstr.pas
@@ -1,18 +1,18 @@
(*
Name: utilstr
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 1 Aug 2006
Modified Date: 8 Jun 2012
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 01 Aug 2006 - mcdurdin - Refactor util functions into multiple units
23 Aug 2006 - mcdurdin - Add StringToExtString and WideQuotedStr functions
14 Sep 2006 - mcdurdin - Add RectToString, StringToRect, use widestrings for some functions
@@ -58,7 +58,25 @@ function GetTokenFromCaret(line: string; var selx, sellen: Integer): string;
function WideQuotedStr(const str: WideString): WideString; deprecated; // I3310
-
+(**
+ * Creates the compiled keyboard filename by inserting the base keyboard ID
+ * before the .kmx extension.
+ *
+ * @param BaseFileName Base keyboard filename, in the form keyboardname.kmx.
+ * @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
+ * @return Compiled keyboard filename, in the form keyboardname-.kmx.
+ *)
+function InsertBKLIDFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+
+(**
+ * Creates the dead-key compiled keyboard filename by inserting the base
+ * keyboard ID and -d suffix before the .kmx extension.
+ *
+ * @param BaseFileName Base keyboard filename, in the form keyboardname.kmx.
+ * @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
+ * @return Dead-key compiled keyboard filename, in the form keyboardname--d.kmx.
+ *)
+function InsertBKLIDDeadkeyFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
implementation
@@ -78,7 +96,7 @@ function CommaToken(var s: WideString): WideString;
Result := '';
Exit;
end;
-
+
if s[1] = '"' then
begin
Delete(s,1,1);
@@ -418,4 +436,14 @@ function StringToRect(s: string): TRect;
Result.Bottom := StrToIntDef(s, 0);
end;
+function InsertBKLIDFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+begin
+ Result := ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
+end;
+
+function InsertBKLIDDeadkeyFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+begin
+ Result := ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx'
+end;
+
end.
diff --git a/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas b/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
index acad7655909..2639ac20728 100644
--- a/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
+++ b/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
@@ -1,18 +1,18 @@
(*
Name: UpgradeMnemonicLayout
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 31 Dec 2014
Modified Date: 2 Jun 2015
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 31 Dec 2014 - mcdurdin - I4553 - V9.0 - Upgrade to 476 or later requires recompile of all mnemonic layouts
06 Feb 2015 - mcdurdin - I4552 - V9.0 - Add mnemonic recompile option to ignore deadkeys
08 Apr 2015 - mcdurdin - I4651 - V9.0 - Mnemonic layout recompiler maps AltGr+VK_BKSLASH rather than VK_OEM_102
@@ -46,7 +46,8 @@ implementation
kmint,
RegistryKeys,
utilexecute,
- utilkmshell;
+ utilkmshell,
+ utilstr;
const
{ CurrentMnemonicLayoutVersion = 476; // First 9.0 build with fixes for mnemonic layouts }
@@ -171,7 +172,7 @@ class procedure TUpgradeMnemonicLayout.UpgradeLayoutLanguage(
FBaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
FBaseFileName := Keyboard.Filename;
FDestFileName := OutputFileName;
- FDestDeadkeyFileName := ChangeFileExt(FDestFileName, '') + '-d.kmx'; // I4552
+ FDestDeadkeyFileName := InsertBKLIDDeadkeyFilename(FBaseFileName, FBaseKeyboardIDHex); // I4552
FMCompilePath := TKeymanPaths.KeymanEngineInstallPath(TKeymanPaths.S_MCompileExe);
FDestPath := ExtractFileDir(Keyboard.Filename);
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index dedea86dae5..4c398f1fe8d 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -47,23 +47,24 @@ implementation
uses
kmint,
- utilkmshell;
+ utilkmshell,
+ utilstr;
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
var
I: Integer;
Keyboard: IKeymanKeyboardInstalled;
- BaseFileName: string;
+ KeyboardFileName: string;
BaseKeyboardIDHex: string;
begin
BaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
for I := 0 to kmcom.Keyboards.Count - 1 do
begin
Keyboard := kmcom.Keyboards.Items[I];
- BaseFileName := Keyboard.Filename;
- if FileExists(BaseFileName) and
- (not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx') or
- not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx')) then
+ KeyboardFileName := Keyboard.Filename;
+ if FileExists(KeyboardFileName) and
+ (not FileExists(InsertBKLIDFilename(KeyboardFileName, BaseKeyboardIDHex)) or
+ not FileExists(InsertBKLIDDeadkeyFilename(KeyboardFileName, BaseKeyboardIDHex))) then
Exit(True);
end;
Result := False;
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
index 3d806afda2e..b05ab325d15 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -47,6 +47,7 @@ implementation
RegistryKeys,
utilexecute,
utilkeyman,
+ utilstr,
utilsystem;
function GetKeyboardLayoutFileName(id: Integer): string;
@@ -83,8 +84,8 @@ procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: strin
FBaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
FBaseFileName := FDestPath + '\' + ExtractFileName(FileName); // I3581
- FDestFileName := ChangeFileExt(FBaseFileName, '') + '-'+FBaseKeyboardIDHex + '.kmx';
- FDestDeadkeyFileName := ChangeFileExt(FBaseFileName, '') + '-'+FBaseKeyboardIDHex + '-d.kmx'; // I4552
+ FDestFileName := InsertBKLIDFilename(FBaseFileName, FBaseKeyboardIDHex);
+ FDestDeadkeyFileName := InsertBKLIDDeadkeyFilename(FBaseFileName, FBaseKeyboardIDHex); // I4552
FMCompilePath := TKeymanPaths.KeymanEngineInstallPath(TKeymanPaths.S_MCompileExe);
{ Recompile with the traditional deadkey behaviour }
From eec0b12c449b56402991747d82d590fbb049a27f Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Thu, 17 Sep 2026 10:38:33 +1000
Subject: [PATCH 23/26] fix(windows): rename argument that was misleading
---
common/windows/delphi/general/utilstr.pas | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/common/windows/delphi/general/utilstr.pas b/common/windows/delphi/general/utilstr.pas
index b5bcd32e659..59a897ad2e1 100644
--- a/common/windows/delphi/general/utilstr.pas
+++ b/common/windows/delphi/general/utilstr.pas
@@ -62,21 +62,21 @@ function WideQuotedStr(const str: WideString): WideString; deprecated; // I3310
* Creates the compiled keyboard filename by inserting the base keyboard ID
* before the .kmx extension.
*
- * @param BaseFileName Base keyboard filename, in the form keyboardname.kmx.
+ * @param KeyboardFileName Keyboard filename, in the form keyboardname.kmx.
* @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
* @return Compiled keyboard filename, in the form keyboardname-.kmx.
*)
-function InsertBKLIDFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+function InsertBKLIDFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
(**
* Creates the dead-key compiled keyboard filename by inserting the base
* keyboard ID and -d suffix before the .kmx extension.
*
- * @param BaseFileName Base keyboard filename, in the form keyboardname.kmx.
+ * @param KeyboardFileName Keyboard filename, in the form keyboardname.kmx.
* @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
* @return Dead-key compiled keyboard filename, in the form keyboardname--d.kmx.
*)
-function InsertBKLIDDeadkeyFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+function InsertBKLIDDeadkeyFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
implementation
@@ -436,14 +436,14 @@ function StringToRect(s: string): TRect;
Result.Bottom := StrToIntDef(s, 0);
end;
-function InsertBKLIDFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+function InsertBKLIDFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
begin
- Result := ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
+ Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
end;
-function InsertBKLIDDeadkeyFilename(const BaseFileName: string; BaseKeyboardIDHex: string): string;
+function InsertBKLIDDeadkeyFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
begin
- Result := ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx'
+ Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx'
end;
end.
From c940caeb711d2524a50717d251b54631d7023d8d Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 18 Sep 2026 16:58:58 +1000
Subject: [PATCH 24/26] fix(windows): fix date in title block
---
.../kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index 4c398f1fe8d..a1fecdd6085 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -1,7 +1,7 @@
(*
* Keyman is copyright (C) SIL Global. MIT License.
*
- * Created by Ross Cruickshank on 2026-09-dd-12
+ * Created by Ross Cruickshank on 2026-09-12
*
*
* This unit assists in setting the base keyboard configuration,
From 587d74dee4841ec36ef085e39fb4f33fdbf3f025 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 18 Sep 2026 20:48:56 +1000
Subject: [PATCH 25/26] fix(windows): apply batched suggestions from code
review
Co-authored-by: Marc Durdin
---
common/windows/delphi/general/utilstr.pas | 22 +++++++++----------
windows/src/desktop/kmshell/main/initprog.pas | 1 +
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/common/windows/delphi/general/utilstr.pas b/common/windows/delphi/general/utilstr.pas
index 59a897ad2e1..8319c37d04c 100644
--- a/common/windows/delphi/general/utilstr.pas
+++ b/common/windows/delphi/general/utilstr.pas
@@ -62,21 +62,21 @@ function WideQuotedStr(const str: WideString): WideString; deprecated; // I3310
* Creates the compiled keyboard filename by inserting the base keyboard ID
* before the .kmx extension.
*
- * @param KeyboardFileName Keyboard filename, in the form keyboardname.kmx.
- * @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
- * @return Compiled keyboard filename, in the form keyboardname-.kmx.
+ * @param KeyboardFileName Keyboard filename, in the form '[path\]keyboardid[.kmx]'
+ * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
+ * @return Compiled keyboard filename, in the form '[path\]keyboardid-.kmx'
*)
-function InsertBKLIDFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+function GetKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
(**
* Creates the dead-key compiled keyboard filename by inserting the base
* keyboard ID and -d suffix before the .kmx extension.
*
- * @param KeyboardFileName Keyboard filename, in the form keyboardname.kmx.
- * @param BaseKeyboardIDHex Base keyboard ID in hexadecimal form.
- * @return Dead-key compiled keyboard filename, in the form keyboardname--d.kmx.
+ * @param KeyboardFileName Keyboard filename, in the form '[path]\keyboardid[.kmx]'
+ * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
+ * @return Dead-key compiled keyboard filename, in the form '[path\]keyboardid--d.kmx'
*)
-function InsertBKLIDDeadkeyFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+function GetKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
implementation
@@ -436,14 +436,14 @@ function StringToRect(s: string): TRect;
Result.Bottom := StrToIntDef(s, 0);
end;
-function InsertBKLIDFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+function GetKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
begin
Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
end;
-function InsertBKLIDDeadkeyFilename(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+function GetKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
begin
- Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx'
+ Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx';
end;
end.
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index f2392d69130..3010dae5ccc 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -266,6 +266,7 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
else if s = '-mcompilekbds' then
begin
+ // Requires elevated context
FMode := fmMCompileKbds;
Inc(i);
if i > ParamCount then Exit;
From bb20b890347a624e1e80a3afd3afc98858d3f8d2 Mon Sep 17 00:00:00 2001
From: rc-swag <58423624+rc-swag@users.noreply.github.com>
Date: Fri, 18 Sep 2026 21:16:54 +1000
Subject: [PATCH 26/26] fix(windows): rename filename builder functions
---
.../windows/delphi/general/utilfiletypes.pas | 31 +++++++++++++++++++
common/windows/delphi/general/utilstr.pas | 30 ------------------
.../kmshell/install/UpgradeMnemonicLayout.pas | 4 +--
...yman.Configuration.System.BaseKeyboard.pas | 6 ++--
.../keyboard/kprecompilemnemonickeyboard.pas | 6 ++--
5 files changed, 39 insertions(+), 38 deletions(-)
diff --git a/common/windows/delphi/general/utilfiletypes.pas b/common/windows/delphi/general/utilfiletypes.pas
index f34be0933d7..28faa8804c4 100644
--- a/common/windows/delphi/general/utilfiletypes.pas
+++ b/common/windows/delphi/general/utilfiletypes.pas
@@ -91,6 +91,27 @@ function IsProjectFile(const FileName: string): Boolean;
function IsKeyboardFile(const FileName: string): Boolean;
function RemoveFileExtension(Filename, Extension: string): string;
+(**
+ * Builds the compiled keyboard filename by inserting the base keyboard ID
+ * before the .kmx extension.
+ *
+ * @param KeyboardFileName Keyboard filename, in the form '[path\]keyboardid[.kmx]'
+ * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
+ * @return Compiled keyboard filename, in the form '[path\]keyboardid-.kmx'
+ *)
+function BuildKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+
+(**
+ * Builds the dead-key compiled keyboard filename by inserting the base
+ * keyboard ID and -d suffix before the .kmx extension.
+ *
+ * @param KeyboardFileName Keyboard filename, in the form '[path]\keyboardid[.kmx]'
+ * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
+ * @return Dead-key compiled keyboard filename, in the form '[path\]keyboardid--d.kmx'
+ *)
+function BuildKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+
+
type
TKeymanFileTypeInfo = class
public
@@ -208,4 +229,14 @@ class function TKeymanFileTypeInfo.IsPackageWelcomeFile(
SameText(ExtractFileExt(Filename), ExtractFileExt(PackageFile_Welcome)));
end;
+function BuildKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+begin
+ Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
+end;
+
+function BuildKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
+begin
+ Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx';
+end;
+
end.
diff --git a/common/windows/delphi/general/utilstr.pas b/common/windows/delphi/general/utilstr.pas
index 8319c37d04c..4cd175e3601 100644
--- a/common/windows/delphi/general/utilstr.pas
+++ b/common/windows/delphi/general/utilstr.pas
@@ -58,26 +58,6 @@ function GetTokenFromCaret(line: string; var selx, sellen: Integer): string;
function WideQuotedStr(const str: WideString): WideString; deprecated; // I3310
-(**
- * Creates the compiled keyboard filename by inserting the base keyboard ID
- * before the .kmx extension.
- *
- * @param KeyboardFileName Keyboard filename, in the form '[path\]keyboardid[.kmx]'
- * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
- * @return Compiled keyboard filename, in the form '[path\]keyboardid-.kmx'
- *)
-function GetKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
-
-(**
- * Creates the dead-key compiled keyboard filename by inserting the base
- * keyboard ID and -d suffix before the .kmx extension.
- *
- * @param KeyboardFileName Keyboard filename, in the form '[path]\keyboardid[.kmx]'
- * @param BaseKeyboardIDHex Base keyboard KLID in eight digit hexadecimal form
- * @return Dead-key compiled keyboard filename, in the form '[path\]keyboardid--d.kmx'
- *)
-function GetKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
-
implementation
uses
@@ -436,14 +416,4 @@ function StringToRect(s: string): TRect;
Result.Bottom := StrToIntDef(s, 0);
end;
-function GetKeyboardFilenameWithBaseKeyboardID(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
-begin
- Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '.kmx';
-end;
-
-function GetKeyboardFilenameWithBaseKeyboardIDAndDeadkey(const KeyboardFileName: string; BaseKeyboardIDHex: string): string;
-begin
- Result := ChangeFileExt(KeyboardFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx';
-end;
-
end.
diff --git a/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas b/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
index 2639ac20728..62b75bf5660 100644
--- a/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
+++ b/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
@@ -47,7 +47,7 @@ implementation
RegistryKeys,
utilexecute,
utilkmshell,
- utilstr;
+ utilfiletypes;
const
{ CurrentMnemonicLayoutVersion = 476; // First 9.0 build with fixes for mnemonic layouts }
@@ -172,7 +172,7 @@ class procedure TUpgradeMnemonicLayout.UpgradeLayoutLanguage(
FBaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
FBaseFileName := Keyboard.Filename;
FDestFileName := OutputFileName;
- FDestDeadkeyFileName := InsertBKLIDDeadkeyFilename(FBaseFileName, FBaseKeyboardIDHex); // I4552
+ FDestDeadkeyFileName := BuildKeyboardFilenameWithBaseKeyboardIDAndDeadkey(FBaseFileName, FBaseKeyboardIDHex); // I4552
FMCompilePath := TKeymanPaths.KeymanEngineInstallPath(TKeymanPaths.S_MCompileExe);
FDestPath := ExtractFileDir(Keyboard.Filename);
diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
index a1fecdd6085..c4fb428b496 100644
--- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.BaseKeyboard.pas
@@ -48,7 +48,7 @@ implementation
uses
kmint,
utilkmshell,
- utilstr;
+ utilfiletypes;
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
var
@@ -63,8 +63,8 @@ function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
Keyboard := kmcom.Keyboards.Items[I];
KeyboardFileName := Keyboard.Filename;
if FileExists(KeyboardFileName) and
- (not FileExists(InsertBKLIDFilename(KeyboardFileName, BaseKeyboardIDHex)) or
- not FileExists(InsertBKLIDDeadkeyFilename(KeyboardFileName, BaseKeyboardIDHex))) then
+ (not FileExists(BuildKeyboardFilenameWithBaseKeyboardID(KeyboardFileName, BaseKeyboardIDHex)) or
+ not FileExists(BuildKeyboardFilenameWithBaseKeyboardIDAndDeadkey(KeyboardFileName, BaseKeyboardIDHex))) then
Exit(True);
end;
Result := False;
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
index b05ab325d15..52139f58397 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -47,7 +47,7 @@ implementation
RegistryKeys,
utilexecute,
utilkeyman,
- utilstr,
+ utilfiletypes,
utilsystem;
function GetKeyboardLayoutFileName(id: Integer): string;
@@ -84,8 +84,8 @@ procedure TKPRecompileMnemonicKeyboard.Execute(const FileName,PackageName: strin
FBaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
FBaseFileName := FDestPath + '\' + ExtractFileName(FileName); // I3581
- FDestFileName := InsertBKLIDFilename(FBaseFileName, FBaseKeyboardIDHex);
- FDestDeadkeyFileName := InsertBKLIDDeadkeyFilename(FBaseFileName, FBaseKeyboardIDHex); // I4552
+ FDestFileName := BuildKeyboardFilenameWithBaseKeyboardID(FBaseFileName, FBaseKeyboardIDHex);
+ FDestDeadkeyFileName := BuildKeyboardFilenameWithBaseKeyboardIDAndDeadkey(FBaseFileName, FBaseKeyboardIDHex); // I4552
FMCompilePath := TKeymanPaths.KeymanEngineInstallPath(TKeymanPaths.S_MCompileExe);
{ Recompile with the traditional deadkey behaviour }