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 6a631fb546..a469db480c 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -661,6 +661,8 @@ end;
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 40a65e31ce..b3f60a5067 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -11,13 +11,16 @@ type
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 @@ var
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 a469db480c..a556019abd 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -197,6 +197,7 @@ uses
Keyman.Configuration.UI.UfrmStartInstall,
RegistryKeys,
SupportXMLRenderer,
+ UfrmBaseKeyboard,
UfrmChangeHotkey,
UfrmHTML,
UfrmInstallKeyboardFromWeb,
@@ -660,11 +661,15 @@ end;
------------------------------------------------------------------------------}
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 359130f27e..8ea4331995 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -90,6 +90,7 @@ type
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
+ fmMCompile,
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
@@ -262,6 +263,13 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
+ else if s = '-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 @@ var
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
+ BaseKeyboardID: Integer;
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
@@ -540,7 +549,12 @@ begin
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 051d399b6e..91ecaa9b5f 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -109,7 +109,7 @@ type
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
+ procedure UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
procedure RefreshInstallation;
public
@@ -151,12 +151,12 @@ begin
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 7bea91450b..8635a74808 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 @@ uses
ErrorControlledRegistry,
RegistryKeys,
Glossary,
+ isadmin,
Keyman.System.BaseKeyboard,
KeymanOptionNames,
keymanerrorcodes;
@@ -112,7 +113,9 @@ end;
procedure TKeymanOptions.Apply;
var
- I, FOldBaseLayout: Integer;
+ I: Integer;
+ FOldBaseLayout: Integer;
+ FNewBaseLayout: Integer;
begin
with TRegistryErrorControlled.Create do // I3717
try
@@ -130,9 +133,10 @@ begin
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 26c92faa90..1df237b0c6 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -125,6 +125,7 @@ var
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
+ BaseKeyboardID: Integer;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
@@ -248,9 +249,11 @@ begin
// 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 30d0c275cc..7a4d5a2b39 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -27,7 +27,7 @@ uses
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 @@ uses
Winapi.Windows,
errorcontrolledregistry,
- keymancontext,
keymanerrorcodes,
KeymanPaths,
- keymanapi_TLB,
RegistryKeys,
utilexecute,
utilkeyman,
@@ -67,7 +65,7 @@ begin
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 @@ var
FExitCode: Integer;
FMCompilePath: string;
FBaseKeyboardFileName: string;
- BaseKeyboardID: Cardinal;
FDestDeadkeyFileName: string;
FCommand: string;
begin
@@ -84,9 +81,6 @@ begin
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 1759468e00..11093ac89a 100644
--- a/windows/src/engine/kmcomapi/util/internalinterfaces.pas
+++ b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
@@ -67,7 +67,7 @@ type
['{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 91ecaa9b5f..52fd698435 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -109,7 +109,7 @@ type
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout(BaseKeyboardID: Integer); // I4169
+ procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
public
@@ -151,15 +151,20 @@ begin
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 8635a74808..a60c5da041 100644
--- a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
+++ b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
@@ -136,7 +136,7 @@ begin
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 7a4d5a2b39..3d806afda2 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 11093ac89a..1759468e00 100644
--- a/windows/src/engine/kmcomapi/util/internalinterfaces.pas
+++ b/windows/src/engine/kmcomapi/util/internalinterfaces.pas
@@ -67,7 +67,7 @@ type
['{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 a556019abd..4ee970cca5 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -666,8 +666,8 @@ var
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 b3f60a5067..e9ce67d5e3 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -21,6 +21,7 @@ type
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 @@ 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;
+ Result := CompileForBaseKeyboard(BaseKeyboardID);
end;
function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
@@ -180,13 +113,33 @@ var
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 3444e7ce53..f9b5f9ac9b 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -90,7 +90,7 @@ type
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
- fmMCompile,
+ fmMCompileKbds,
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
@@ -263,9 +263,9 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = '-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 @@ begin
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 52fd698435..01b03ae3fc 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -63,7 +63,8 @@ type
TKeymanKeyboardInstalled = class( // I3581
TKeymanKeyboard,
IIntKeymanKeyboardInstalled,
- IKeymanKeyboardInstalled)
+ IKeymanKeyboardInstalled,
+ IKeymanKeyboardInstalled2)
private
FRegKeyboard: TRegKeyboard;
FVisualKeyboard: IKeymanVisualKeyboard;
@@ -112,6 +113,9 @@ type
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 @@ begin
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 a60c5da041..1848428033 100644
--- a/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
+++ b/windows/src/engine/kmcomapi/com/options/keymanoptions.pas
@@ -112,32 +112,8 @@ begin
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 3ceb5b15cd..786ce6c9b2 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,6 +1569,16 @@ type
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 ac20310a87..9eb63fbd68 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 c6ee3564ae..3cc8dcc901 100644
--- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas
+++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas
@@ -18,9 +18,9 @@ type
FPackage: IKeymanPackageInstalled; const BCP47: string); static;
public
class function BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean; static;
- class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string): Boolean; overload; static;
- class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean; overload; static;
- class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean; overload; static;
+ class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string; BaseKeyboardID: Integer): Boolean; overload; static;
+ class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean; overload; static;
+ class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean; overload; static;
end;
implementation
@@ -35,29 +35,30 @@ uses
Keyman.Configuration.UI.KeymanProtocolHandler,
Keyman.Configuration.UI.MitigationForWin10_1803,
kmint,
+ KeymanOptionNames,
UfrmHTML,
UfrmInstallKeyboard;
class function TInstallFile.Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean;
- const LogFile: string): Boolean;
+ const LogFile: string; BaseKeyboardID: Integer): Boolean;
begin
if TKeymanProtocolHandler.CanHandle(FirstKeyboardFileName) then
begin
- Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile);
+ Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, BaseKeyboardID);
end
else if (KeyboardFileNames.Count > 1) or (Pos('=', FirstKeyboardFileName) > 0) then
begin
- Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent)
+ Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent, BaseKeyboardID)
end
// TODO: support bare package ids from command line (if it does not include a file extension, assume it is a .kmp and try and download it)
// else if IsNotPackageOrKeyboardFile then
else
begin
- Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '');
+ Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '', BaseKeyboardID);
end;
end;
-class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean;
+class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean;
var
n: Integer;
InstalledKeyboards: array of IKeymanKeyboardInstalled;
@@ -77,7 +78,7 @@ begin
begin
if ASilent then
begin
- InstallKeyboard(LogFile, BCP47);
+ InstallKeyboard(LogFile, BCP47, BaseKeyboardID);
Result := True;
end
else
@@ -139,7 +140,7 @@ end;
/// This is the handler for the `-i` parameter, e.g.
/// kmshell -i khmer_angkor.kmp c:\temp\sil_euro_latin.kmp=fr
///
-class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean;
+class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean;
var
i, j: Integer;
FPackage: IKeymanPackageInstalled;
@@ -170,7 +171,7 @@ begin
end;
if IsPackage then
begin
- FPackage := (kmcom.Packages as IKeymanPackagesInstalled2).Install2(FileName, True);
+ FPackage := (kmcom.Packages as IKeymanPackagesInstalled3).Install3(FileName, True, BaseKeyboardID);
if Length(FilenameBCP47) > 1
then RegisterKeyboardPackageLanguage(FPackage, FilenameBCP47[1])
else RegisterKeyboardPackageLanguage(FPackage, '');
@@ -178,7 +179,7 @@ begin
end
else
begin
- FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled2).Install2(FileName, True);
+ FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled3).Install3(FileName, True, BaseKeyboardID);
if (Length(FilenameBCP47) > 1) and (Trim(FilenameBCP47[1]) <> '')
then BCP47Tag := FilenameBCP47[1]
else BCP47Tag := TTIPMaintenance.GetFirstLanguage(FKeyboard);
@@ -209,6 +210,7 @@ end;
class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean;
var
dlgOpen: TOpenDialog;
+ BaseKeyboardID : Integer;
begin
dlgOpen := TOpenDialog.Create(nil);
try
@@ -216,9 +218,9 @@ begin
'Keyman files (*.kmx, *.kxx, *.kmp)|*.kmx;*.kxx;*.kmp|Keyman keyboards (*.kmx,*.kxx)' +
'|*.kmx;*.kxx|Keyman packages (*.kmp)|*.kmp|All files (*.*)|*.*';
dlgOpen.Title := 'Install Keyman Keyboard';
-
+ BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
if dlgOpen.Execute then
- Result := Execute(Owner, dlgOpen.FileName, False, False, '', '')
+ Result := Execute(Owner, dlgOpen.FileName, False, False, '', '', BaseKeyboardID)
else
Result := False;
finally
diff --git a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas
index 6f13f6777b..60ac8ae43c 100644
--- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas
+++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas
@@ -17,13 +17,13 @@ type
FDownloadURL: string;
frmDownloadProgress: TfrmDownloadProgress;
function DoHandle(Owner: TComponent; const url: string; ASilent,
- ANoWelcome: Boolean; const ALogFile: string): Boolean;
+ ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean;
procedure DoDownload(AOwner: TfrmDownloadProgress; var Result: Boolean);
procedure HttpReceiveData(const Sender: TObject; AContentLength,
AReadCount: Int64; var Abort: Boolean);
public
class function CanHandle(const url: string): Boolean; static;
- class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string): Boolean; static;
+ class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean; static;
end;
implementation
@@ -51,13 +51,13 @@ end;
class function TKeymanProtocolHandler.Handle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
- const ALogFile: string): Boolean;
+ const ALogFile: string; BaseKeyboardID: Integer): Boolean;
var
h: TKeymanProtocolHandler;
begin
h := TKeymanProtocolHandler.Create;
try
- Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile);
+ Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile, BaseKeyboardID);
finally
h.Free;
end;
@@ -65,7 +65,7 @@ end;
function TKeymanProtocolHandler.DoHandle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
- const ALogFile: string): Boolean;
+ const ALogFile: string; BaseKeyboardID: Integer): Boolean;
var
FTempDir: string;
PackageID, BCP47: string;
@@ -98,7 +98,7 @@ begin
end;
// TODO: this makes a circular dependency, refactor it out!
- Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47);
+ Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID);
finally
if FileExists(FDownloadFilename) then
diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
index 6d79811a80..775aa1ca2e 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
@@ -74,6 +74,7 @@ uses
Vcl.StdCtrls,
keymanapi_TLB,
+ KeymanOptionNames,
UfrmKeymanBase,
UfrmWebContainer;
@@ -102,7 +103,7 @@ type
protected
procedure FireCommand(const command: WideString; params: TStringList); override;
public
- procedure InstallKeyboard(const ALogFile, BCP47Tag: string);
+ procedure InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
property DefaultBCP47Tag: string read FDefaultBCP47Tag write SetDefaultBCP47Tag;
property InstallFile: string read FInstallFile write SetInstallFile;
property Silent: Boolean read FSilent write FSilent;
@@ -271,6 +272,7 @@ end;
procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TStringList);
var
BCP47Tag: string;
+ BaseKeyboardID :Integer;
begin
BCP47Tag := '';
if (command = 'keyboard_install') and kmcom.SystemInfo.IsAdministrator then // I4172
@@ -283,7 +285,8 @@ begin
Manager.Title := 'Installing Keyboard';
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
- InstallKeyboard('', BCP47Tag);
+ BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
+ InstallKeyboard('', BCP47Tag, BaseKeyboardID);
Result := True;
end
);
@@ -299,6 +302,7 @@ begin
var
t: TTempFile;
ExecParams: string;
+ BaseKeyboardString :string;
begin
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
@@ -306,8 +310,9 @@ begin
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
t := TTempFileManager.Get('.log');
+ BaseKeyboardString := IntToHex(kmcom.Options[KeymanOptionName(koBaseLayout)].Value, 8);
try
- ExecParams := '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
+ ExecParams := '-log "'+t.Name+'" -bkd "'+BaseKeyboardString+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
' -nowelcome '+TTIPMaintenance.GetUserDefaultLangParameterString;
KL.Log('Calling elevated kmshell %s', [ExecParams]);
if WaitForElevatedConfiguration(GetForegroundWindow, ExecParams) = 0 then
@@ -358,7 +363,7 @@ end;
------------------------------------------------------------------------------}
// TODO: move this to TInstallFile
-procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string);
+procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
@@ -400,7 +405,7 @@ begin
kbd := nil;
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh;
- FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile2).Install2(True);
+ FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile3).Install3(True, BaseKeyboardID);
if not InstallTipForKeyboard(BCP47Tag) then
begin
// TODO can we return a failure code?
@@ -461,7 +466,7 @@ begin
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh; // I2169
- (FPackage as IKeymanPackageFile2).Install2(True);
+ (FPackage as IKeymanPackageFile3).Install3(True, BaseKeyboardID);
kmcom.Refresh;
diff --git a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
index aff3251037..ed236d489d 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
@@ -87,6 +87,7 @@ uses
Keyman.Configuration.UI.InstallFile,
Keyman.System.LocaleStrings,
kmint,
+ KeymanOptionNames,
MessageIdentifierConsts,
Upload_Settings,
utilfiletypes,
@@ -213,6 +214,7 @@ end;
procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string);
var
FTempDir: string;
+ BaseKeyboardID: Integer;
begin
FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679
try
@@ -230,8 +232,8 @@ begin
finally
frmDownloadProgress.Free;
end;
-
- if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47) then
+ BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
+ if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID) then
ModalResult := mrOk;
finally
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index f9b5f9ac9b..0f0cc6f367 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -206,7 +206,7 @@ end;
function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean;
- var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
+ var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID, FBaseKeyboard: Integer): Boolean;
var
s: string;
i: Integer;
@@ -263,6 +263,7 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
+ else if s = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
@@ -329,7 +330,7 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
- const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
+ const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward;
procedure Run;
var
@@ -340,7 +341,7 @@ var
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID: Integer;
+ FDefaultLangID, FBaseKeyboard: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -349,7 +350,7 @@ begin
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
- if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
+ if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
@@ -357,7 +358,7 @@ begin
if not LoadKMCOM then Exit;
try
- RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
+ RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard);
finally
kmcom := nil;
end;
@@ -396,7 +397,7 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
- FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
+ FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
@@ -559,7 +560,7 @@ begin
else ExitCode := 1;
fmInstall:
- if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile)
+ if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile, FBaseKeyboard)
then ExitCode := 0
else ExitCode := 1;
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
index 5ea1e74265..b7255869b7 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
@@ -37,7 +37,7 @@ uses
keymankeyboard, keymancontext, Classes, PackageInfo, keymankeyboardlanguagesfile;
type
- TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2)
+ TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2, IKeymanKeyboardFile3)
private
FFileName: WideString;
FError: Boolean;
@@ -52,6 +52,7 @@ type
{ IKeymanKeyboardFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
{ IKeymanKeyboard }
function Get_Copyright: WideString; override; safecall;
@@ -252,7 +253,7 @@ procedure TKeymanKeyboardFile.Install(Force: WordBool);
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
+ Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
finally
Free;
end;
@@ -264,7 +265,23 @@ var
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FFileName, '', [], nil, Force);
+ Execute(FFileName, '', [], nil, Force, 0);
+ finally
+ Free;
+ end;
+
+ kki := Context.Keyboards as IKeymanKeyboardsInstalled;
+ kki.Refresh;
+ Result := kki.Items[FFileName];
+end;
+
+function TKeymanKeyboardFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled;
+var
+ kki: IKeymanKeyboardsInstalled;
+begin
+ with TKPInstallKeyboard.Create(Context) do
+ try
+ Execute(FFileName, '', [], nil, Force, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
index f5f8b74448..b37e0dfce0 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
@@ -37,7 +37,8 @@ uses
keymanerrorcodes, keymankeyboardinstalled, keymankeyboard, internalinterfaces;
type
- TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled) // I4376
+ TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled,
+ IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled3) // I4376
private
FKeyboards: TKeyboardList;
procedure TriggerWindowsLanguageSync;
@@ -55,6 +56,7 @@ type
procedure Install(const Filename: WideString; Force: WordBool); safecall;
procedure Apply; safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; safecall;
+ function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
procedure RefreshInstalledKeyboards; safecall;
{ IIntKeymanKeyboardsInstalled }
@@ -101,7 +103,7 @@ procedure TKeymanKeyboardsInstalled.Install(const Filename: WideString; Force: W
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
+ Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
finally
Free;
end;
@@ -112,7 +114,21 @@ function TKeymanKeyboardsInstalled.Install2(const Filename: WideString;
begin
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FileName, '', [], nil, Force);
+ Execute(FileName, '', [], nil, Force, 0);
+ finally
+ Free;
+ end;
+
+ DoRefresh;
+ Result := Get_Items(FileName);
+end;
+
+function TKeymanKeyboardsInstalled.Install3(const Filename: WideString;
+ Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled;
+begin
+ with TKPInstallKeyboard.Create(Context) do
+ try
+ Execute(FileName, '', [], nil, Force, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
index 14b207e229..28ef2d064a 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
@@ -1,18 +1,18 @@
(*
Name: keymanpackagefile
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 20 Jun 2006
Modified Date: 29 Mar 2010
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 20 Jun 2006 - mcdurdin - Initial version
01 Aug 2006 - mcdurdin - Avoid processmessages in unzip
04 Dec 2006 - mcdurdin - Add Serialize function, support ShortcutRootPath in installation
@@ -37,7 +37,7 @@ uses
keymanpackagecontentfiles, StdVcl, kmpinffile, KeymanContext, Graphics, Classes, internalinterfaces;
type
- TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2)
+ TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2, IKeymanPackageFile3)
private
FSourcePath: string;
FSubFiles: IKeymanPackageContentFiles;
@@ -74,6 +74,7 @@ type
{ IKeymanPackageFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext; const Filename: Widestring);
destructor Destroy; override;
@@ -175,7 +176,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(FFileName, o);
+ Execute(FFileName, o, 0);
finally
Free;
end;
@@ -191,7 +192,27 @@ begin
o := [];
if Force then
Include(o, ipForce);
- Execute(FFileName, o);
+ Execute(FFileName, o, 0);
+ finally
+ Free;
+ end;
+
+ kpi := Context.Packages as IKeymanPackagesInstalled;
+ kpi.Refresh;
+ Result := kpi.Items[FFileName];
+end;
+
+function TKeymanPackageFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled;
+var
+ o: TKPInstallPackageOptions;
+ kpi: IKeymanPackagesInstalled;
+begin
+ with TKPInstallPackage.Create(Context) do
+ try
+ o := [];
+ if Force then
+ Include(o, ipForce);
+ Execute(FFileName, o, BaseKeyboardID);
finally
Free;
end;
@@ -211,7 +232,7 @@ var
begin
if not FileExists(FFileName) then
raise Exception.Create('File '+FFileName+' does not exist.');
-
+
if GetTempPath(260, buf) = 0 then
raise Exception.Create('Unable to get temporary path: ' + IntToHex(GetLastError, 8) + ' ' + SysErrorMessage(GetLastError));
FTempOutPath := buf;
diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
index 9dd9f1a52a..821a38bdc5 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
@@ -38,7 +38,8 @@ type
property Items[Index: Integer]: IIntKeymanPackageInstalled read GetItem write SetItem; default;
end;
- TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, IKeymanPackagesInstalled, IKeymanPackagesInstalled2)
+ TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject,
+ IKeymanPackagesInstalled, IKeymanPackagesInstalled2, IKeymanPackagesInstalled3)
private
FPackages: TPackageList;
protected
@@ -51,6 +52,7 @@ type
function IndexOf(const ID: WideString): Integer; safecall;
procedure Install(const Filename: WideString; Force: WordBool); safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
+ function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext);
destructor Destroy; override;
@@ -118,7 +120,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(Filename, o);
+ Execute(Filename, o, 0);
finally
Free;
end;
@@ -136,7 +138,29 @@ begin
o := [];
if Force then
Include(o, ipForce);
- Execute(Filename, o);
+ Execute(Filename, o, 0);
+ finally
+ Free;
+ end;
+
+ DoRefresh;
+ Result := Get_Items(Filename);
+
+ KL.MethodExit(Self, 'Install2');
+end;
+
+function TKeymanPackagesInstalled.Install3(const Filename: WideString;
+ Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled;
+var
+ o: TKPInstallPackageOptions;
+begin
+ KL.MethodEnter(Self, 'Install2', [Filename, Force]);
+ with TKPInstallPackage.Create(Context) do
+ try
+ o := [];
+ if Force then
+ Include(o, ipForce);
+ Execute(Filename, o, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/keymanapi_TLB.pas b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
index 786ce6c9b2..7246c9173f 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,6 +1569,17 @@ type
procedure RefreshInstalledKeyboards; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardsInstalled3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
+// *********************************************************************//
+ IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
+ ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
+ function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
+ procedure RefreshInstalledKeyboards; safecall;
+ end;
+
// *********************************************************************//
// Interface: IKeymanKeyboardInstalled2
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1610,6 +1621,16 @@ type
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanPackagesInstalled3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
+// *********************************************************************//
+ IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled)
+ ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
+ function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall;
+ end;
+
// *********************************************************************//
// DispIntf: IKeymanPackagesInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1639,6 +1660,16 @@ type
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardFile3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8}
+// *********************************************************************//
+ IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
+ ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
+ end;
+
// *********************************************************************//
// DispIntf: IKeymanKeyboardFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1677,6 +1708,17 @@ type
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanPackageFile3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
+// *********************************************************************//
+ IKeymanPackageFile3 = interface(IKeymanPackageFile)
+ ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
+ end;
+
+
// *********************************************************************//
// DispIntf: IKeymanPackageFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index 9eb63fbd68..91f49822b5 100644
--- a/windows/src/engine/kmcomapi/kmcomapi.ridl
+++ b/windows/src/engine/kmcomapi/kmcomapi.ridl
@@ -66,6 +66,10 @@ library keymanapi
interface IKeymanPackageFile2;
interface IKeymanKeyboardLanguageInstalled2;
interface IKeymanKeyboardLanguagesInstalled2;
+ interface IKeymanKeyboardFile3;
+ interface IKeymanPackageFile3;
+ interface IKeymanKeyboardsInstalled3;
+ interface IKeymanPackagesInstalled3;
interface IKeymanBCP47Canonicalization;
interface IKeymanDefaultLanguage;
@@ -976,6 +980,60 @@ library keymanapi
HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
+ [
+ uuid(8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4),
+ version(19.0),
+ helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanKeyboardFile3"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardFile3: IKeymanKeyboardFile
+ {
+ [id(0x00000121)]
+ HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
+ };
+
+ [
+ uuid(C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7),
+ version(19.0),
+ helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackageFile3"),
+ dual,
+ oleautomation
+ ]
+
+ interface IKeymanPackageFile3: IKeymanPackageFile
+ {
+ [id(0x00000124)]
+ HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageFile** Package);
+ };
+
+
+ [
+ uuid(B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641),
+ version(19.0),
+ helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2\3"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanKeyboardsInstalled3: IKeymanKeyboardsInstalled
+ {
+ [id(0x00000122)]
+ HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
+ };
+
+ [
+ uuid(3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458),
+ version(19.0),
+ helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackagesInstalled3"),
+ dual,
+ oleautomation
+ ]
+ interface IKeymanPackagesInstalled3: IKeymanPackagesInstalled
+ {
+ [id(0x00000123)]
+ HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageInstalled** PackageResult);
+ };
+
[
uuid(9B43B6BC-C622-47EF-915E-6780CF53BAAA),
version(14.0),
diff --git a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
index 1df237b0c6..6d3bd1f3ed 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -64,7 +64,7 @@ type
ikLegacyRegisterAndInstallProfiles);
TKPInstallKeyboard = class(TKPBase)
- procedure Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
+ procedure Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
procedure RegisterProfiles(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; PackageLanguageMetadata: TPackageKeyboardLanguageList);
private
procedure LegacyRegisterAndInstallLanguageProfile(Langs: array of Integer;
@@ -112,7 +112,7 @@ uses
utiltsf,
keymanapi_TLB;
-procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
+procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
var
ki: TKeyboardInfo;
FDestPath: string;
@@ -125,7 +125,9 @@ var
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
- BaseKeyboardID: Integer;
+ ElevatedBaseKeyboardID: Integer;
+ KeymanContext: TKeymanContext;
+ RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
@@ -246,14 +248,19 @@ begin
KL.Log(FLogText);
end;
- // Recompile a mnemonic layout to the user's selected base layout
+ // Recompile a mnemonic layout to the user's selected base layout. If
+ // the baselayout has not been passed through (=0) then use the current
+ // process configured value which is likely the Admin user
if ki.MnemonicLayout then // I4169
begin
- with Context as TKeymanContext do
- BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;
- with TKPRecompileMnemonicKeyboard.Create(Context) do
+ KeymanContext := Context as TKeymanContext;
+ ElevatedBaseKeyboardID := (KeymanContext.Options as IKeymanOptions).Items['koBaseLayout'].Value;
+ RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context);
try
- Execute(FDestFileName, PackageID, BaseKeyboardID);
+ if (BaseKeyboardID = 0) then
+ RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, ElevatedBaseKeyboardID)
+ else
+ RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
Free;
end;
diff --git a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
index 98edfbf3fb..4ab33cdfee 100644
--- a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
+++ b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
@@ -50,7 +50,7 @@ type
TKPInstallPackage = class(TKPBase)
public
- procedure Execute(const FileName: string; Options: TKPInstallPackageOptions);
+ procedure Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
end;
implementation
@@ -85,7 +85,7 @@ uses
{ TKPInstallPackage }
-procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions);
+procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
function GetHHIcon: string;
var
buf: array[0..260] of char;
@@ -112,7 +112,7 @@ var
FErrorValue: Cardinal;
FSrcFileName: string;
- procedure InstallKeyboard(FileName: string);
+ procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer);
var
FOptions: TKPInstallKeyboardOptions;
kbd: TPackageKeyboard;
@@ -132,7 +132,7 @@ var
with TKPInstallKeyboard.Create(Context) do
try
- Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options);
+ Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options, BaseKeyboardID);
finally
Free;
end;
@@ -253,12 +253,12 @@ begin
begin
case inf.Files[i].FileType of
ftKeymanFile:
- InstallKeyboard(dest + inf.Files[i].FileName);
+ InstallKeyboard(dest + inf.Files[i].FileName, BaseKeyboardID);
ftPackageFile:
with TKPInstallPackage.Create(Context) do
try
- Execute(dest + inf.Files[i].FileName, Options);
+ Execute(dest + inf.Files[i].FileName, Options, BaseKeyboardID);
finally
Free;
end;
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 | 251 ++++++++++++++----
windows/src/engine/kmcomapi/kmcomapi.ridl | 108 ++++----
3 files changed, 252 insertions(+), 109 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 0f0cc6f367..b1afe4e10f 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -263,7 +263,7 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end
+ else if s = '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 7246c9173f..3c436dc5d9 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@ unit keymanapi_TLB;
// ************************************************************************ //
// $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 @@ const
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 @@ type
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
+ IKeymanKeyboardInstalled2 = interface;
+ IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -258,6 +265,14 @@ type
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;
@@ -1569,27 +1584,6 @@ type
procedure RefreshInstalledKeyboards; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardsInstalled3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
-// *********************************************************************//
- IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
- ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
- function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
- procedure RefreshInstalledKeyboards; safecall;
- end;
-
-// *********************************************************************//
-// Interface: IKeymanKeyboardInstalled2
-// Flags: (4416) Dual OleAutomation Dispatchable
-// 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
@@ -1611,6 +1605,51 @@ type
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
@@ -1621,16 +1660,6 @@ type
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanPackagesInstalled3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
-// *********************************************************************//
- IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled)
- ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
- function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall;
- end;
-
// *********************************************************************//
// DispIntf: IKeymanPackagesInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1660,16 +1689,6 @@ type
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardFile3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8}
-// *********************************************************************//
- IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
- ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
- end;
-
// *********************************************************************//
// DispIntf: IKeymanKeyboardFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1708,17 +1727,6 @@ type
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanPackageFile3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
-// *********************************************************************//
- IKeymanPackageFile3 = interface(IKeymanPackageFile)
- ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
- end;
-
-
// *********************************************************************//
// DispIntf: IKeymanPackageFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1820,6 +1828,143 @@ type
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 91f49822b5..ecfff3d707 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,60 +980,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),
@@ -1079,6 +1025,58 @@ library keymanapi
HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
};
+ [
+ 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\x03"),
+ 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(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 b1afe4e10f..f4d2a4161d 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -263,7 +263,7 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = 'bkd' then begin Inc(i); FBaseKeyboard := 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 3c436dc5d9..b0530cb94a 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1873,7 +1873,7 @@ type
// *********************************************************************//
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 @@ type
// *********************************************************************//
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 ecfff3d707..0b2366c144 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 6d3bd1f3ed..1d198264cb 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -262,7 +262,7 @@ begin
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 e9ce67d5e3..1f136871e6 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -21,7 +21,7 @@ type
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 @@ begin
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 @@ begin
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 e2d28b88d2..e4ce8316d3 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 371ce4cd49..ca611b40e4 100644
--- a/windows/src/desktop/kmshell/kmshell.dproj
+++ b/windows/src/desktop/kmshell/kmshell.dproj
@@ -358,6 +358,7 @@
+
Cfg_2
@@ -419,6 +420,12 @@
False
+
+
+ kmshell.exe
+ true
+
+
.\
@@ -431,12 +438,6 @@
true
-
-
- kmshell.exe
- true
-
-
1
diff --git a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
index 1f136871e6..56e7c442b4 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -19,9 +19,6 @@ type
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 @@ begin
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 100fd24fd2..599566b91c 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -174,6 +174,7 @@ uses
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 f4d2a4161d..2d6cc1e6d2 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -115,6 +115,7 @@ uses
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 0000000000..44488179c9
--- /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 2d6cc1e6d2..6457542bca 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -264,7 +264,7 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = '-bkd' then begin Inc(i); FBaseKeyboard := 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 b0530cb94a..3c436dc5d9 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1873,7 +1873,7 @@ type
// *********************************************************************//
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 @@ type
// *********************************************************************//
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 0b2366c144..ecfff3d707 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 | 251 ++++--------------
windows/src/engine/kmcomapi/kmcomapi.ridl | 108 ++++----
3 files changed, 109 insertions(+), 252 deletions(-)
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index 6457542bca..3143d72828 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -264,7 +264,7 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = 'bkd' then begin Inc(i); FBaseKeyboard := 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 3c436dc5d9..7246c9173f 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@ unit keymanapi_TLB;
// ************************************************************************ //
// $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 @@ const
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 @@ type
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
- IKeymanKeyboardInstalled2 = interface;
- IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -265,14 +258,6 @@ type
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;
@@ -1584,6 +1569,27 @@ type
procedure RefreshInstalledKeyboards; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardsInstalled3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
+// *********************************************************************//
+ IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
+ ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
+ function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
+ procedure RefreshInstalledKeyboards; safecall;
+ end;
+
+// *********************************************************************//
+// Interface: IKeymanKeyboardInstalled2
+// Flags: (4416) Dual OleAutomation Dispatchable
+// 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
@@ -1605,51 +1611,6 @@ type
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
@@ -1660,6 +1621,16 @@ type
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanPackagesInstalled3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
+// *********************************************************************//
+ IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled)
+ ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
+ function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall;
+ end;
+
// *********************************************************************//
// DispIntf: IKeymanPackagesInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1689,6 +1660,16 @@ type
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanKeyboardFile3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8}
+// *********************************************************************//
+ IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
+ ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
+ end;
+
// *********************************************************************//
// DispIntf: IKeymanKeyboardFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1727,6 +1708,17 @@ type
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
end;
+// *********************************************************************//
+// Interface: IKeymanPackageFile3
+// Flags: (4416) Dual OleAutomation Dispatchable
+// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
+// *********************************************************************//
+ IKeymanPackageFile3 = interface(IKeymanPackageFile)
+ ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
+ function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
+ end;
+
+
// *********************************************************************//
// DispIntf: IKeymanPackageFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1828,143 +1820,6 @@ type
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 ecfff3d707..91f49822b5 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,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),
@@ -1025,58 +1079,6 @@ library keymanapi
HRESULT _stdcall Add([in] BSTR BCP47Tag, [out, retval] IKeymanKeyboardLanguageInstalled** Result);
};
- [
- 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\x03"),
- 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(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 3cc8dcc901..c6ee3564ae 100644
--- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas
+++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.InstallFile.pas
@@ -18,9 +18,9 @@ type
FPackage: IKeymanPackageInstalled; const BCP47: string); static;
public
class function BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean; static;
- class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string; 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 @@ uses
Keyman.Configuration.UI.KeymanProtocolHandler,
Keyman.Configuration.UI.MitigationForWin10_1803,
kmint,
- KeymanOptionNames,
UfrmHTML,
UfrmInstallKeyboard;
class function TInstallFile.Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean;
- const LogFile: string; 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 @@ begin
begin
if ASilent then
begin
- InstallKeyboard(LogFile, BCP47, BaseKeyboardID);
+ InstallKeyboard(LogFile, BCP47);
Result := True;
end
else
@@ -140,7 +139,7 @@ end;
/// This is the handler for the `-i` parameter, e.g.
/// kmshell -i khmer_angkor.kmp c:\temp\sil_euro_latin.kmp=fr
///
-class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; 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 @@ begin
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 @@ begin
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 @@ end;
class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean;
var
dlgOpen: TOpenDialog;
- BaseKeyboardID : Integer;
begin
dlgOpen := TOpenDialog.Create(nil);
try
@@ -218,9 +216,9 @@ begin
'Keyman files (*.kmx, *.kxx, *.kmp)|*.kmx;*.kxx;*.kmp|Keyman keyboards (*.kmx,*.kxx)' +
'|*.kmx;*.kxx|Keyman packages (*.kmp)|*.kmp|All files (*.*)|*.*';
dlgOpen.Title := 'Install Keyman Keyboard';
- BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
+
if dlgOpen.Execute then
- Result := Execute(Owner, dlgOpen.FileName, False, False, '', '', 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 60ac8ae43c..6f13f6777b 100644
--- a/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas
+++ b/windows/src/desktop/kmshell/install/Keyman.Configuration.UI.KeymanProtocolHandler.pas
@@ -17,13 +17,13 @@ type
FDownloadURL: string;
frmDownloadProgress: TfrmDownloadProgress;
function DoHandle(Owner: TComponent; const url: string; ASilent,
- ANoWelcome: Boolean; const ALogFile: string; 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 @@ end;
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 @@ end;
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 @@ begin
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 775aa1ca2e..6d79811a80 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboard.pas
@@ -74,7 +74,6 @@ uses
Vcl.StdCtrls,
keymanapi_TLB,
- KeymanOptionNames,
UfrmKeymanBase,
UfrmWebContainer;
@@ -103,7 +102,7 @@ type
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 @@ end;
procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TStringList);
var
BCP47Tag: string;
- BaseKeyboardID :Integer;
begin
BCP47Tag := '';
if (command = 'keyboard_install') and kmcom.SystemInfo.IsAdministrator then // I4172
@@ -285,8 +283,7 @@ begin
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 @@ begin
var
t: TTempFile;
ExecParams: string;
- BaseKeyboardString :string;
begin
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
@@ -310,9 +306,8 @@ begin
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
t := TTempFileManager.Get('.log');
- BaseKeyboardString := IntToHex(kmcom.Options[KeymanOptionName(koBaseLayout)].Value, 8);
try
- ExecParams := '-log "'+t.Name+'" -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 @@ end;
------------------------------------------------------------------------------}
// 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 @@ begin
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 @@ begin
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 ed236d489d..aff3251037 100644
--- a/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
+++ b/windows/src/desktop/kmshell/install/UfrmInstallKeyboardFromWeb.pas
@@ -87,7 +87,6 @@ uses
Keyman.Configuration.UI.InstallFile,
Keyman.System.LocaleStrings,
kmint,
- KeymanOptionNames,
MessageIdentifierConsts,
Upload_Settings,
utilfiletypes,
@@ -214,7 +213,6 @@ end;
procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string);
var
FTempDir: string;
- BaseKeyboardID: Integer;
begin
FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679
try
@@ -232,8 +230,8 @@ begin
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 3143d72828..64fc2cd214 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -207,7 +207,7 @@ end;
function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean;
- var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID, FBaseKeyboard: Integer): Boolean;
+ var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
var
s: string;
i: Integer;
@@ -264,7 +264,6 @@ begin
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
- else if s = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
@@ -331,7 +330,7 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
- const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward;
+ const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
procedure Run;
var
@@ -342,7 +341,7 @@ var
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID, FBaseKeyboard: Integer;
+ FDefaultLangID: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -351,7 +350,7 @@ begin
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
- if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, 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 @@ begin
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 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
- FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer);
+ FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
@@ -561,7 +560,7 @@ begin
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 b7255869b7..5ea1e74265 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardfile.pas
@@ -37,7 +37,7 @@ uses
keymankeyboard, keymancontext, Classes, PackageInfo, keymankeyboardlanguagesfile;
type
- TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2, IKeymanKeyboardFile3)
+ TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2)
private
FFileName: WideString;
FError: Boolean;
@@ -52,7 +52,6 @@ type
{ IKeymanKeyboardFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
{ IKeymanKeyboard }
function Get_Copyright: WideString; override; safecall;
@@ -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 @@ var
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 b37e0dfce0..f5f8b74448 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardsinstalled.pas
@@ -37,8 +37,7 @@ uses
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 @@ type
procedure Install(const Filename: WideString; Force: WordBool); safecall;
procedure Apply; safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; safecall;
- function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
procedure RefreshInstalledKeyboards; safecall;
{ IIntKeymanKeyboardsInstalled }
@@ -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 28ef2d064a..14b207e229 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagefile.pas
@@ -1,18 +1,18 @@
(*
Name: keymanpackagefile
Copyright: Copyright (C) SIL International.
- Documentation:
- Description:
+ Documentation:
+ Description:
Create Date: 20 Jun 2006
Modified Date: 29 Mar 2010
Authors: mcdurdin
- Related Files:
- Dependencies:
+ Related Files:
+ Dependencies:
- Bugs:
- Todo:
- Notes:
+ Bugs:
+ Todo:
+ Notes:
History: 20 Jun 2006 - mcdurdin - Initial version
01 Aug 2006 - mcdurdin - Avoid processmessages in unzip
04 Dec 2006 - mcdurdin - Add Serialize function, support ShortcutRootPath in installation
@@ -37,7 +37,7 @@ uses
keymanpackagecontentfiles, StdVcl, kmpinffile, KeymanContext, Graphics, Classes, internalinterfaces;
type
- TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2, IKeymanPackageFile3)
+ TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2)
private
FSourcePath: string;
FSubFiles: IKeymanPackageContentFiles;
@@ -74,7 +74,6 @@ type
{ IKeymanPackageFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext; const Filename: Widestring);
destructor Destroy; override;
@@ -176,7 +175,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(FFileName, o, 0);
+ Execute(FFileName, o);
finally
Free;
end;
@@ -192,27 +191,7 @@ begin
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 @@ var
begin
if not FileExists(FFileName) then
raise Exception.Create('File '+FFileName+' does not exist.');
-
+
if GetTempPath(260, buf) = 0 then
raise Exception.Create('Unable to get temporary path: ' + IntToHex(GetLastError, 8) + ' ' + SysErrorMessage(GetLastError));
FTempOutPath := buf;
diff --git a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
index 821a38bdc5..9dd9f1a52a 100644
--- a/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/packages/keymanpackagesinstalled.pas
@@ -38,8 +38,7 @@ type
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 @@ type
function IndexOf(const ID: WideString): Integer; safecall;
procedure Install(const Filename: WideString; Force: WordBool); safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
- function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext);
destructor Destroy; override;
@@ -120,7 +118,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
- Execute(Filename, o, 0);
+ Execute(Filename, o);
finally
Free;
end;
@@ -138,29 +136,7 @@ begin
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 7246c9173f..786ce6c9b2 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -1569,17 +1569,6 @@ type
procedure RefreshInstalledKeyboards; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardsInstalled3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
-// *********************************************************************//
- IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
- ['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
- function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
- procedure RefreshInstalledKeyboards; safecall;
- end;
-
// *********************************************************************//
// Interface: IKeymanKeyboardInstalled2
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1621,16 +1610,6 @@ type
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanPackagesInstalled3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
-// *********************************************************************//
- IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled)
- ['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
- function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall;
- end;
-
// *********************************************************************//
// DispIntf: IKeymanPackagesInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1660,16 +1639,6 @@ type
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanKeyboardFile3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8}
-// *********************************************************************//
- IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
- ['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
- end;
-
// *********************************************************************//
// DispIntf: IKeymanKeyboardFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@@ -1708,17 +1677,6 @@ type
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
end;
-// *********************************************************************//
-// Interface: IKeymanPackageFile3
-// Flags: (4416) Dual OleAutomation Dispatchable
-// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
-// *********************************************************************//
- IKeymanPackageFile3 = interface(IKeymanPackageFile)
- ['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
- function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
- end;
-
-
// *********************************************************************//
// DispIntf: IKeymanPackageFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
diff --git a/windows/src/engine/kmcomapi/kmcomapi.ridl b/windows/src/engine/kmcomapi/kmcomapi.ridl
index 91f49822b5..9eb63fbd68 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 1d198264cb..1205d77f72 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -64,7 +64,7 @@ type
ikLegacyRegisterAndInstallProfiles);
TKPInstallKeyboard = class(TKPBase)
- procedure Execute(const FileName: 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 @@ uses
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 @@ var
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 @@ begin
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 4ab33cdfee..98edfbf3fb 100644
--- a/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
+++ b/windows/src/engine/kmcomapi/processes/package/kpinstallpackage.pas
@@ -50,7 +50,7 @@ type
TKPInstallPackage = class(TKPBase)
public
- procedure Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
+ procedure Execute(const FileName: string; Options: TKPInstallPackageOptions);
end;
implementation
@@ -85,7 +85,7 @@ uses
{ 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 @@ var
FErrorValue: Cardinal;
FSrcFileName: string;
- procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer);
+ procedure InstallKeyboard(FileName: string);
var
FOptions: TKPInstallKeyboardOptions;
kbd: TPackageKeyboard;
@@ -132,7 +132,7 @@ var
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 @@ begin
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 56e7c442b4..91a6710112 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -33,7 +33,8 @@ uses
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 e4ce8316d3..124b0357ce 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 ca611b40e4..abcb521597 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 44488179c9..c47d90a1a5 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 @@ uses
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 @@ begin
WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8));
end
else
- CompileForBaseKeyboard(BaseKeyboardID);
+ MCompileBaseKeyboard(BaseKeyboardID);
end;
kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
@@ -55,29 +54,21 @@ begin
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 599566b91c..9c4478283e 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -174,7 +174,7 @@ uses
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 64fc2cd214..54f4a73f65 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -115,7 +115,7 @@ uses
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 @@ end;
function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean;
- var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
+ var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID, FBaseKeyboard: Integer): Boolean;
var
s: string;
i: Integer;
@@ -269,7 +269,7 @@ begin
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 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
- const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
+ const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward;
procedure Run;
var
@@ -341,7 +341,7 @@ var
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
- FDefaultLangID: Integer;
+ FDefaultLangID, FBaseKeyboard: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@@ -350,7 +350,7 @@ begin
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
- if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
+ if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
@@ -358,7 +358,7 @@ begin
if not LoadKMCOM then Exit;
try
- RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
+ RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard);
finally
kmcom := nil;
end;
@@ -397,7 +397,7 @@ end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
- FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
+ FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
@@ -555,7 +555,7 @@ begin
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 c47d90a1a5..d91b439f33 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 @@ uses
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 @@ end;
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 91a6710112..dd298a8642 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -18,6 +18,14 @@ type
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 786ce6c9b2..550a13064d 100644
--- a/windows/src/engine/kmcomapi/keymanapi_TLB.pas
+++ b/windows/src/engine/kmcomapi/keymanapi_TLB.pas
@@ -12,7 +12,7 @@ unit keymanapi_TLB;
// ************************************************************************ //
// $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 @@ const
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 @@ type
IKeymanKeyboardLanguagesFileDisp = dispinterface;
IKeymanKeyboardsInstalled2 = interface;
IKeymanKeyboardsInstalled2Disp = dispinterface;
+ IKeymanKeyboardInstalled2 = interface;
+ IKeymanKeyboardInstalled2Disp = dispinterface;
IKeymanPackagesInstalled2 = interface;
IKeymanPackagesInstalled2Disp = dispinterface;
IKeymanKeyboardFile2 = interface;
@@ -1569,16 +1572,6 @@ type
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 @@ type
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 9eb63fbd68..4d65b37777 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 1205d77f72..1df237b0c6 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kpinstallkeyboard.pas
@@ -255,7 +255,7 @@ begin
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 01b03ae3fc..7077bc1291 100644
--- a/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
+++ b/windows/src/engine/kmcomapi/com/keyboards/keymankeyboardinstalled.pas
@@ -110,7 +110,6 @@ type
{ IIntKeymanKeyboardInstalled }
function RegKeyboard: TRegKeyboard;
procedure ClearVisualKeyboard;
- procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;
{ IKeymanKeyboardInstalled2 }
@@ -155,22 +154,6 @@ begin
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 1759468e00..edfc65bf28 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 @@ type
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 @@ type
['{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 d91b439f33..926e766daa 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 @@ uses
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 dd298a8642..1d06e7ca25 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -20,12 +20,12 @@ type
(**
- 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 926e766daa..dedea86dae 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 1d06e7ca25..825088ad0a 100644
--- a/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
+++ b/windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
@@ -18,15 +18,14 @@ type
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 @@ uses
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 9c4478283e..472353102c 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 54f4a73f65..f2392d6913 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -402,7 +402,6 @@ var
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
- BaseKeyboardID: Integer;
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
@@ -550,7 +549,7 @@ begin
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 | 44 +++++++++++++++----
.../kmshell/install/UpgradeMnemonicLayout.pas | 19 ++++----
...yman.Configuration.System.BaseKeyboard.pas | 13 +++---
.../keyboard/kprecompilemnemonickeyboard.pas | 5 ++-
4 files changed, 56 insertions(+), 25 deletions(-)
diff --git a/common/windows/delphi/general/utilstr.pas b/common/windows/delphi/general/utilstr.pas
index 01e085b8a8..b5bcd32e65 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 @@ begin
Result := '';
Exit;
end;
-
+
if s[1] = '"' then
begin
Delete(s,1,1);
@@ -418,4 +436,14 @@ begin
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 acad765590..2639ac2072 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 @@ uses
kmint,
RegistryKeys,
utilexecute,
- utilkmshell;
+ utilkmshell,
+ utilstr;
const
{ CurrentMnemonicLayoutVersion = 476; // First 9.0 build with fixes for mnemonic layouts }
@@ -171,7 +172,7 @@ begin
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 dedea86dae..4c398f1fe8 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 3d806afda2..b05ab325d1 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -47,6 +47,7 @@ uses
RegistryKeys,
utilexecute,
utilkeyman,
+ utilstr,
utilsystem;
function GetKeyboardLayoutFileName(id: Integer): string;
@@ -83,8 +84,8 @@ begin
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 b5bcd32e65..59a897ad2e 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 @@ begin
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 4c398f1fe8..a1fecdd608 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 59a897ad2e..8319c37d04 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 @@ begin
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 f2392d6913..3010dae5cc 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -266,6 +266,7 @@ begin
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 f34be0933d..28faa8804c 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 @@ begin
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 8319c37d04..4cd175e360 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 @@ begin
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 2639ac2072..62b75bf566 100644
--- a/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
+++ b/windows/src/desktop/kmshell/install/UpgradeMnemonicLayout.pas
@@ -47,7 +47,7 @@ uses
RegistryKeys,
utilexecute,
utilkmshell,
- utilstr;
+ utilfiletypes;
const
{ CurrentMnemonicLayoutVersion = 476; // First 9.0 build with fixes for mnemonic layouts }
@@ -172,7 +172,7 @@ begin
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 a1fecdd608..c4fb428b49 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 @@ begin
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 b05ab325d1..52139f5839 100644
--- a/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
+++ b/windows/src/engine/kmcomapi/processes/keyboard/kprecompilemnemonickeyboard.pas
@@ -47,7 +47,7 @@ uses
RegistryKeys,
utilexecute,
utilkeyman,
- utilstr,
+ utilfiletypes,
utilsystem;
function GetKeyboardLayoutFileName(id: Integer): string;
@@ -84,8 +84,8 @@ begin
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 }