From 39b64be67a35f89dd37b699e92493678c6d8f3d1 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 22 Jan 2024 09:18:04 +0700 Subject: [PATCH 1/5] refactor(developer): use km_core_state_get_actions for LDML keyboard debugger Relates to #10416. Moves from using action queue to action struct for the LDML keyboard debugger. Does not do the same for the KMX keyboard debugger, because that relies on action items to do single-step debugging. --- core/tests/unit/kmnkbd/action_api.cpp | 10 ++++ .../debug/Keyman.System.Debug.DebugEvent.pas | 44 ++++++++------- .../tike/main/Keyman.System.KeymanCore.pas | 54 +++++++++++++++++++ 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/core/tests/unit/kmnkbd/action_api.cpp b/core/tests/unit/kmnkbd/action_api.cpp index 6a84eafa2d..50f39ffdce 100644 --- a/core/tests/unit/kmnkbd/action_api.cpp +++ b/core/tests/unit/kmnkbd/action_api.cpp @@ -218,6 +218,16 @@ int main(int argc, char *argv []) { } console_color::enabled = console_color::isaterminal() || arg_color; + km_core_actions act = {0}; + + std::cout << "sizeof(km_core_actions): " << sizeof(km_core_actions) << std::endl; + std::cout << "&km_core_actions.code_points_to_delete: " << ((int)(&act.code_points_to_delete)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.output: " << ((int)(&act.output)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.persist_options: " << ((int)(&act.persist_options)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.do_alert: " << ((int)(&act.do_alert)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.emit_keystroke: " << ((int)(&act.emit_keystroke)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.new_caps_lock_state: " << ((int)(&act.new_caps_lock_state)-(int)(&act)) << std::endl; + // actions test_two_backspaces(); test_marker_text_interleaved(); diff --git a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas index 2d6e5a39bf..c4b92f53e7 100644 --- a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas +++ b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas @@ -94,8 +94,8 @@ type modifier_state: uint16_t ): Boolean; overload; - function AddLdmlStateItems(state: pkm_core_state; vk, - modifier_state: uint16_t; debugkeyboard: TDebugKeyboard): Boolean; + procedure AddLdmlStateItems(state: pkm_core_state; vk, + modifier_state: uint16_t; debugkeyboard: TDebugKeyboard); end; implementation @@ -375,34 +375,42 @@ begin Assert(action._type = KM_CORE_IT_END); end; -function TDebugEventList.AddLdmlStateItems( +procedure TDebugEventList.AddLdmlStateItems( state: pkm_core_state; vk: uint16_t; modifier_state: uint16_t; debugkeyboard: TDebugKeyboard -): Boolean; +); var - action: pkm_core_action_item; + actions: pkm_core_actions; + p: pkm_core_usv; + i: UInt32; begin - // TODO: use action struct - Result := True; - action := km_core_state_action_items(state, nil); - while (action._type <> KM_CORE_IT_END) do + actions := km_core_state_get_actions(state); + + for i := 1 to actions.code_points_to_delete do + Action_DeleteBack(Byte(KM_CORE_BT_CHAR), 0); + + p := actions.output; + while p^ <> 0 do begin - Result := Result and AddActionItem(vk, action); - Inc(action); + Action_Char(p^); + Inc(p); end; - if action._type = KM_CORE_IT_EMIT_KEYSTROKE then + // TODO: actions.persist_options + + if actions.do_alert <> 0 then begin - // The EMIT_KEYSTROKE action comes after all rules have completed processing - Result := Result and AddActionItem(vk, action); - Inc(action); + // TODO end; - // By the time we get to the end of rule processing, all actions should have - // already been undertaken - Assert(action._type = KM_CORE_IT_END); + if actions.emit_keystroke <> 0 then + begin + Action_EmitKeystroke(vk); + end; + + // TODO: actions.new_caps_lock_state end; { TDebugEventRuleData } diff --git a/developer/src/tike/main/Keyman.System.KeymanCore.pas b/developer/src/tike/main/Keyman.System.KeymanCore.pas index 408a16ef1f..7d3a6d22c0 100644 --- a/developer/src/tike/main/Keyman.System.KeymanCore.pas +++ b/developer/src/tike/main/Keyman.System.KeymanCore.pas @@ -20,6 +20,7 @@ type km_core_virtual_key = uint16_t; km_core_usv = uint32_t; // UTF-32 + pkm_core_usv = ^km_core_usv; km_core_cp = WideChar; pkm_core_cp = ^km_core_cp; @@ -201,6 +202,35 @@ type pkm_core_action_item = ^km_core_action_item; + km_core_bool = uint32; + + km_core_caps_state = ( + KM_CORE_CAPS_UNCHANGED = -1, + KM_CORE_CAPS_OFF = 0, + KM_CORE_CAPS_ON = 1 + ); + + km_core_actions = record + code_points_to_delete: uint32; // number of codepoints (not codeunits!) to delete from app context. + + // null-term string of characters to insert into document + output: pkm_core_usv; + + // list of options to persist, terminated with KM_CORE_OPTIONS_END + persist_options: pkm_core_option_item; + + // issue a beep, 0 = no, 1 = yes + do_alert: km_core_bool; + + // emit the (unmodified) input keystroke to the application, 0 = no, 1 = yes + emit_keystroke: km_core_bool; + + // -1=unchanged, 0=off, 1=on + new_caps_lock_state: km_core_caps_state; + + end; + pkm_core_actions = ^km_core_actions; + // These types are used only for debugging convenience type km_core_action_item_array = array[0..100] of km_core_action_item; @@ -280,6 +310,10 @@ function km_core_state_action_items( num_items: pinteger ): pkm_core_action_item; cdecl; external keymancore delayed; +function km_core_state_get_actions( + state: pkm_core_state +): pkm_core_actions; cdecl; external keymancore delayed; + function km_core_state_to_json( state: pkm_core_state; buf: PAnsiChar; @@ -652,4 +686,24 @@ begin RaiseLastOSError; end; +// Verify size of km_core_actions - from x86 core c++ build, test_actions.cpp + +procedure VerifyKmCoreActionsSize; +var + act: km_core_actions; +begin +{$IFDEF WIN64} + {$ERROR Struct size not yet verified for 64-bit} +{$ENDIF} + assert(sizeof(km_core_actions) = 24); + // &km_core_actions.code_points_to_delete: 0 + assert(Uint32(@act.output) - Uint32(@act) = 4); + assert(Uint32(@act.persist_options) - Uint32(@act) = 8); + assert(Uint32(@act.do_alert) - Uint32(@act) = 12); + assert(Uint32(@act.emit_keystroke) - Uint32(@act) = 16); + assert(Uint32(@act.new_caps_lock_state) - Uint32(@act) = 20); +end; + +initialization + VerifyKmCoreActionsSize; end. From 7e41ecb35820234db0d223c00fedf82a98f87c6e Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 23 Jan 2024 12:32:42 +0700 Subject: [PATCH 2/5] feat(developer): LDML keyboard test window marker support Fixes #10458. Refactors the LDML keyboard test window significantly, in order to be able to support markers. Cleans up the state machine for the debug window in the process, as that was complicating the changes. Removes a lot of extraneous code in the debug window. --- ...veloper.UI.Debug.UfrmLdmlKeyboardDebug.pas | 540 +++++++----------- ...an.Developer.UI.UfrmLdmlKeyboardEditor.pas | 2 - .../debug/Keyman.System.Debug.DebugEvent.pas | 41 -- .../Keyman.UI.Debug.CharacterGridRenderer.pas | 10 +- .../tike/main/Keyman.System.KeymanCore.pas | 13 +- 5 files changed, 217 insertions(+), 389 deletions(-) diff --git a/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.pas b/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.pas index 8f086ee9b2..a6306eb13f 100644 --- a/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.pas +++ b/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.pas @@ -32,8 +32,6 @@ uses PaintPanel, KeymanDeveloperDebuggerMemo, Keyman.System.Debug.DebugCore, - Keyman.System.Debug.DebugEvent, - Keyman.System.Debug.DebugUIStatus, Keyman.System.Debug.DebugUtils, Keyman.System.KeymanCore, Keyman.System.KeymanCoreDebug, @@ -42,6 +40,13 @@ uses UfrmTike, UserMessages; +type + TLdmlDebugUIStatus = ( + duiStarting, + duiTest, + duiClosing + ); + type TfrmLdmlKeyboardDebug = class(TTikeForm) memo: TKeymanDeveloperDebuggerMemo; @@ -56,7 +61,6 @@ type mnuPaste: TMenuItem; // I4808 procedure FormCreate(Sender: TObject); procedure memoGotFocus(Sender: TObject); - procedure memoLostFocus(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure memoChange(Sender: TObject); @@ -70,27 +74,15 @@ type procedure memoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormResize(Sender: TObject); private - - FDebugVisible: Boolean; - FRunning: Boolean; FFileName: string; debugkeyboard: TDebugKeyboard; - _FCurrentEvent: Integer; FDefaultFont: Boolean; - FEvents: TDebugEventList; - FUIStatus: TDebugUIStatus; + FUIStatus: TLdmlDebugUIStatus; FUIDisabled: Boolean; { Deadkey member variables } FSelectedDeadkey: TDeadKeyInfo; - FSavedSelection: TMemoSelection; - procedure ResetEvents; - procedure ExecuteEvent(n: Integer); - procedure ExecuteEventAction(n: Integer); - procedure SetUIStatus(const Value: TDebugUIStatus); - procedure DisableUI; - procedure EnableUI; function GetStatusText: string; procedure SetStatusText(Value: string); @@ -102,7 +94,6 @@ type FDebugFileName: WideString; procedure ClearDeadkeys; procedure ClearDeadkeyStyle; - function GetCurrentEvent: TDebugEvent; procedure UninitDeadkeys; procedure UpdateDeadkeyDisplay; procedure UpdateDeadkeys; @@ -114,8 +105,7 @@ type procedure CleanupCoreState; function SetKeyEventContext: Boolean; function HandleMemoKeydown(var Message: TMessage): Boolean; - procedure SetCurrentEvent(Value: Integer); - procedure Run; + procedure Run(vkey: Word); protected function GetHelpTopic: string; override; @@ -132,7 +122,7 @@ type function GetDebugKeyboard: TDebugKeyboard; - property UIStatus: TDebugUIStatus read FUIStatus write SetUIStatus; + property UIStatus: TLdmlDebugUIStatus read FUIStatus write FUIStatus; property DebugFileName: WideString read FDebugFileName write FDebugFileName; property CompiledFileName: string read FFileName write FFileName; // I4695 @@ -141,11 +131,7 @@ type procedure ShowDebugForm; procedure HideDebugForm; - property DebugVisible: Boolean read FDebugVisible; - function ShortcutDisabled(Key: Word): Boolean; - - property CurrentEvent: TDebugEvent read GetCurrentEvent; end; implementation @@ -153,20 +139,18 @@ implementation {$R *.DFM} uses + System.Character, + System.Math, + Keyman.Developer.System.HelpTopics, - ActiveX, dmActionsDebugger, dmActionsMain, - Glossary, Keyman.Developer.System.Project.ProjectLog, + Keyman.Developer.UI.Project.ProjectUI, Keyman.Developer.UI.UfrmLdmlKeyboardEditor, Keyman.UI.Debug.CharacterGridRenderer, KeyNames, - kmxfile, - kmxfileconsts, - ErrorControlledRegistry, - RegistryKeys, KeymanDeveloperOptions, KeymanDeveloperUtils, ScanCodeMap, @@ -174,13 +158,9 @@ uses UfrmEditor, UfrmMain, UfrmMessages, - UfrmRegressionTestFailure, UfrmSelectSystemKeyboard, Unicode, - utilstr, - UTikeDebugMode, - VKeys, - XString; + utilstr; const // WM_KEYDOWN bits; KEYFLAG_KEYMAN is a reserved value @@ -197,18 +177,19 @@ begin FDeadkeys := TDebugDeadkeyInfoList.Create; - FUIStatus := duiInvalid; - FEvents := TDebugEventList.Create; + FUIStatus := duiStarting; FDefaultFont := True; memo.Align := alClient; + memo.ReadOnly := False; + memo.IsDebugging := True; + StatusText := 'Simple Test'; - UIStatus := duiReadyForInput; + UIStatus := duiTest; end; procedure TfrmLdmlKeyboardDebug.FormDestroy(Sender: TObject); begin ResetDebug; - FreeAndNil(FEvents); UninitDeadkeys; end; @@ -224,9 +205,6 @@ end; procedure TfrmLdmlKeyboardDebug.memoGotFocus(Sender: TObject); begin - if UIStatus = duiReadyForInput then - UIStatus := duiFocusedForInput; - memoSelMove(memo); end; @@ -236,30 +214,15 @@ begin memoSelMove(memo); end; -procedure TfrmLdmlKeyboardDebug.memoLostFocus(Sender: TObject); -begin - if UIStatus = duiFocusedForInput then - UIStatus := duiReadyForInput; -end; - function TfrmLdmlKeyboardDebug.HandleMemoKeydown(var Message: TMessage): Boolean; begin - if (Message.wParam = VK_ESCAPE) and - (GetKeyState(VK_SHIFT) < 0) and - (UIStatus <> duiPaused) then // I4033 - UIStatus := duiPaused - else if (Message.wParam = VK_F6) and + if (Message.wParam = VK_F6) and (GetKeyState(VK_CONTROL) >= 0) and - (GetKeyState(VK_MENU) >= 0) and - (UIStatus <> duiFocusedForInput) then + (GetKeyState(VK_MENU) >= 0) then begin EditorMemo.SetFocus; end - else if (Message.wParam = VK_ESCAPE) and - (GetKeyState(VK_SHIFT) < 0) and - (UIStatus = duiPaused) then - UIStatus := duiFocusedForInput - else if UIStatus in [duiTest, duiFocusedForInput] then + else if UIStatus = duiTest then begin Exit(ProcessKeyEvent(Message)); end @@ -274,9 +237,9 @@ procedure TfrmLdmlKeyboardDebug.memoMessage(Sender: TObject; var Message: TMessa begin Handled := False; - if UIStatus = duiClosing then + if UIStatus <> duiTest then begin - Exit; // Don't process while destroying... + Exit; end; case Message.Msg of @@ -384,63 +347,35 @@ begin Exit(True); end; - FEvents.Clear; - FEvents.AddLdmlStateItems(FDebugCore.State, vkey, modifier, debugkeyboard); + Run(vkey); - FRunning := True; - SetCurrentEvent(0); - Run; + UpdateDeadkeys; end else begin - FEvents.Clear; Result := False; end; end; -procedure TfrmLdmlKeyboardDebug.SetCurrentEvent(Value: Integer); +function UsvToString(p: pkm_core_usv): string; begin - _FCurrentEvent := Value; + Result := ''; + while p^ <> 0 do + begin + Result := Result + Char.ConvertFromUtf32(p^); + Inc(p); + end; end; -procedure TfrmLdmlKeyboardDebug.Run; -begin - FRunning := True; - try - while (_FCurrentEvent < FEvents.Count) do - begin - ExecuteEvent(_FCurrentEvent); - SetCurrentEvent(_FCurrentEvent + 1); - if UIStatus = duiPaused then // I4033 - Exit; - end; - finally - FRunning := False; - EnableUI; - UpdateCharacterGrid; - // We want to refresh the memo and character grid for rapid typing - memo.Update; - sgChars.Update; +procedure TfrmLdmlKeyboardDebug.Run(vkey: Word); + + procedure DoAlert; + begin + MessageBeep(0); end; - if UIStatus <> duiTest then - if memo.Focused - then UIStatus := duiFocusedForInput - else UIStatus := duiReadyForInput; -end; -{ Stores } -procedure TfrmLdmlKeyboardDebug.ExecuteEvent(n: Integer); -begin - memo.ReadOnly := False; - memo.Selection := FSavedSelection; - ExecuteEventAction(n); - FSavedSelection := memo.Selection; - memo.ReadOnly := True; -end; - -procedure TfrmLdmlKeyboardDebug.ExecuteEventAction(n: Integer); type TMemoSelectionState = record Selection: TMemoSelection; @@ -481,126 +416,6 @@ procedure TfrmLdmlKeyboardDebug.ExecuteEventAction(n: Integer); UpdateDeadkeys; end; - procedure DoBackspace(BackspaceType: km_core_backspace_type); - var - m, n: Integer; - dk: TDeadKeyInfo; - state: TMemoSelectionState; - begin - // Offset is zero-based, but string is 1-based. Beware! - state := SaveMemoSelectionState; - n := memo.SelStart; - m := n; - - if memo.SelLength > 0 then - begin - // If the memo has a selection, we have given Core an empty context, - // which forces it to emit a KM_CORE_BT_UNKNOWN backspace, which is - // exactly what we want here. We just delete the selection - Assert(BackspaceType = KM_CORE_BT_UNKNOWN); - memo.SelText := ''; - RealignMemoSelectionState(state); - Exit; - end; - - case BackspaceType of - KM_CORE_BT_MARKER: - begin - Assert(m >= 1); - Assert(memo.Text[m] = #$FFFC); - dk := FDeadkeys.GetFromPosition(m-1); - Assert(Assigned(dk)); - dk.Delete; - Dec(m); - end; - KM_CORE_BT_CHAR: - begin - Assert(m >= 1); - Assert(memo.Text[m] <> #$FFFC); - // Delete surrogate pairs - if (m > 1) and - Uni_IsSurrogate2(memo.Text[m]) and - Uni_IsSurrogate1(memo.Text[m-1]) then - Dec(m, 2) - // Delete \r\n line breaks - else if (m > 1) and - (memo.Text[m] = #$0A) and - (memo.Text[m-1] = #$0D) then - Dec(m, 2) - else - Dec(m); - end; - KM_CORE_BT_UNKNOWN: - begin - while (m >= 1) and (memo.Text[m] = #$FFFC) do - begin - dk := FDeadkeys.GetFromPosition(m-1); - Assert(Assigned(dk)); - dk.Delete; - Dec(m); - end; - - // Delete character - if (m > 1) and - Uni_IsSurrogate2(memo.Text[m]) and - Uni_IsSurrogate1(memo.Text[m-1]) then - Dec(m, 2) - else - Dec(m); - - // Also delete deadkeys to left of current character - while (m >= 1) and (memo.Text[m] = #$FFFC) do - begin - dk := FDeadkeys.GetFromPosition(m-1); - Assert(Assigned(dk)); - dk.Delete; - Dec(m); - end; - end; - else - Assert(False, 'Unrecognised backspace type'); - end; - - memo.Text := Copy(memo.Text, 1, m) + Copy(memo.Text, n+1, MaxInt); - memo.SelStart := m; - - RealignMemoSelectionState(state); - end; - - procedure DoDeadkey(dkCode: Integer); - var - dk: TDeadKeyInfo; - i: Integer; - state: TMemoSelectionState; - begin - dk := TDeadKeyInfo.Create; - dk.Memo := memo; - dk.Deadkey := nil; - for i := 0 to debugkeyboard.Deadkeys.Count - 1 do - if debugkeyboard.Deadkeys[i].Value = dkCode then - begin - dk.Deadkey := debugkeyboard.Deadkeys[i]; - Break; - end; - if not Assigned(dk.Deadkey) then - dk.Free //silent failure - else - begin - state := SaveMemoSelectionState; - - memo.SelText := WideChar($FFFC); - memo.SelStart := memo.SelStart + memo.SelLength; // I1603 - memo.SelLength := 0; - dk.Position := memo.SelStart - 1; - - RealignMemoSelectionState(state); - - FDeadkeys.Add(dk); - UpdateDeadkeyDisplay; - - end; - end; - procedure DoHandleShortcut(vk: UINT); begin // Because we disable shortcuts in the debug memo, there are a small set of @@ -610,7 +425,13 @@ procedure TfrmLdmlKeyboardDebug.ExecuteEventAction(n: Integer); // apart from Ctrl+A if GetKeyState(VK_CONTROL) >= 0 then + begin + if (vk = VK_RETURN) and (GetKeyState(VK_MENU) >= 0) then + begin + memo.SelText := #13#10; + end; Exit; + end; case vk of Ord('A'): memo.SelectAll; @@ -653,85 +474,187 @@ procedure TfrmLdmlKeyboardDebug.ExecuteEventAction(n: Integer); end; end; - procedure DoChar(const text: string); + function ContextToDebugString(context_items: pkm_core_context_item; offset, length: Integer): string; var - state: TMemoSelectionState; + outText: array of UInt32; + ox: Integer; + pc: pkm_core_context_item; + dk: TDeadKeyInfo; begin - state := SaveMemoSelectionState; - // Line breaks: replace \r (0x0D) with \r\n (0x0D 0x0A) so line breaks work - memo.SelText := ReplaceStr(Text, #$0D, #$0D#$0A); - memo.SelStart := memo.SelStart + memo.SelLength; // I1603 - memo.SelLength := 0; - RealignMemoSelectionState(state); - end; + SetLength(outText, length + 1); - procedure DoBell; - begin - MessageBeep(0); - end; - -begin - DisableUI; - with FEvents[n].Action do - begin - case ActionType of - KM_CORE_IT_EMIT_KEYSTROKE: DoEmitKeystroke(dwData); - KM_CORE_IT_CHAR: DoChar(Text); - KM_CORE_IT_MARKER: DoDeadkey(dwData); - KM_CORE_IT_ALERT: DoBell; - KM_CORE_IT_BACK: DoBackspace(km_core_backspace_type(dwData)); - KM_CORE_IT_PERSIST_OPT: ; //TODO - KM_CORE_IT_CAPSLOCK: ; //TODO - KM_CORE_IT_INVALIDATE_CONTEXT: ; // no-op + ox := 0; + pc := context_items; + while pc._type <> KM_CORE_CT_END do + begin + if pc._type = KM_CORE_CT_CHAR then + outText[ox] := pc.character + else + begin + dk := TDeadKeyInfo.Create; + dk.Deadkey := TDebugDeadkey.Create; + dk.Deadkey.Name := '\m{'+IntToStr(pc.marker)+'}'; + dk.Deadkey.Value := pc.marker; + dk.Position := ox + offset; + dk.SavedPosition := ox + offset; + FDeadkeys.Add(dk); + outText[ox] := $FFFC; + end; + Inc(pc); + Inc(ox); end; -// AddDEBUG(Format('%d: %d [%s]', [ActionType, dwData, Text])); - end; - EnableUI; -end; -procedure TfrmLdmlKeyboardDebug.DisableUI; + outText[ox] := 0; + + Result := USVToString(@outText[0]); + end; + +var + actions: pkm_core_actions; + context_items: pkm_core_context_item; + selection: TMemoSelection; + output: string; + lhs, rhs, context: string; + status: km_core_status; + dk: TDeadKeyInfo; + context_items_length: Integer; + state: TMemoSelectionState; + Adjustment: Integer; begin FUIDisabled := True; -// UpdateControlCaptions; -end; -procedure TfrmLdmlKeyboardDebug.EnableUI; -begin - if not FRunning then + actions := km_core_state_get_actions(FDebugCore.State); + if actions = nil then begin + GetGlobalProjectUI.Log(plsError, FDebugFileName, + 'Failed to get actions from Keyman Core', 0, 0); + Exit; + end; + + context_items := nil; + status := km_core_context_get(km_core_state_context(FDebugCore.State), @context_items); + if status <> KM_CORE_STATUS_OK then + begin + GetGlobalProjectUI.Log(plsError, FDebugFileName, + 'Failed to get context from Keyman Core with error '+IntToStr(Ord(Status)), 0, 0); + km_core_actions_dispose(actions); + Exit; + end; + + selection := memo.Selection; + + // TODO: #10471 deleting U+000D U+000A should delete as a unit + + try + if (actions.emit_keystroke = 1) and (vkey <> VK_BACK) and + (actions.code_points_to_delete = 0) and (actions.output^ = 0) then + begin + // If the keystroke is being emitted, then it was not matched by LDML, and + // must be a frame key. We exclude Bksp as a special case which needs + // additional processing. All other frame keys should be passed to the + // text control for default processing. + end + else + begin + if selection.Finish > selection.Start then + begin + // We have a selection, so we should remove it first and then continue + // as normal. We will have given Core a zero-length context, so we + // need to save everything before the start of selection before + // continuing, and cleanup any markers that were in the selection + if (actions.emit_keystroke = 0) or (vkey = VK_BACK) then + begin + state := SaveMemoSelectionState; + memo.SelText := ''; + RealignMemoSelectionState(state); + selection := memo.Selection; + end; + lhs := Copy(memo.Text, 1, selection.Start); + end + else + lhs := ''; + + context := Copy(memo.Text, lhs.Length + 1, selection.Start - lhs.Length); + rhs := Copy(memo.Text, lhs.Length + context.Length + 1, MaxInt); + + // Reinsert the context + + context_items_length := km_core_context_length(km_core_state_context(FDebugCore.State)); + Adjustment := context_items_length - selection.Start + lhs.Length; + + // Delete all markers that are in the context, because we will reinsert + // them shortly, and adjust marker positions to right of insertion point + + for dk in FDeadkeys do + begin + if (dk.Position > lhs.Length) and (dk.Position < selection.Start) then + begin + dk.Delete; + end + else if dk.Position >= selection.Start then + begin + dk.Position := dk.Position + Adjustment; + end; + end; + + // Build the new context string and create new markers + + output := ContextToDebugString(context_items, lhs.Length, context_items_length); + + // Merge left of context, context, and right of context and update memo + // insertion point position + + memo.Text := lhs + output + rhs; + selection.Start := lhs.Length + output.Length; + selection.Finish := selection.Start; + selection.Anchor := selection.Start; + memo.Selection := selection; + end; + + // actions.persist_options are not currently supported by LDML + + if actions.do_alert <> 0 then + begin + DoAlert; + end; + + if actions.emit_keystroke <> 0 then + begin + DoEmitKeystroke(vkey); + end; + + finally + km_core_actions_dispose(actions); + km_core_context_items_dispose(context_items); + FUIDisabled := False; + UpdateCharacterGrid; + + // We want to refresh the memo and character grid for rapid typing + memo.Update; + sgChars.Update; end; end; +{ Stores } + procedure TfrmLdmlKeyboardDebug.CleanupCoreState; begin FreeAndNil(FDebugCore); end; -procedure TfrmLdmlKeyboardDebug.ResetEvents; -begin - if _FCurrentEvent > 0 then - begin - FEvents.Clear; - SetCurrentEvent(0); - end; -end; - procedure TfrmLdmlKeyboardDebug.HideDebugForm; begin frmKeymanDeveloper.ShowDebug(False); // I4796 - FDebugVisible := False; ResetDebug; - UIStatus := duiReadyForInput; end; procedure TfrmLdmlKeyboardDebug.ShowDebugForm; begin + UIStatus := duiTest; + frmKeymanDeveloper.ShowDebug(True); // I4796 - FDebugVisible := True; - - //UpdateFont(nil); if not SetupDebug then Exit; @@ -741,8 +664,6 @@ end; procedure TfrmLdmlKeyboardDebug.ResetDebug; begin FreeAndNil(debugkeyboard); - SetCurrentEvent(1); - ResetEvents; ClearDeadkeys; // I1699 CleanupCoreState; memo.Text := ''; @@ -783,67 +704,6 @@ begin memo.Font := FFont; end; -procedure TfrmLdmlKeyboardDebug.SetUIStatus(const Value: TDebugUIStatus); -var - FOldUIStatus: TDebugUIStatus; -begin - if FUIStatus <> Value then - begin - FOldUIStatus := FUIStatus; - FUIStatus := Value; - - case Value of - duiTest: - begin - StatusText := 'Simple Test'; - memo.ReadOnly := False; - memo.IsDebugging := True; - end; - duiFocusedForInput: - begin - DisableUI; - StatusText := 'Focused for input'; - memo.ReadOnly := False; - memo.IsDebugging := True; - end; - duiReadyForInput: - begin - if memo.Focused then UIStatus := duiFocusedForInput - else - begin - EnableUI; - StatusText := 'Ready for input'; - memo.ReadOnly := True; - memo.IsDebugging := False; - end; - end; - duiPaused: - begin - EnableUI; - FUIDisabled := False; // I4033 - StatusText := 'Paused'; - memo.ReadOnly := True; - memo.IsDebugging := False; - end; - end; - if FOldUIStatus = duiTest then - begin - if memo.Focused then - begin - GetParentForm(memo).ActiveControl := nil; - memo.SetFocus; - end; - end - end; -end; - -function TfrmLdmlKeyboardDebug.GetCurrentEvent: TDebugEvent; -begin - if (_FCurrentEvent >= 0) and (_FCurrentEvent < FEvents.Count) - then Result := FEvents[_FCurrentEvent] - else Result := nil; -end; - function TfrmLdmlKeyboardDebug.GetDebugKeyboard: TDebugKeyboard; begin Result := debugkeyboard; @@ -971,7 +831,6 @@ begin if not memo.ReadOnly then begin - FSavedSelection := memo.Selection; UpdateCharacterGrid; // I4808 end; end; @@ -981,7 +840,8 @@ begin if csDestroying in ComponentState then Exit; - TCharacterGridRenderer.Fill(sgChars, memo.Text, FDeadkeys, memo.SelStart, memo.SelLength, memo.Selection.Anchor); + TCharacterGridRenderer.Fill(sgChars, memo.Text, FDeadkeys, memo.SelStart, + memo.SelLength, memo.Selection.Anchor, True); TCharacterGridRenderer.Size(sgChars, memo.Font); end; diff --git a/developer/src/tike/child/Keyman.Developer.UI.UfrmLdmlKeyboardEditor.pas b/developer/src/tike/child/Keyman.Developer.UI.UfrmLdmlKeyboardEditor.pas index 12ef7a3bbb..a9c41b09ec 100644 --- a/developer/src/tike/child/Keyman.Developer.UI.UfrmLdmlKeyboardEditor.pas +++ b/developer/src/tike/child/Keyman.Developer.UI.UfrmLdmlKeyboardEditor.pas @@ -83,8 +83,6 @@ procedure TfrmLdmlKeyboardEditor.StartDebugging; begin if not IsDebugVisible then begin - FDebugForm.UIStatus := duiReadyForInput; - (ProjectFileUI as TxmlLdmlProjectFileUI).Debug := True; // I4687 frmMessages.Clear; // I4686 diff --git a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas index c4b92f53e7..4f5ee40211 100644 --- a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas +++ b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas @@ -93,9 +93,6 @@ type vk: uint16_t; modifier_state: uint16_t ): Boolean; overload; - - procedure AddLdmlStateItems(state: pkm_core_state; vk, - modifier_state: uint16_t; debugkeyboard: TDebugKeyboard); end; implementation @@ -375,44 +372,6 @@ begin Assert(action._type = KM_CORE_IT_END); end; -procedure TDebugEventList.AddLdmlStateItems( - state: pkm_core_state; - vk: uint16_t; - modifier_state: uint16_t; - debugkeyboard: TDebugKeyboard -); -var - actions: pkm_core_actions; - p: pkm_core_usv; - i: UInt32; -begin - actions := km_core_state_get_actions(state); - - for i := 1 to actions.code_points_to_delete do - Action_DeleteBack(Byte(KM_CORE_BT_CHAR), 0); - - p := actions.output; - while p^ <> 0 do - begin - Action_Char(p^); - Inc(p); - end; - - // TODO: actions.persist_options - - if actions.do_alert <> 0 then - begin - // TODO - end; - - if actions.emit_keystroke <> 0 then - begin - Action_EmitKeystroke(vk); - end; - - // TODO: actions.new_caps_lock_state -end; - { TDebugEventRuleData } procedure TDebugEventRuleData.FillStoreList(event: pkm_core_state_debug_item; KeyboardMemory: PChar); diff --git a/developer/src/tike/debug/Keyman.UI.Debug.CharacterGridRenderer.pas b/developer/src/tike/debug/Keyman.UI.Debug.CharacterGridRenderer.pas index 93397fee92..4f7453c775 100644 --- a/developer/src/tike/debug/Keyman.UI.Debug.CharacterGridRenderer.pas +++ b/developer/src/tike/debug/Keyman.UI.Debug.CharacterGridRenderer.pas @@ -22,7 +22,8 @@ type class procedure Fill(grid: TStringGrid; const text: string; deadkeys: TDebugDeadkeyInfoList; - SelStart, SelLength, SelAnchor: Integer); static; + SelStart, SelLength, SelAnchor: Integer; + DeadkeysAreCalledMarkers: Boolean = False); static; class procedure Render(grid: TStringGrid; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState; CharFont: TFont); static; class procedure Size(grid: TStringGrid; CharFont: TFont); static; @@ -36,7 +37,8 @@ uses class procedure TCharacterGridRenderer.Fill(grid: TStringGrid; const text: string; deadkeys: TDebugDeadkeyInfoList; - SelStart, SelLength, SelAnchor: Integer); + SelStart, SelLength, SelAnchor: Integer; + DeadkeysAreCalledMarkers: Boolean); type TCellType = (ctChar, ctDeadkey); TCell = record @@ -87,7 +89,9 @@ type if not Assigned(cell.dk) then grid.Cells[x, 0] := '???' else grid.Cells[x, 0] := cell.dk.Deadkey.Name; - grid.Cells[x, 1] := 'Deadkey'; + if DeadkeysAreCalledMarkers + then grid.Cells[x, 1] := 'Marker' + else grid.Cells[x, 1] := 'Deadkey'; end else begin diff --git a/developer/src/tike/main/Keyman.System.KeymanCore.pas b/developer/src/tike/main/Keyman.System.KeymanCore.pas index 7d3a6d22c0..0e339a4113 100644 --- a/developer/src/tike/main/Keyman.System.KeymanCore.pas +++ b/developer/src/tike/main/Keyman.System.KeymanCore.pas @@ -71,6 +71,7 @@ type end; pkm_core_context_item = ^km_core_context_item; + ppkm_core_context_item = ^pkm_core_context_item; const KM_CORE_CONTEXT_ITEM_END: km_core_context_item = ( @@ -105,7 +106,7 @@ function km_core_context_items_to_utf8( ): km_core_status; cdecl; external keymancore delayed; procedure km_core_context_items_dispose( - const context_items: km_core_context_item + context_items: pkm_core_context_item ); cdecl; external keymancore delayed; function km_core_context_set( @@ -115,7 +116,7 @@ function km_core_context_set( function km_core_context_get( context: pkm_core_context; - var context_items: pkm_core_context_item + context_items: ppkm_core_context_item ): km_core_status; cdecl; external keymancore delayed; procedure km_core_context_clear( @@ -133,7 +134,9 @@ function km_core_context_shrink( prefix: pkm_core_context_item ): km_core_status; cdecl; external keymancore delayed; - +function km_core_context_length( + context: pkm_core_context +): uint32; cdecl; external keymancore delayed; type km_core_option_scope = ( @@ -314,6 +317,10 @@ function km_core_state_get_actions( state: pkm_core_state ): pkm_core_actions; cdecl; external keymancore delayed; +function km_core_actions_dispose( + actions: pkm_core_actions +): km_core_status; cdecl; external keymancore delayed; + function km_core_state_to_json( state: pkm_core_state; buf: PAnsiChar; From fa39ae0b22209375c3f6db6b4098bd5623157c91 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 23 Jan 2024 13:12:47 +0700 Subject: [PATCH 3/5] chore(core): fixup types on unit test --- core/tests/unit/kmnkbd/action_api.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/tests/unit/kmnkbd/action_api.cpp b/core/tests/unit/kmnkbd/action_api.cpp index 50f39ffdce..83ddbb5b59 100644 --- a/core/tests/unit/kmnkbd/action_api.cpp +++ b/core/tests/unit/kmnkbd/action_api.cpp @@ -221,12 +221,12 @@ int main(int argc, char *argv []) { km_core_actions act = {0}; std::cout << "sizeof(km_core_actions): " << sizeof(km_core_actions) << std::endl; - std::cout << "&km_core_actions.code_points_to_delete: " << ((int)(&act.code_points_to_delete)-(int)(&act)) << std::endl; - std::cout << "&km_core_actions.output: " << ((int)(&act.output)-(int)(&act)) << std::endl; - std::cout << "&km_core_actions.persist_options: " << ((int)(&act.persist_options)-(int)(&act)) << std::endl; - std::cout << "&km_core_actions.do_alert: " << ((int)(&act.do_alert)-(int)(&act)) << std::endl; - std::cout << "&km_core_actions.emit_keystroke: " << ((int)(&act.emit_keystroke)-(int)(&act)) << std::endl; - std::cout << "&km_core_actions.new_caps_lock_state: " << ((int)(&act.new_caps_lock_state)-(int)(&act)) << std::endl; + std::cout << "&km_core_actions.code_points_to_delete: " << ((intptr_t)(&act.code_points_to_delete)-(intptr_t)(&act)) << std::endl; + std::cout << "&km_core_actions.output: " << ((intptr_t)(&act.output)-(intptr_t)(&act)) << std::endl; + std::cout << "&km_core_actions.persist_options: " << ((intptr_t)(&act.persist_options)-(intptr_t)(&act)) << std::endl; + std::cout << "&km_core_actions.do_alert: " << ((intptr_t)(&act.do_alert)-(intptr_t)(&act)) << std::endl; + std::cout << "&km_core_actions.emit_keystroke: " << ((intptr_t)(&act.emit_keystroke)-(intptr_t)(&act)) << std::endl; + std::cout << "&km_core_actions.new_caps_lock_state: " << ((intptr_t)(&act.new_caps_lock_state)-(intptr_t)(&act)) << std::endl; // actions test_two_backspaces(); From ebccb23c41d21a63b7f82f99575e2b03e447f7e7 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 23 Jan 2024 13:34:41 +0700 Subject: [PATCH 4/5] chore(developer): remove old proc reference --- .../child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.dfm | 1 - 1 file changed, 1 deletion(-) diff --git a/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.dfm b/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.dfm index 53b4975e43..bf8bba4cbd 100644 --- a/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.dfm +++ b/developer/src/tike/child/Keyman.Developer.UI.Debug.UfrmLdmlKeyboardDebug.dfm @@ -37,7 +37,6 @@ inherited frmLdmlKeyboardDebug: TfrmLdmlKeyboardDebug OnChange = memoChange OnClick = memoClick OnEnter = memoGotFocus - OnExit = memoLostFocus OnKeyUp = memoKeyUp OnMessage = memoMessage IsDebugging = False From 41cc2f4d1e4e828c791ce8e071eb04afe5968d4d Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 26 Jan 2024 06:37:09 +0700 Subject: [PATCH 5/5] feat(developer): make context_get and context_length public again Rolls back the privatisation of the km_core_context_get and km_core_context_length APIs because the debugger uses them. --- core/include/keyman/keyman_core_api_context.h | 37 ++++++++++++++++++- core/src/actions_normalize.cpp | 6 +-- core/src/context.hpp | 32 ---------------- core/src/context_helpers.cpp | 2 +- core/src/km_core_context_api.cpp | 4 +- core/src/km_core_state_api.cpp | 4 +- core/tests/unit/kmnkbd/context_api.cpp | 14 +++---- core/tests/unit/kmnkbd/state_api.cpp | 4 +- core/tests/unit/kmnkbd/state_context_api.cpp | 4 +- core/tests/unit/kmx/kmx.cpp | 4 +- core/tests/unit/ldml/ldml.cpp | 2 +- .../unit/ldml/test_context_normalization.cpp | 4 +- linux/debian/libkeymancore.symbols | 2 + 13 files changed, 62 insertions(+), 57 deletions(-) diff --git a/core/include/keyman/keyman_core_api_context.h b/core/include/keyman/keyman_core_api_context.h index dfa271e7b2..7b42d1c820 100644 --- a/core/include/keyman/keyman_core_api_context.h +++ b/core/include/keyman/keyman_core_api_context.h @@ -92,7 +92,7 @@ km_core_state_get_intermediate_context(km_core_state *state, km_core_context_ite ##### Description: Free the allocated memory belonging to a `km_core_context_item` array previously returned by `km_core_state_get_intermediate_context` (internally, also -`context_items_from_utf16` and `context_get`) +`context_items_from_utf16` and `km_core_context_get`) ##### Parameters: - __context_items__: A pointer to the start of the `km_core_context_item` array to be disposed of. @@ -182,6 +182,41 @@ KMN_API size_t km_core_context_item_list_size(km_core_context_item const *context_items); +/** + * + * Copies all items in the context into a new array and returns the new array. + * This must be disposed of by caller using `km_core_context_items_dispose`. + * + * @return km_core_status + * * `KM_CORE_STATUS_OK`: On success. + * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are + * null. + * * `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be + * allocated for the output buffer. + * + * @param context A pointer to an opaque context object + * @param out A pointer to the result variable: A pointer to the start + * of the `km_core_context_item` array containing a copy of + * the context. Terminated with a type of `KM_CORE_CT_END`. + * Must be disposed of with + * `km_core_context_items_dispose`. + */ +KMN_API +km_core_status +km_core_context_get(km_core_context const *context, + km_core_context_item **out); + +/** + * Return the number of items in the context. + * + * @return size_t The number of items in the context, and will return 0 if + * passed a null `context` pointer. + * @param context A pointer to an opaque context object +*/ +KMN_API +size_t +km_core_context_length(km_core_context *); + #if defined(__cplusplus) } // extern "C" #endif diff --git a/core/src/actions_normalize.cpp b/core/src/actions_normalize.cpp index 8dc944620a..ded302fe15 100644 --- a/core/src/actions_normalize.cpp +++ b/core/src/actions_normalize.cpp @@ -228,7 +228,7 @@ icu::UnicodeString context_items_to_unicode_string(km_core_context const *contex km_core_context_item *items = nullptr; km_core_status status; - if((status = context_get(context, &items)) != KM_CORE_STATUS_OK) { + if((status = km_core_context_get(context, &items)) != KM_CORE_STATUS_OK) { DebugLog("Failed to retrieve context with %s", status); return nullString; } @@ -297,8 +297,8 @@ bool km::core::actions_update_app_context_nfu( km_core_status status = KM_CORE_STATUS_OK; km_core_context_item *items = nullptr; - if((status = context_get(cached_context, &items)) != KM_CORE_STATUS_OK) { - DebugLog("context_get failed with %d", status); + if((status = km_core_context_get(cached_context, &items)) != KM_CORE_STATUS_OK) { + DebugLog("km_core_context_get failed with %d", status); return false; } diff --git a/core/src/context.hpp b/core/src/context.hpp index 5f71ab86dd..9366835839 100644 --- a/core/src/context.hpp +++ b/core/src/context.hpp @@ -169,38 +169,6 @@ km_core_status context_items_to_utf32(km_core_context_item const *item, km_core_usv *buf, size_t *buf_size); -/** - * - * Copies all items in the context into a new array and returns the new array. - * This must be disposed of by caller using `km_core_context_items_dispose`. - * - * @return km_core_status - * * `KM_CORE_STATUS_OK`: On success. - * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are - * null. - * * `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be - * allocated for the output buffer. - * - * @param context A pointer to an opaque context object - * @param out A pointer to the result variable: A pointer to the start - * of the `km_core_context_item` array containing a copy of - * the context. Terminated with a type of `KM_CORE_CT_END`. - * Must be disposed of with - * `km_core_context_items_dispose`. - */ -km_core_status -context_get(km_core_context const *context, - km_core_context_item **out); - -/** - * Return the number of items in the context. - * - * @return size_t The number of items in the context, and will return 0 if - * passed a null `context` pointer. - * @param context A pointer to an opaque context object -*/ -size_t -context_length(km_core_context *); /** * Add more items to the end (insertion point) of the context. If these exceed diff --git a/core/src/context_helpers.cpp b/core/src/context_helpers.cpp index c3e26ac207..6c687f3200 100644 --- a/core/src/context_helpers.cpp +++ b/core/src/context_helpers.cpp @@ -24,7 +24,7 @@ km_core_cp* km::core::get_context_as_string(km_core_context *context) { size_t buf_size = 0; km_core_context_item* context_items = nullptr; - if(context_get(context, &context_items) != KM_CORE_STATUS_OK) { + if(km_core_context_get(context, &context_items) != KM_CORE_STATUS_OK) { return nullptr; } diff --git a/core/src/km_core_context_api.cpp b/core/src/km_core_context_api.cpp index 50d0658816..134200b711 100644 --- a/core/src/km_core_context_api.cpp +++ b/core/src/km_core_context_api.cpp @@ -153,7 +153,7 @@ km_core_status km_core_context_set(km_core_context *ctxt, km_core_context_item c } -km_core_status context_get(km_core_context const *ctxt, +km_core_status km_core_context_get(km_core_context const *ctxt, km_core_context_item **out_ptr) { assert(ctxt); assert(out_ptr); @@ -184,7 +184,7 @@ void km_core_context_clear(km_core_context *ctxt) } -size_t context_length(km_core_context *ctxt) +size_t km_core_context_length(km_core_context *ctxt) { assert(ctxt); return ctxt ? ctxt->size() : 0; diff --git a/core/src/km_core_state_api.cpp b/core/src/km_core_state_api.cpp index 475c70db0d..8b8807b1d2 100644 --- a/core/src/km_core_state_api.cpp +++ b/core/src/km_core_state_api.cpp @@ -310,11 +310,11 @@ km_core_cp * km_core_state_context_debug( return _new_error_string(u""); } } else if(context_type == KM_CORE_DEBUG_CONTEXT_CACHED) { - if(context_get(km_core_state_context(state), &context_items) != KM_CORE_STATUS_OK) { + if(km_core_context_get(km_core_state_context(state), &context_items) != KM_CORE_STATUS_OK) { return _new_error_string(u""); } } else if(context_type == KM_CORE_DEBUG_CONTEXT_APP) { - if(context_get(km_core_state_app_context(state), &context_items) != KM_CORE_STATUS_OK) { + if(km_core_context_get(km_core_state_app_context(state), &context_items) != KM_CORE_STATUS_OK) { return _new_error_string(u""); } } else { diff --git a/core/tests/unit/kmnkbd/context_api.cpp b/core/tests/unit/kmnkbd/context_api.cpp index e0f675ded3..0b3bcf3673 100644 --- a/core/tests/unit/kmnkbd/context_api.cpp +++ b/core/tests/unit/kmnkbd/context_api.cpp @@ -79,19 +79,19 @@ int main(int, char * []) km_core_context_items_dispose(ctxt2); // Test lengths, these are Unicode Scalar Values, not utf16 codeunits. - if(context_length(&mock_ctxt1) != bmp_ctxt_size) return __LINE__; - if(context_length(&mock_ctxt2) != smp_ctxt_size) return __LINE__; + if(km_core_context_length(&mock_ctxt1) != bmp_ctxt_size) return __LINE__; + if(km_core_context_length(&mock_ctxt2) != smp_ctxt_size) return __LINE__; // retrieve bmp context and check it's okay. km_core_context_item *tmp_ctxt; - try_status(context_get(&mock_ctxt1, &tmp_ctxt)); + try_status(km_core_context_get(&mock_ctxt1, &tmp_ctxt)); ctxt_size=sizeof ctxt_buffer/sizeof(km_core_cp); try_status(context_items_to_utf16(tmp_ctxt, ctxt_buffer, &ctxt_size)); km_core_context_items_dispose(tmp_ctxt); if (initial_bmp_context != ctxt_buffer) return __LINE__; // retrieve smp context and check it's okay. - try_status(context_get(&mock_ctxt2, &tmp_ctxt)); + try_status(km_core_context_get(&mock_ctxt2, &tmp_ctxt)); ctxt_size=sizeof ctxt_buffer/sizeof(km_core_cp); try_status(context_items_to_utf16(tmp_ctxt, ctxt_buffer, &ctxt_size)); km_core_context_items_dispose(tmp_ctxt); @@ -99,7 +99,7 @@ int main(int, char * []) // Call km_core_context_clear km_core_context_clear(&mock_ctxt2); - if(context_length(&mock_ctxt2) != 0) return __LINE__; + if(km_core_context_length(&mock_ctxt2) != 0) return __LINE__; // Mutation tests try_status(context_shrink(&mock_ctxt1, 42, nullptr)); @@ -117,7 +117,7 @@ int main(int, char * []) // Check it matches. The marker will be elided during the conversion. ctxt_size=sizeof ctxt_buffer/sizeof(km_core_cp); - try_status(context_get(&mock_ctxt1, &tmp_ctxt)); + try_status(km_core_context_get(&mock_ctxt1, &tmp_ctxt)); try_status(context_items_to_utf16(tmp_ctxt, ctxt_buffer, &ctxt_size)); if (std::u16string(u"Hello World!") != ctxt_buffer) return __LINE__; km_core_context_items_dispose(tmp_ctxt); @@ -128,7 +128,7 @@ int main(int, char * []) // expected if you go by the test string above. try_status(context_shrink(&mock_ctxt1, 8, ctxt1)); ctxt_size=sizeof ctxt_buffer/sizeof(km_core_cp); - try_status(context_get(&mock_ctxt1, &tmp_ctxt)); + try_status(km_core_context_get(&mock_ctxt1, &tmp_ctxt)); try_status(context_items_to_utf16(tmp_ctxt, ctxt_buffer, &ctxt_size)); if (std::u16string(u"Bye, Hello") != ctxt_buffer) return __LINE__; diff --git a/core/tests/unit/kmnkbd/state_api.cpp b/core/tests/unit/kmnkbd/state_api.cpp index a28cc04490..1da70c33fa 100644 --- a/core/tests/unit/kmnkbd/state_api.cpp +++ b/core/tests/unit/kmnkbd/state_api.cpp @@ -133,9 +133,9 @@ int main(int argc, char * argv[]) try_status(context_items_from_utf16(u"Hello 😁", &citems)); try_status(km_core_context_set(km_core_state_context(test_state), citems)); km_core_context_items_dispose(citems); - if(context_length(km_core_state_context(test_state)) != 7) + if(km_core_context_length(km_core_state_context(test_state)) != 7) return __LINE__; - if(context_length(km_core_state_context(test_clone)) != 0) + if(km_core_context_length(km_core_state_context(test_clone)) != 0) return __LINE__; // Overwrite some data. diff --git a/core/tests/unit/kmnkbd/state_context_api.cpp b/core/tests/unit/kmnkbd/state_context_api.cpp index 9b1a2b5da8..32af9d88e6 100644 --- a/core/tests/unit/kmnkbd/state_context_api.cpp +++ b/core/tests/unit/kmnkbd/state_context_api.cpp @@ -51,7 +51,7 @@ setup(const char *keyboard, const km_core_cp *context) { bool is_identical_context(km_core_cp const *cached_context) { size_t buf_size; - try_status(context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); try_status(context_items_to_utf16(citems, nullptr, &buf_size)); km_core_cp *new_cached_context = new km_core_cp[buf_size]; try_status(context_items_to_utf16(citems, new_cached_context, &buf_size)); @@ -145,7 +145,7 @@ test_context_set_if_needed_cached_context_has_markers() { km_core_context_item *citems_new; - try_status(context_get(km_core_state_context(test_state), &citems_new)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems_new)); for (int i = 0; citems[i].type || citems_new[i].type; i++) { assert(citems_new[i].type == citems[i].type); diff --git a/core/tests/unit/kmx/kmx.cpp b/core/tests/unit/kmx/kmx.cpp index e2dd8cb275..ac93441c1a 100644 --- a/core/tests/unit/kmx/kmx.cpp +++ b/core/tests/unit/kmx/kmx.cpp @@ -244,7 +244,7 @@ run_test(const km::core::path &source, const km::core::path &compiled) { // Compare context and text store at each step // should be identical unless an action has caused the context to be invalidated size_t n = 0; - try_status(context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); try_status(context_items_to_utf16(citems, nullptr, &n)); km_core_cp *core_context_str = new km_core_cp[n]; try_status(context_items_to_utf16(citems, core_context_str, &n)); @@ -271,7 +271,7 @@ run_test(const km::core::path &source, const km::core::path &compiled) { // Compare final output - retrieve internal context size_t n = 0; - try_status(context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); try_status(context_items_to_utf16(citems, nullptr, &n)); km_core_cp *core_context_str = new km_core_cp[n]; try_status(context_items_to_utf16(citems, core_context_str, &n)); diff --git a/core/tests/unit/ldml/ldml.cpp b/core/tests/unit/ldml/ldml.cpp index a87cd9d647..ef1d4eb030 100644 --- a/core/tests/unit/ldml/ldml.cpp +++ b/core/tests/unit/ldml/ldml.cpp @@ -199,7 +199,7 @@ verify_context(std::u16string& text_store, km_core_state* &test_state, std::vect // Compare context and text store at each step - should be identical size_t n = 0; km_core_context_item* citems = nullptr; - try_status(context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); try_status(context_items_to_utf16(citems, nullptr, &n)); km_core_cp *buf = new km_core_cp[n]; try_status(context_items_to_utf16(citems, buf, &n)); diff --git a/core/tests/unit/ldml/test_context_normalization.cpp b/core/tests/unit/ldml/test_context_normalization.cpp index e2954b54d6..f9c9a694ff 100644 --- a/core/tests/unit/ldml/test_context_normalization.cpp +++ b/core/tests/unit/ldml/test_context_normalization.cpp @@ -63,9 +63,9 @@ bool is_identical_context(km_core_cp const *cached_context, km_core_debug_contex debug_context(context_type); if(context_type == KM_CORE_DEBUG_CONTEXT_APP) { - try_status(context_get(km_core_state_app_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_app_context(test_state), &citems)); } else { - try_status(context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); } try_status(context_items_to_utf16(citems, nullptr, &buf_size)); km_core_cp* new_cached_context = new km_core_cp[buf_size]; diff --git a/linux/debian/libkeymancore.symbols b/linux/debian/libkeymancore.symbols index 0ba4e316f3..7f8d8945dd 100644 --- a/linux/debian/libkeymancore.symbols +++ b/linux/debian/libkeymancore.symbols @@ -4,8 +4,10 @@ libkeymancore.so.1 libkeymancore #MINVER# (c++|optional)"typeinfo name for std::codecvt_utf8_utf16@Base" 17.0.244 km_core_actions_dispose@Base 17.0.197 km_core_context_clear@Base 17.0.195 + km_core_context_get@Base 17.0.195 km_core_context_item_list_size@Base 17.0.195 km_core_context_items_dispose@Base 17.0.195 + km_core_context_length@Base 17.0.195 km_core_context_set@Base 17.0.195 km_core_cp_dispose@Base 17.0.244 km_core_event@Base 17.0.195