diff --git a/.gitattributes b/.gitattributes index 0e8672cd4b..3d66bbee1c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4976,7 +4976,9 @@ components/synedit/languages/syneditstrconst.uk.po svneol=native#text/plain components/synedit/languages/syneditstrconst.zh_CN.po svneol=native#text/plain components/synedit/lazsyneditmousecmdstypes.pp svneol=native#text/pascal components/synedit/lazsynedittext.pas svneol=native#text/pascal +components/synedit/lazsyngtk2imm.pas svneol=native#text/pascal components/synedit/lazsynimm.pas svneol=native#text/pascal +components/synedit/lazsynimmbase.pas svneol=native#text/pascal components/synedit/lazsyntextarea.pp svneol=native#text/pascal components/synedit/synbeautifier.pas svneol=native#text/plain components/synedit/synbeautifierpascal.pas svneol=native#text/pascal diff --git a/components/synedit/allsynedit.pas b/components/synedit/allsynedit.pas index c804ec8fa4..03eb2ad055 100644 --- a/components/synedit/allsynedit.pas +++ b/components/synedit/allsynedit.pas @@ -32,7 +32,7 @@ uses SynHighlighterIni, SynEditMarkupSpecialChar, SynEditTextDoubleWidthChars, SynEditTextSystemCharWidth, SynEditMarkupIfDef, SynPluginMultiCaret, synhighlighterpike, SynEditMarkupFoldColoring, SynEditViewedLineMap, - SynEditWrappedView, SynBeautifierPascal, LazarusPackageIntf; + SynEditWrappedView, SynBeautifierPascal, LazSynIMMBase, LazarusPackageIntf; implementation diff --git a/components/synedit/lazsyngtk2imm.pas b/components/synedit/lazsyngtk2imm.pas new file mode 100644 index 0000000000..dcec32ce3d --- /dev/null +++ b/components/synedit/lazsyngtk2imm.pas @@ -0,0 +1,79 @@ +unit LazSynGtk2IMM; + +{$mode objfpc}{$H+} + +interface + +uses + {$ifdef LCLGtk2} + gtk2, Gtk2Globals, + {$endif} + Classes, SysUtils, Messages, LMessages, LazSynIMMBase, SynEditKeyCmds; + + +type + + { LazSynImeGtk2 } + + LazSynImeGtk2 = class(LazSynIme) + private + FIMESelText: string; + public + procedure WMImeComposition(var Message: TMessage); override; + end; + + +implementation + +uses + SynEdit; + +{ LazSynImeGtk2 } + +procedure LazSynImeGtk2.WMImeComposition(var Message: TMessage); +{$IFDEF WITH_GTK2_IM} +var + IMStr:string; + i:Integer; +{$ENDIF} +begin +{$IFDEF WITH_GTK2_IM} + if (not FriendEdit.ReadOnly) then + begin + if (Message.WParam and GTK_IM_FLAG_START<>0) then + FIMESelText := FriendEdit.SelText; + // to do : accurate candidate position + // set candidate position + if (Message.WParam and (GTK_IM_FLAG_START or GTK_IM_FLAG_PREEDIT))<>0 then + IM_Context_Set_Cursor_Pos(FriendEdit.CaretXPix,FriendEdit.CaretYPix+FriendEdit.LineHeight); + // valid string at composition & commit + if Message.WParam and (GTK_IM_FLAG_COMMIT or GTK_IM_FLAG_PREEDIT)<>0 then + begin + // insert preedit or commit string + IMStr:=pchar(Message.LParam); + for i:=1 to Length(IMStr) do + TSynEdit(FriendEdit).CommandProcessor(ecChar,IMStr[i],nil); + // select last preedit + if (Message.WParam and GTK_IM_FLAG_COMMIT=0) then + begin + if Length(IMStr)>0 then + for i:=1 to Length(UTF8Decode(IMStr)) do + TSynEdit(FriendEdit).CommandProcessor(ecSelLeft,#0,nil) + end + else + FIMESelText:=''; + end; + // end composition + if (Message.WParam and GTK_IM_FLAG_END<>0) and (FIMESelText<>'') then + begin + TSynEdit(FriendEdit).ClearSelection; + // restore selection before preedit. + for i:=1 to Length(FIMESelText) do + TSynEdit(FriendEdit).CommandProcessor(ecChar,FIMESelText[i],nil); + end; + end; +{$ENDIF} +end; + +end. + diff --git a/components/synedit/lazsynimm.pas b/components/synedit/lazsynimm.pas index 057f4bee3a..4d91508c79 100644 --- a/components/synedit/lazsynimm.pas +++ b/components/synedit/lazsynimm.pas @@ -9,7 +9,7 @@ unit LazSynIMM; interface uses - windows, imm, Classes, SysUtils, Controls, LazLoggerBase, LCLType, LazUTF8, Graphics, + windows, imm, LazSynIMMBase, Classes, SysUtils, Controls, LazLoggerBase, LCLType, LazUTF8, Graphics, SynEditMiscClasses, SynTextDrawer, SynEditPointClasses, SynEditMarkupSelection, SynEditMarkup, SynEditTypes, SynEditKeyCmds, LazSynEditText, SynEditTextBase; @@ -20,36 +20,16 @@ const {$ENDIF}{$ENDIF} type - { LazSynIme } + { LazSynWinIme } - LazSynIme = class(TSynEditFriend) - private - FInvalidateLinesMethod: TInvalidateLines; - FOnIMEEnd: TNotifyEvent; - FOnIMEStart: TNotifyEvent; - FIMEActive: Boolean; + LazSynWinIme = class(LazSynIme) protected - FInCompose: Boolean; - procedure InvalidateLines(FirstLine, LastLine: integer); - procedure StopIme(Success: Boolean); virtual; - procedure DoIMEStarted; - procedure DoIMEEnded; - public - constructor Create(AOwner: TSynEditBase); reintroduce; - procedure WMImeRequest(var Msg: TMessage); virtual; - procedure WMImeNotify(var Msg: TMessage); virtual; - procedure WMImeComposition(var Msg: TMessage); virtual; - procedure WMImeStartComposition(var Msg: TMessage); virtual; - procedure WMImeEndComposition(var Msg: TMessage); virtual; - procedure FocusKilled; virtual; - property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod; - property OnIMEStart: TNotifyEvent read FOnIMEStart write FOnIMEStart; - property OnIMEEnd: TNotifyEvent read FOnIMEEnd write FOnIMEEnd; + procedure StopIme(Success: Boolean); override; end; { LazSynImeSimple } - LazSynImeSimple = class(LazSynIme) + LazSynImeSimple = class(LazSynWinIme) private FImeBlockSelection: TSynEditSelection; FImeWinX, FImeWinY: Integer; @@ -77,7 +57,7 @@ type { LazSynImeFull } - LazSynImeFull = class(LazSynIme) + LazSynImeFull = class(LazSynWinIme) private FAdjustLeftCharForTargets: Boolean; FLeftPosForTarget, FRightPosForTarget: Integer; @@ -116,14 +96,9 @@ type implementation -{ LazSynIme } +{ LazSynWinIme } -procedure LazSynIme.InvalidateLines(FirstLine, LastLine: integer); -begin - FInvalidateLinesMethod(FirstLine, LastLine); -end; - -procedure LazSynIme.StopIme(Success: Boolean); +procedure LazSynWinIme.StopIme(Success: Boolean); var imc: HIMC; begin @@ -137,54 +112,7 @@ begin ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); ImmReleaseContext(FriendEdit.Handle, imc); end; - DoIMEEnded; -end; - -procedure LazSynIme.DoIMEStarted; -begin - if FIMEActive then - exit; - FIMEActive := True; - if FOnIMEStart <> nil then - FOnIMEStart(FriendEdit); -end; - -procedure LazSynIme.DoIMEEnded; -begin - if not FIMEActive then - exit; - FIMEActive := False; - if FOnIMEEnd <> nil then - FOnIMEEnd(FriendEdit); -end; - -constructor LazSynIme.Create(AOwner: TSynEditBase); -begin - FriendEdit := AOwner; -end; - -procedure LazSynIme.WMImeRequest(var Msg: TMessage); -begin -end; - -procedure LazSynIme.WMImeComposition(var Msg: TMessage); -begin -end; - -procedure LazSynIme.WMImeNotify(var Msg: TMessage); -begin -end; - -procedure LazSynIme.WMImeStartComposition(var Msg: TMessage); -begin -end; - -procedure LazSynIme.WMImeEndComposition(var Msg: TMessage); -begin -end; - -procedure LazSynIme.FocusKilled; -begin + inherited StopIme(Success); end; { LazSynImeSimple } diff --git a/components/synedit/lazsynimmbase.pas b/components/synedit/lazsynimmbase.pas new file mode 100644 index 0000000000..7972e464bc --- /dev/null +++ b/components/synedit/lazsynimmbase.pas @@ -0,0 +1,101 @@ +unit LazSynIMMBase; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Messages, SynEditMiscClasses, SynEditPointClasses; + +type + + { LazSynIme } + + LazSynIme = class(TSynEditFriend) + private + FInvalidateLinesMethod: TInvalidateLines; + FOnIMEEnd: TNotifyEvent; + FOnIMEStart: TNotifyEvent; + FIMEActive: Boolean; + protected + FInCompose: Boolean; + procedure InvalidateLines(FirstLine, LastLine: integer); + procedure StopIme(Success: Boolean); virtual; + procedure DoIMEStarted; + procedure DoIMEEnded; + public + constructor Create(AOwner: TSynEditBase); reintroduce; + procedure WMImeRequest(var Msg: TMessage); virtual; + procedure WMImeNotify(var Msg: TMessage); virtual; + procedure WMImeComposition(var Msg: TMessage); virtual; + procedure WMImeStartComposition(var Msg: TMessage); virtual; + procedure WMImeEndComposition(var Msg: TMessage); virtual; + procedure FocusKilled; virtual; + property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod; + property OnIMEStart: TNotifyEvent read FOnIMEStart write FOnIMEStart; + property OnIMEEnd: TNotifyEvent read FOnIMEEnd write FOnIMEEnd; + end; + +implementation + +{ LazSynIme } + +procedure LazSynIme.InvalidateLines(FirstLine, LastLine: integer); +begin + FInvalidateLinesMethod(FirstLine, LastLine); +end; + +procedure LazSynIme.StopIme(Success: Boolean); +begin + DoIMEEnded; +end; + +procedure LazSynIme.DoIMEStarted; +begin + if FIMEActive then + exit; + FIMEActive := True; + if FOnIMEStart <> nil then + FOnIMEStart(FriendEdit); +end; + +procedure LazSynIme.DoIMEEnded; +begin + if not FIMEActive then + exit; + FIMEActive := False; + if FOnIMEEnd <> nil then + FOnIMEEnd(FriendEdit); +end; + +constructor LazSynIme.Create(AOwner: TSynEditBase); +begin + FriendEdit := AOwner; +end; + +procedure LazSynIme.WMImeRequest(var Msg: TMessage); +begin +end; + +procedure LazSynIme.WMImeComposition(var Msg: TMessage); +begin +end; + +procedure LazSynIme.WMImeNotify(var Msg: TMessage); +begin +end; + +procedure LazSynIme.WMImeStartComposition(var Msg: TMessage); +begin +end; + +procedure LazSynIme.WMImeEndComposition(var Msg: TMessage); +begin +end; + +procedure LazSynIme.FocusKilled; +begin +end; + +end. + diff --git a/components/synedit/synedit.lpk b/components/synedit/synedit.lpk index 65bbc240fb..9750c91a65 100644 --- a/components/synedit/synedit.lpk +++ b/components/synedit/synedit.lpk @@ -379,7 +379,7 @@ If you wish to allow use of your version of these files only under the terms of - + @@ -389,6 +389,15 @@ If you wish to allow use of your version of these files only under the terms of + + + + + + + + + diff --git a/components/synedit/synedit.pp b/components/synedit/synedit.pp index 53e4c1449b..71568f5ce7 100644 --- a/components/synedit/synedit.pp +++ b/components/synedit/synedit.pp @@ -49,6 +49,7 @@ unit SynEdit; {$DEFINE WinIMEFull} {$ENDIF} {$ENDIF} +{..$DEFINE Gtk2IME} {$I synedit.inc} @@ -102,9 +103,13 @@ interface {$ENDIF} uses + LazSynIMMBase, {$IFDEF WinIME} LazSynIMM, {$ENDIF} + {$IFDEF Gtk2IME} + LazSynGtk2IMM, + {$ENDIF} {$IFDEF USE_UTF8BIDI_LCL} FreeBIDI, utf8bidi, {$ENDIF} @@ -426,19 +431,25 @@ type TCustomSynEdit = class(TSynEditBase) procedure SelAvailChange(Sender: TObject); - {$IFDEF WinIME} private FImeHandler: LazSynIme; - procedure SetImeHandler(AValue: LazSynIme); + {$IFDEF Gtk2IME} + protected + procedure GTK_IMComposition(var Message: TMessage); message LM_IM_COMPOSITION; + {$ENDIF} + {$IFDEF WinIME} + private procedure WMImeRequest(var Msg: TMessage); message WM_IME_REQUEST; procedure WMImeNotify(var Msg: TMessage); message WM_IME_NOTIFY; procedure WMImeStartComposition(var Msg: TMessage); message WM_IME_STARTCOMPOSITION; procedure WMImeComposition(var Msg: TMessage); message WM_IME_COMPOSITION; procedure WMImeEndComposition(var Msg: TMessage); message WM_IME_ENDCOMPOSITION; + {$ENDIF} + private + procedure SetImeHandler(AValue: LazSynIme); protected // SynEdit takes ownership property ImeHandler: LazSynIme read FImeHandler write SetImeHandler; - {$ENDIF} private procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES; procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND; @@ -2323,6 +2334,10 @@ begin {$ENDIF} FImeHandler.InvalidateLinesMethod := @InvalidateLines; {$ENDIF} + {$IFDEF Gtk2IME} + FImeHandler := LazSynImeGtk2 .Create(Self); + FImeHandler.InvalidateLinesMethod := @InvalidateLines; + {$ENDIF} fFontDummy.Name := SynDefaultFontName; fFontDummy.Height := SynDefaultFontHeight; @@ -2654,9 +2669,7 @@ begin FreeAndNil(FRightGutterArea); FreeAndNil(FTextArea); FreeAndNil(fTSearch); - {$IFDEF WinIME} FreeAndNil(FImeHandler); - {$ENDIF} FreeAndNil(fMarkupManager); FreeAndNil(fKeyStrokes); FreeAndNil(FMouseActionSearchHandlerList); @@ -2894,12 +2907,6 @@ begin Result := ''; end; -{$IFDEF WinIME} -procedure TCustomSynEdit.WMImeRequest(var Msg: TMessage); -begin - FImeHandler.WMImeRequest(Msg); -end; - procedure TCustomSynEdit.SetImeHandler(AValue: LazSynIme); begin if FImeHandler = AValue then Exit; @@ -2907,6 +2914,19 @@ begin FImeHandler := AValue; end; +{$ifdef Gtk2IME} +procedure TCustomSynEdit.GTK_IMComposition(var Message: TMessage); +begin + FImeHandler.WMImeComposition(Message); +end; +{$endif} + +{$IFDEF WinIME} +procedure TCustomSynEdit.WMImeRequest(var Msg: TMessage); +begin + FImeHandler.WMImeRequest(Msg); +end; + procedure TCustomSynEdit.WMImeNotify(var Msg: TMessage); begin FImeHandler.WMImeNotify(Msg); @@ -5133,9 +5153,8 @@ begin UpdateScreenCaret; if HideSelection and SelAvail then Invalidate; - {$IFDEF WinIME} - FImeHandler.FocusKilled; - {$ENDIF} + if FImeHandler <> nil then + FImeHandler.FocusKilled; inherited; StatusChanged([scFocus]); end; diff --git a/ide/sourcesyneditor.pas b/ide/sourcesyneditor.pas index f3f9b5d56e..0068f2cbc5 100644 --- a/ide/sourcesyneditor.pas +++ b/ide/sourcesyneditor.pas @@ -43,6 +43,7 @@ interface {$I ide.inc} uses + LazSynIMMBase, {$IFDEF WinIME} LazSynIMM, {$ENDIF}