diff --git a/windows/src/desktop/kmshell/kmshell.dpr b/windows/src/desktop/kmshell/kmshell.dpr
index b9b77242bb..6b59b0591e 100644
--- a/windows/src/desktop/kmshell/kmshell.dpr
+++ b/windows/src/desktop/kmshell/kmshell.dpr
@@ -171,7 +171,12 @@ uses
Keyman.System.UILanguageManager in '..\..\global\delphi\general\Keyman.System.UILanguageManager.pas',
Keyman.Configuration.System.TIPMaintenance in 'install\Keyman.Configuration.System.TIPMaintenance.pas',
UfrmDownloadProgress in 'util\UfrmDownloadProgress.pas' {frmDownloadProgress},
- Keyman.Configuration.System.UImportOlderVersionKeyboards11To13 in 'main\Keyman.Configuration.System.UImportOlderVersionKeyboards11To13.pas';
+ Keyman.Configuration.System.UImportOlderVersionKeyboards11To13 in 'main\Keyman.Configuration.System.UImportOlderVersionKeyboards11To13.pas',
+ Keyman.System.Settings in '..\..\global\delphi\general\Keyman.System.Settings.pas',
+ Keyman.System.SettingsManager in '..\..\global\delphi\general\Keyman.System.SettingsManager.pas',
+ Keyman.Configuration.UI.UfrmSettingsManager in 'settings\Keyman.Configuration.UI.UfrmSettingsManager.pas' {frmSettingsManager},
+ Keyman.Configuration.UI.UfrmSettingsAddTSFApp in 'settings\Keyman.Configuration.UI.UfrmSettingsAddTSFApp.pas' {frmSettingsAddTSFApp},
+ Keyman.System.SettingsManagerFile in '..\..\global\delphi\general\Keyman.System.SettingsManagerFile.pas';
{$R VERSION.RES}
{$R manifest.res}
diff --git a/windows/src/desktop/kmshell/kmshell.dproj b/windows/src/desktop/kmshell/kmshell.dproj
index 2e4b743164..94eb66913f 100644
--- a/windows/src/desktop/kmshell/kmshell.dproj
+++ b/windows/src/desktop/kmshell/kmshell.dproj
@@ -325,6 +325,17 @@
dfm
+
+
+
+
+ dfm
+
+
+
+ dfm
+
+
Cfg_2
diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res
index d105ddca54..ce3230a965 100644
Binary files a/windows/src/desktop/kmshell/kmshell.res and b/windows/src/desktop/kmshell/kmshell.res differ
diff --git a/windows/src/desktop/kmshell/main/UfrmMain.pas b/windows/src/desktop/kmshell/main/UfrmMain.pas
index 5d9e0617c3..1c18c83aea 100644
--- a/windows/src/desktop/kmshell/main/UfrmMain.pas
+++ b/windows/src/desktop/kmshell/main/UfrmMain.pas
@@ -125,6 +125,7 @@ type
function GetOptionFromParams(params: TStringList; out option: IKeymanOption): Boolean;
procedure Options_ResetHints;
procedure Options_BaseKeyboard; // I4169
+ procedure Options_SettingsManager;
function GetHotkeyFromParams(params: TStringList;
out hotkey: IKeymanHotkey): Boolean;
@@ -184,6 +185,7 @@ uses
Keyman.Configuration.System.UmodWebHttpServer,
Keyman.Configuration.System.HttpServer.App.ConfigMain,
Keyman.Configuration.UI.InstallFile,
+ Keyman.Configuration.UI.UfrmSettingsManager,
RegistryKeys,
ShellApi,
StrUtils,
@@ -332,6 +334,8 @@ begin
else if command = 'options_clickcheck' then Options_ClickCheck(params)
else if command = 'options_resethints' then Options_ResetHints
else if command = 'options_basekeyboard' then Options_BaseKeyboard // I4169
+ else if command = 'options_settingsmanager' then Options_SettingsManager
+
else if command = 'language_underlyingkeyboard' then Options_BaseKeyboard
else if command = 'hotkey_set' then Hotkey_Set(params)
@@ -733,6 +737,20 @@ begin
Do_Content_Render(True);
end;
+procedure TfrmMain.Options_SettingsManager;
+begin
+ if kmcom.SystemInfo.IsAdministrator then
+ begin
+ if not TfrmSettingsManager.Execute then
+ Exit;
+ end
+ else
+ WaitForElevatedConfiguration(Handle, '-settings');
+
+ kmcom.Options.Refresh;
+ Do_Content_Render(True);
+end;
+
procedure TfrmMain.Options_ClickCheck(params: TStringList);
var
option: IKeymanOption;
diff --git a/windows/src/desktop/kmshell/main/initprog.pas b/windows/src/desktop/kmshell/main/initprog.pas
index b7e1b115ba..0797da1ed8 100644
--- a/windows/src/desktop/kmshell/main/initprog.pas
+++ b/windows/src/desktop/kmshell/main/initprog.pas
@@ -89,6 +89,7 @@ type
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
+ fmSettings,
// Commands from Keyman Engine
fmShowHint,
@@ -111,6 +112,7 @@ uses
Keyman.Configuration.UI.InstallFile,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.System.UImportOlderVersionKeyboards11To13,
+ Keyman.Configuration.UI.UfrmSettingsManager,
KeymanPaths,
KLog,
kmint,
@@ -275,6 +277,7 @@ begin
FParentWindow := StrToIntDef(ParamStr(i), 0);
end
else if s = '-showhelp' then FMode := fmShowHelp
+ else if s = '-settings' then FMode := fmSettings
else Exit;
end
@@ -539,6 +542,11 @@ begin
fmKeepInTouch:
ShowKeepInTouchForm(True); // I4658
+ fmSettings:
+ if TfrmSettingsManager.Execute
+ then ExitCode := 0
+ else ExitCode := 1;
+
fmShowHint:
if ShowKMShellHintQuery(FParentWindow, FirstKeyboardFileName) = mrOk
then ExitCode := 0
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.dfm b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.dfm
new file mode 100644
index 0000000000..20daa99b3f
--- /dev/null
+++ b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.dfm
@@ -0,0 +1,83 @@
+object frmSettingsAddTSFApp: TfrmSettingsAddTSFApp
+ Left = 0
+ Top = 0
+ ActiveControl = editFilename
+ BorderIcons = [biSystemMenu]
+ BorderStyle = bsDialog
+ Caption = 'Text Services Framework Application Overrides'
+ ClientHeight = 139
+ ClientWidth = 442
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ Position = poOwnerFormCenter
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Label1: TLabel
+ Left = 8
+ Top = 8
+ Width = 425
+ Height = 26
+ Caption =
+ 'Add per-application overrides for Text Services Framework suppor' +
+ 't. Use the executable filename of the application. Set value to' +
+ ' 1 to enable support and 0 to disable.'
+ WordWrap = True
+ end
+ object lblFilename: TLabel
+ Left = 8
+ Top = 51
+ Width = 46
+ Height = 13
+ Caption = 'Filename:'
+ end
+ object Label2: TLabel
+ Left = 8
+ Top = 78
+ Width = 30
+ Height = 13
+ Caption = 'Value:'
+ end
+ object cmdOK: TButton
+ Left = 275
+ Top = 106
+ Width = 77
+ Height = 25
+ Caption = 'OK'
+ Default = True
+ TabOrder = 2
+ OnClick = cmdOKClick
+ end
+ object cmdCancel: TButton
+ Left = 356
+ Top = 106
+ Width = 77
+ Height = 25
+ Cancel = True
+ Caption = 'Cancel'
+ ModalResult = 2
+ TabOrder = 3
+ end
+ object editFilename: TEdit
+ Left = 80
+ Top = 48
+ Width = 145
+ Height = 21
+ TabOrder = 0
+ end
+ object cbValue: TComboBox
+ Left = 80
+ Top = 75
+ Width = 145
+ Height = 21
+ Style = csDropDownList
+ TabOrder = 1
+ Items.Strings = (
+ '0 - Disabled'
+ '1 - Enabled')
+ end
+end
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.pas b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.pas
new file mode 100644
index 0000000000..4f70310ad4
--- /dev/null
+++ b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsAddTSFApp.pas
@@ -0,0 +1,75 @@
+unit Keyman.Configuration.UI.UfrmSettingsAddTSFApp;
+
+interface
+
+uses
+ System.Classes,
+ System.SysUtils,
+ System.Variants,
+ Vcl.Controls,
+ Vcl.Dialogs,
+ Vcl.Forms,
+ Vcl.Graphics,
+ Vcl.Grids,
+ Vcl.StdCtrls,
+ Winapi.Messages,
+ Winapi.Windows;
+
+type
+ TfrmSettingsAddTSFApp = class(TForm)
+ cmdOK: TButton;
+ cmdCancel: TButton;
+ Label1: TLabel;
+ lblFilename: TLabel;
+ editFilename: TEdit;
+ cbValue: TComboBox;
+ Label2: TLabel;
+ procedure cmdOKClick(Sender: TObject);
+ private
+ function GetFilename: string;
+ function GetValueInt: Integer;
+ { Private declarations }
+ public
+ { Public declarations }
+ property Filename: string read GetFilename;
+ property ValueInt: Integer read GetValueInt;
+ end;
+
+implementation
+
+{$R *.dfm}
+
+{ TfrmSettingsAddTSFApp }
+
+procedure TfrmSettingsAddTSFApp.cmdOKClick(Sender: TObject);
+var
+ filename: string;
+begin
+ filename := editFilename.Text;
+ filename := filename.Trim.ToLower;
+ if not filename.EndsWith('.exe') or filename.Contains('\') then
+ begin
+ ShowMessage('The application '+filename+' is not valid. It must be an executable file ending in .exe and must not include a path');
+ Exit;
+ end;
+
+ if cbValue.ItemIndex < 0 then
+ begin
+ ShowMessage('You must select an entry in the Value list');
+ Exit;
+ end;
+
+ ModalResult := mrOk;
+end;
+
+function TfrmSettingsAddTSFApp.GetFilename: string;
+begin
+ Result := editFilename.Text;
+end;
+
+function TfrmSettingsAddTSFApp.GetValueInt: Integer;
+begin
+ Result := cbValue.ItemIndex;
+end;
+
+end.
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.dfm b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.dfm
new file mode 100644
index 0000000000..f580b13549
--- /dev/null
+++ b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.dfm
@@ -0,0 +1,249 @@
+object frmSettingsManager: TfrmSettingsManager
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu]
+ Caption = 'Keyman Settings Manager'
+ ClientHeight = 447
+ ClientWidth = 704
+ Color = clBtnFace
+ Constraints.MinHeight = 360
+ Constraints.MinWidth = 720
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ Position = poOwnerFormCenter
+ OnCloseQuery = FormCloseQuery
+ OnCreate = FormCreate
+ OnResize = FormResize
+ DesignSize = (
+ 704
+ 447)
+ PixelsPerInch = 96
+ TextHeight = 13
+ object imgElevate: TImage
+ Left = 346
+ Top = 363
+ Width = 16
+ Height = 16
+ Anchors = [akLeft, akBottom]
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000
+ 001008060000001FF3FF61000000017352474200AECE1CE90000000467414D41
+ 0000B18F0BFC6105000000097048597300000EC300000EC301C76FA864000002
+ AF4944415478DA85935D48935118C7FF7BF7A16E7B5B534B25D29BC2E8BB04FB
+ 1033BF924CA61B2D234ACAD845ED228C82098157411174511745DE4451C10C22
+ 96330D45FB508B29A5929898CEE91CDB9A9BF375EFFB6EEFD631BA68D9ECC081
+ C339FFE7F79CE77F9E234282118BC544ADAD1D853CCF85753A4D5F229DE85F9B
+ 56AB759D54A67A381D4CAA2CDF3E80F1A9ACE70B8B8241ABD5FA5705D86CB674
+ A552591760228D6E4E9E3EE2F0C354FE024C90C25747EE9CCBABBA3E31F9ED49
+ 4343837F0560C2EEEA72FAD8A2002B506A9502BE450EA3D3F3B85ADC0E840240
+ 98876F490D379311199B5535D768F517E3003DB6EFBEC13956AD9088209550F8
+ 116461F704714747CA67098067012E42602C5E3BF2DF1FADA92F8C03B4F68CF8
+ FB673815CB72BFB207423C9C7E161FCEBC0216DD249027B78891194507AFEFAD
+ A83114C4015E767E9EEB996233BD01065F48EDE39E2544893E74E13139259905
+ 099932B2A6D0E6AFEEAED49D2F8E07BCF9647B3B13C91BB67B3138E58340A293
+ A5C4BCD36688C42250E2142296220631BADDD5CF34DAE3A7E23DE86E7B50B0A9
+ CB206615003346EAF520CCF1C8BC5B079A4EC17A5A0EB954868DB40C2776738D
+ 1A4DD58D3880D5DA7E646FCE507B866C9E18465E29348DF01283ECE6B3484BA5
+ 9146203CB141BB55118BB97AB7994CA6D138C072E77D7CD732B02FAB7F0F2214
+ B9810B61C683DC47E7909E4623492C455254844B074556CDB1B2AAE590158D64
+ B1580EEFCC99EDCC4E9EA4C0F911093AB0ABC58035B40202C95E9FB7868BBA87
+ F38D46C350C2566E6BB3DCDA9FEBB9B2366A87C038516639497C97A060831CC5
+ 3941534949C9CD55FF42535393A4E8D081A73B36B3FA54991BD7FA4A911965B0
+ 45E9B95F51516A2492E87F3F93D96C16D3B4EAB29A168CCE8514211CF4DEAEAD
+ D5DFFB3B3821E08F41FDD60889043F01326A2C20F97EFC660000000049454E44
+ AE426082}
+ Visible = False
+ end
+ object lblDefault: TLabel
+ Left = 8
+ Top = 391
+ Width = 39
+ Height = 13
+ Anchors = [akLeft, akBottom]
+ Caption = 'Default:'
+ ExplicitTop = 461
+ end
+ object imgElevateTSFApplications: TImage
+ Left = 146
+ Top = 420
+ Width = 16
+ Height = 16
+ Anchors = [akLeft, akBottom]
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000
+ 001008060000001FF3FF61000000017352474200AECE1CE90000000467414D41
+ 0000B18F0BFC6105000000097048597300000EC300000EC301C76FA864000002
+ AF4944415478DA85935D48935118C7FF7BF7A16E7B5B534B25D29BC2E8BB04FB
+ 1033BF924CA61B2D234ACAD845ED228C82098157411174511745DE4451C10C22
+ 96330D45FB508B29A5929898CEE91CDB9A9BF375EFFB6EEFD631BA68D9ECC081
+ C339FFE7F79CE77F9E234282118BC544ADAD1D853CCF85753A4D5F229DE85F9B
+ 56AB759D54A67A381D4CAA2CDF3E80F1A9ACE70B8B8241ABD5FA5705D86CB674
+ A552591760228D6E4E9E3EE2F0C354FE024C90C25747EE9CCBABBA3E31F9ED49
+ 4343837F0560C2EEEA72FAD8A2002B506A9502BE450EA3D3F3B85ADC0E840240
+ 98876F490D379311199B5535D768F517E3003DB6EFBEC13956AD9088209550F8
+ 116461F704714747CA67098067012E42602C5E3BF2DF1FADA92F8C03B4F68CF8
+ FB673815CB72BFB207423C9C7E161FCEBC0216DD249027B78891194507AFEFAD
+ A83114C4015E767E9EEB996233BD01065F48EDE39E2544893E74E13139259905
+ 099932B2A6D0E6AFEEAED49D2F8E07BCF9647B3B13C91BB67B3138E58340A293
+ A5C4BCD36688C42250E2142296220631BADDD5CF34DAE3A7E23DE86E7B50B0A9
+ CB206615003346EAF520CCF1C8BC5B079A4EC17A5A0EB954868DB40C2776738D
+ 1A4DD58D3880D5DA7E646FCE507B866C9E18465E29348DF01283ECE6B3484BA5
+ 9146203CB141BB55118BB97AB7994CA6D138C072E77D7CD732B02FAB7F0F2214
+ B9810B61C683DC47E7909E4623492C455254844B074556CDB1B2AAE590158D64
+ B1580EEFCC99EDCC4E9EA4C0F911093AB0ABC58035B40202C95E9FB7868BBA87
+ F38D46C350C2566E6BB3DCDA9FEBB9B2366A87C038516639497C97A060831CC5
+ 3941534949C9CD55FF42535393A4E8D081A73B36B3FA54991BD7FA4A911965B0
+ 45E9B95F51516A2492E87F3F93D96C16D3B4EAB29A168CCE8514211CF4DEAEAD
+ D5DFFB3B3821E08F41FDD60889043F01326A2C20F97EFC660000000049454E44
+ AE426082}
+ ExplicitTop = 490
+ end
+ object gridDebugOption: TStringGrid
+ Left = 8
+ Top = 8
+ Width = 688
+ Height = 243
+ Anchors = [akLeft, akTop, akRight, akBottom]
+ ColCount = 2
+ DefaultRowHeight = 16
+ DefaultDrawing = False
+ Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing, goEditing]
+ TabOrder = 0
+ OnClick = gridDebugOptionClick
+ OnDrawCell = gridDebugOptionDrawCell
+ OnSetEditText = gridDebugOptionSetEditText
+ end
+ object memoDescription: TMemo
+ Left = 8
+ Top = 266
+ Width = 336
+ Height = 89
+ Anchors = [akLeft, akBottom]
+ ParentColor = True
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ end
+ object cmdApply: TButton
+ Left = 528
+ Top = 414
+ Width = 87
+ Height = 25
+ Anchors = [akRight, akBottom]
+ Caption = '&Apply'
+ TabOrder = 2
+ OnClick = cmdApplyClick
+ end
+ object cmdClearAll: TButton
+ Left = 561
+ Top = 383
+ Width = 135
+ Height = 25
+ Anchors = [akRight, akBottom]
+ Caption = '&Reset all to default'
+ TabOrder = 3
+ OnClick = cmdClearAllClick
+ end
+ object cmdClose: TButton
+ Left = 621
+ Top = 414
+ Width = 75
+ Height = 25
+ Anchors = [akRight, akBottom]
+ Caption = 'Close'
+ TabOrder = 4
+ OnClick = cmdCloseClick
+ end
+ object editRegKey: TEdit
+ Left = 8
+ Top = 361
+ Width = 336
+ Height = 21
+ Anchors = [akLeft, akBottom]
+ ParentColor = True
+ ReadOnly = True
+ TabOrder = 5
+ end
+ object editDefault: TEdit
+ Left = 53
+ Top = 388
+ Width = 210
+ Height = 21
+ Anchors = [akLeft, akBottom]
+ ParentColor = True
+ ReadOnly = True
+ TabOrder = 6
+ end
+ object cmdReset: TButton
+ Left = 269
+ Top = 388
+ Width = 75
+ Height = 21
+ Anchors = [akLeft, akBottom]
+ Caption = '&Reset'
+ TabOrder = 7
+ OnClick = cmdResetClick
+ end
+ object cmdExport: TButton
+ Left = 561
+ Top = 321
+ Width = 135
+ Height = 25
+ Anchors = [akRight, akBottom]
+ Caption = '&Export...'
+ TabOrder = 8
+ OnClick = cmdExportClick
+ end
+ object chkShowDevelopmentSettings: TCheckBox
+ Left = 360
+ Top = 422
+ Width = 167
+ Height = 17
+ Anchors = [akRight, akBottom]
+ Caption = 'Show Development Settings'
+ TabOrder = 9
+ OnClick = chkShowDevelopmentSettingsClick
+ end
+ object cmdImport: TButton
+ Left = 561
+ Top = 352
+ Width = 135
+ Height = 25
+ Anchors = [akRight, akBottom]
+ Caption = '&Import...'
+ TabOrder = 10
+ OnClick = cmdImportClick
+ end
+ object cmdTSFApplicationSettings: TButton
+ Left = 8
+ Top = 415
+ Width = 135
+ Height = 25
+ Anchors = [akLeft, akBottom]
+ Caption = '&Add TSF Override...'
+ TabOrder = 11
+ OnClick = cmdTSFApplicationSettingsClick
+ end
+ object dlgImport: TOpenDialog
+ DefaultExt = 'json'
+ Filter = 'Keyman Settings Files (*.json)|*.json|All files (*.*)|*.*'
+ Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
+ Title = 'Import Keyman Settings from File'
+ Left = 424
+ Top = 152
+ end
+ object dlgExport: TSaveDialog
+ DefaultExt = 'json'
+ Filter = 'Keyman Settings Files (*.json)|*.json|All files (*.*)|*.*'
+ Options = [ofHideReadOnly, ofPathMustExist, ofEnableSizing]
+ Title = 'Export Keyman Settings to File'
+ Left = 368
+ Top = 152
+ end
+end
diff --git a/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.pas b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.pas
new file mode 100644
index 0000000000..4cbb25b882
--- /dev/null
+++ b/windows/src/desktop/kmshell/settings/Keyman.Configuration.UI.UfrmSettingsManager.pas
@@ -0,0 +1,367 @@
+unit Keyman.Configuration.UI.UfrmSettingsManager;
+
+interface
+
+uses
+ System.Classes,
+ System.SysUtils,
+ System.Variants,
+ Vcl.Controls,
+ Vcl.Dialogs,
+ Vcl.Forms,
+ Vcl.Graphics,
+ Vcl.Grids,
+ Vcl.StdCtrls,
+ Winapi.Messages,
+ Winapi.Windows,
+
+ Keyman.System.Settings, Vcl.Imaging.pngimage, Vcl.ExtCtrls;
+
+type
+ TfrmSettingsManager = class(TForm)
+ gridDebugOption: TStringGrid;
+ memoDescription: TMemo;
+ cmdApply: TButton;
+ cmdClearAll: TButton;
+ cmdClose: TButton;
+ editRegKey: TEdit;
+ editDefault: TEdit;
+ cmdReset: TButton;
+ imgElevate: TImage;
+ cmdExport: TButton;
+ chkShowDevelopmentSettings: TCheckBox;
+ cmdImport: TButton;
+ dlgImport: TOpenDialog;
+ dlgExport: TSaveDialog;
+ lblDefault: TLabel;
+ cmdTSFApplicationSettings: TButton;
+ imgElevateTSFApplications: TImage;
+ procedure FormCreate(Sender: TObject);
+ procedure gridDebugOptionClick(Sender: TObject);
+ procedure FormResize(Sender: TObject);
+ procedure gridDebugOptionSetEditText(Sender: TObject; ACol, ARow: Integer;
+ const Value: string);
+ procedure cmdApplyClick(Sender: TObject);
+ procedure cmdCloseClick(Sender: TObject);
+ procedure cmdClearAllClick(Sender: TObject);
+ procedure cmdResetClick(Sender: TObject);
+ procedure gridDebugOptionDrawCell(Sender: TObject; ACol, ARow: Integer;
+ Rect: TRect; State: TGridDrawState);
+ procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+ procedure chkShowDevelopmentSettingsClick(Sender: TObject);
+ procedure cmdExportClick(Sender: TObject);
+ procedure cmdImportClick(Sender: TObject);
+ procedure cmdTSFApplicationSettingsClick(Sender: TObject);
+ private
+ IsAdmin: Boolean;
+ FWasSaved: Boolean;
+ procedure FillGrid;
+ function SelectedSetting: TKeymanSetting;
+ procedure EnableControls;
+ function FindSettingRow(const ID: string): Integer;
+ public
+ Settings: TKeymanSettings;
+ class function Execute(AOwner: TComponent = nil): Boolean;
+ end;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ System.Math,
+ System.UITypes,
+ System.Win.Registry,
+
+ Keyman.System.SettingsManager,
+ Keyman.System.SettingsManagerFile,
+ Keyman.Configuration.UI.UfrmSettingsAddTSFApp,
+ RegistryKeys;
+
+procedure TfrmSettingsManager.FormCreate(Sender: TObject);
+var
+ r: TRegistry;
+begin
+ r := TRegistry.Create;
+ try
+ r.RootKey := HKEY_LOCAL_MACHINE;
+ IsAdmin := r.OpenKey(SRegKey_KeymanEngine_LM, True);
+ finally
+ r.Free;
+ end;
+
+ Settings := TKeymanSettings.Create;
+
+ TKeymanSettingsManager.Load(Settings);
+
+ FillGrid;
+ EnableControls;
+end;
+
+procedure TfrmSettingsManager.FormResize(Sender: TObject);
+begin
+ gridDebugOption.ColWidths[1] := gridDebugOption.ClientWidth - gridDebugOption.ColWidths[0] - 1;
+end;
+
+procedure TfrmSettingsManager.FormCloseQuery(Sender: TObject;
+ var CanClose: Boolean);
+begin
+ CanClose := True;
+ if settings.Modified then
+ begin
+ case MessageDlg('Do you want to save changes before closing?', mtConfirmation, mbYesNoCancel, 0) of
+ mrYes: cmdApplyClick(cmdApply);
+ mrNo: ;
+ mrCancel: CanClose := False;
+ end;
+ end;
+end;
+
+
+procedure TfrmSettingsManager.cmdResetClick(Sender: TObject);
+begin
+ SelectedSetting.Reset;
+ FillGrid;
+ EnableControls;
+end;
+
+procedure TfrmSettingsManager.chkShowDevelopmentSettingsClick(
+ Sender: TObject);
+begin
+ FillGrid;
+end;
+
+procedure TfrmSettingsManager.cmdClearAllClick(Sender: TObject);
+begin
+ Settings.Reset;
+ FillGrid;
+ EnableControls;
+end;
+
+procedure TfrmSettingsManager.cmdCloseClick(Sender: TObject);
+begin
+ if fsModal in FormState then
+ begin
+ if FWasSaved
+ then ModalResult := mrOk
+ else ModalResult := mrCancel;
+ end
+ else
+ Close;
+end;
+
+procedure TfrmSettingsManager.cmdExportClick(Sender: TObject);
+begin
+ if dlgExport.Execute then
+ begin
+ TKeymanSettingsManagerFile.Export(Settings, dlgExport.FileName);
+ end;
+end;
+
+procedure TfrmSettingsManager.cmdImportClick(Sender: TObject);
+begin
+ if dlgImport.Execute then
+ begin
+ TKeymanSettingsManagerFile.Import(Settings, dlgImport.FileName);
+ FillGrid;
+ EnableControls;
+ end;
+end;
+
+procedure TfrmSettingsManager.cmdApplyClick(Sender: TObject);
+var
+ AdminChanges: Boolean;
+ setting: TKeymanSetting;
+begin
+ if not IsAdmin then
+ begin
+ AdminChanges := False;
+ for setting in settings do
+ if setting.Base.RequiresAdministrator and setting.Modified then
+ AdminChanges := True;
+ if AdminChanges then
+ ShowMessage('Cannot save changes to HKLM values; re-run as Administrator to make these changes.');
+ end;
+
+ TKeymanSettingsManager.Save(Settings, IsAdmin);
+ // We'll recreate the Settings list so that settings that have been removed
+ // will be refreshed
+ FreeAndNil(Settings);
+ Settings := TKeymanSettings.Create;
+ TKeymanSettingsManager.Load(Settings);
+ FillGrid;
+ gridDebugOption.Invalidate;
+ FWasSaved := True;
+ EnableControls;
+end;
+
+procedure TfrmSettingsManager.cmdTSFApplicationSettingsClick(
+ Sender: TObject);
+var
+ frm: TfrmSettingsAddTSFApp;
+ s: TKeymanSetting;
+begin
+ frm := TfrmSettingsAddTSFApp.Create(Self);
+ try
+ if frm.ShowModal = mrOk then
+ begin
+ s := TKeymanSetting.CreateCustom_TSFApp(CustomKeymanSetting_TSFApp.ID + frm.Filename);
+ s.ValueInt := frm.ValueInt;
+ Settings.Add(s);
+ FillGrid;
+ gridDebugOption.Row := FindSettingRow(s.Base.ID);
+ gridDebugOptionClick(gridDebugOption);
+ end;
+ finally
+ frm.Free;
+ end;
+ EnableControls;
+end;
+
+function TfrmSettingsManager.FindSettingRow(const ID: string): Integer;
+var
+ i: Integer;
+begin
+ for i := 1 to gridDebugOption.RowCount - 1 do
+ if SameText((gridDebugOption.Objects[0, i] as TKeymanSetting).Base.ID, ID) then
+ Exit(i);
+ Result := -1;
+end;
+
+procedure TfrmSettingsManager.EnableControls;
+begin
+ cmdApply.Enabled := Settings.Modified;
+end;
+
+class function TfrmSettingsManager.Execute(AOwner: TComponent): Boolean;
+var
+ frm: TfrmSettingsManager;
+begin
+ frm := TfrmSettingsManager.Create(AOwner);
+ try
+ Result := frm.ShowModal = mrOk;
+ finally
+ frm.Free;
+ end;
+end;
+
+procedure TfrmSettingsManager.FillGrid;
+var
+ s: TKeymanSetting;
+ MaxWidth, i: Integer;
+begin
+ gridDebugOption.RowCount := Settings.Count + 1;
+ gridDebugOption.Cells[0, 0] := 'Name';
+ gridDebugOption.Cells[1, 0] := 'Value';
+
+ gridDebugOption.Canvas.Font.Style := [fsBold];
+
+ i := 1; MaxWidth := 0;
+ for s in Settings do
+ begin
+ if chkShowDevelopmentSettings.Checked or not s.Base.ID.StartsWith('development.') then
+ begin
+ gridDebugOption.Objects[0, i] := s;
+ gridDebugOption.Cells[0, i] := s.Base.ID;
+ if s.Base.ValueType = kstString
+ then gridDebugOption.Cells[1, i] := s.ValueStr
+ else gridDebugOption.Cells[1, i] := IntToStr(s.ValueInt);
+ MaxWidth := System.Math.Max(MaxWidth, gridDebugOption.Canvas.TextWidth(s.Base.ID+' *'));
+ Inc(i);
+ end;
+ end;
+
+ gridDebugOption.RowCount := i;
+
+ gridDebugOption.ColWidths[0] := MaxWidth + 8;
+ gridDebugOption.ColWidths[1] := gridDebugOption.ClientWidth - MaxWidth - 8 - 1;
+ gridDebugOptionClick(gridDebugOption);
+end;
+
+
+function TfrmSettingsManager.SelectedSetting: TKeymanSetting;
+begin
+ Result := gridDebugOption.Objects[0, gridDebugOption.Row] as TKeymanSetting;
+end;
+
+procedure TfrmSettingsManager.gridDebugOptionClick(Sender: TObject);
+begin
+ memoDescription.Text := SelectedSetting.Base.Description;
+ if SelectedSetting.Base.RootKey = HKCU
+ then editRegKey.Text := 'HKCU\'+SelectedSetting.Base.Key + ': '+SelectedSetting.Base.Name
+ else editRegKey.Text := 'HKLM\'+SelectedSetting.Base.Key + ': '+SelectedSetting.Base.Name;
+ editDefault.Text := SelectedSetting.Base.DefaultAsString;
+ imgElevate.Visible := not IsAdmin and SelectedSetting.Base.RequiresAdministrator;
+
+ imgElevateTSFApplications.Visible := not IsAdmin and (SelectedSetting.Base.ID = 'engine.compatibility.text_services_framework');
+ cmdTSFApplicationSettings.Visible := SelectedSetting.Base.ID = 'engine.compatibility.text_services_framework';
+end;
+
+procedure TfrmSettingsManager.gridDebugOptionDrawCell(Sender: TObject; ACol, ARow: Integer;
+ Rect: TRect; State: TGridDrawState);
+var
+ s: TKeymanSetting;
+ t: string;
+begin
+ if gdFixed in State then
+ begin
+ gridDebugOption.Canvas.Brush.Color := clLtGray;
+ gridDebugOption.Canvas.Font.Color := clBlack;
+ end
+ else if gdSelected in State then
+ begin
+ gridDebugOption.Canvas.Brush.Color := clHighlight;
+ gridDebugOption.Canvas.Font.Color := clHighlightText;
+ end
+ else
+ begin
+ gridDebugOption.Canvas.Brush.Color := clWindow;
+ gridDebugOption.Canvas.Font.Color := clWindowText;
+ end;
+
+ t := gridDebugOption.Cells[ACol, ARow];
+
+ if (ARow = 0) then
+ begin
+ gridDebugOption.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 1, t);
+ Exit;
+ end;
+ s := gridDebugOption.Objects[0, ARow] as TKeymanSetting;
+ if not s.IsEmpty
+ then gridDebugOption.Canvas.Font.Style := [fsBold]
+ else gridDebugOption.Canvas.Font.Style := [];
+
+ if (ACol = 0) and (s.Modified) then
+ t := t + ' *';
+ gridDebugOption.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 1, t);
+
+ if (ACol = 0) and s.Base.RequiresAdministrator and not IsAdmin then
+ begin
+ gridDebugOption.Canvas.Draw(Rect.Left + 2 + gridDebugOption.Canvas.TextWidth(t) + 2, Rect.Top, imgElevate.Picture.Graphic);
+ end;
+end;
+
+procedure TfrmSettingsManager.gridDebugOptionSetEditText(Sender: TObject; ACol,
+ ARow: Integer; const Value: string);
+var
+ v: Integer;
+ s: TKeymanSetting;
+begin
+ s := gridDebugOption.Objects[0, ARow] as TKeymanSetting;
+ if s.Base.ValueType = kstInteger then
+ begin
+ if not TryStrToInt(Value, v) then
+ Exit;
+ s.ValueInt := v;
+ end
+ else
+ begin
+ s.ValueStr := Value.Trim;
+ end;
+
+ // Repaint caption
+ InvalidateRect(gridDebugOption.Handle, gridDebugOption.CellRect(0, ARow), False);
+ EnableControls;
+end;
+
+end.
diff --git a/windows/src/desktop/kmshell/settings/elevation.png b/windows/src/desktop/kmshell/settings/elevation.png
new file mode 100644
index 0000000000..45b02ced86
Binary files /dev/null and b/windows/src/desktop/kmshell/settings/elevation.png differ
diff --git a/windows/src/desktop/kmshell/xml/config.css b/windows/src/desktop/kmshell/xml/config.css
index bea36a3896..6bad9432bf 100644
--- a/windows/src/desktop/kmshell/xml/config.css
+++ b/windows/src/desktop/kmshell/xml/config.css
@@ -134,6 +134,7 @@ input[type='submit'], input[type='button'], button
border-radius: 4px;
color: #33333f;
border: none;
+ vertical-align: top;
}
input[type='submit']:disabled, input[type='button']:disabled, button:disabled
diff --git a/windows/src/desktop/kmshell/xml/keyman_options.xsl b/windows/src/desktop/kmshell/xml/keyman_options.xsl
index 8536fecd39..3be0997489 100644
--- a/windows/src/desktop/kmshell/xml/keyman_options.xsl
+++ b/windows/src/desktop/kmshell/xml/keyman_options.xsl
@@ -29,7 +29,13 @@
keyman:support_proxyconfig
-
+
+
+ 1
+
+ keyman:options_settingsmanager
+
+
1
diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml
index 1748fb2ce2..cdd1621343 100644
--- a/windows/src/desktop/kmshell/xml/strings.xml
+++ b/windows/src/desktop/kmshell/xml/strings.xml
@@ -562,6 +562,11 @@
Proxy Settings...
+
+
+
+ Keyman System Settings...
+