SynEdit: Handle new Gtk2 IM / Experimental / Issue #38730 / Based on Patch by Do-wan Kim / Moved to new unit

git-svn-id: trunk@65175 -
This commit is contained in:
martin 2021-06-05 22:33:53 +00:00
parent 0d724cb5bb
commit 176f0b3310
8 changed files with 236 additions and 97 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -32,7 +32,7 @@ uses
SynHighlighterIni, SynEditMarkupSpecialChar, SynEditTextDoubleWidthChars,
SynEditTextSystemCharWidth, SynEditMarkupIfDef, SynPluginMultiCaret,
synhighlighterpike, SynEditMarkupFoldColoring, SynEditViewedLineMap,
SynEditWrappedView, SynBeautifierPascal, LazarusPackageIntf;
SynEditWrappedView, SynBeautifierPascal, LazSynIMMBase, LazarusPackageIntf;
implementation

View File

@ -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.

View File

@ -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 }

View File

@ -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.

View File

@ -379,7 +379,7 @@ If you wish to allow use of your version of these files only under the terms of
</Item>
<Item>
<Filename Value="syneditviewedlinemap.pp"/>
<UnitName Value="syneditviewedlinemap"/>
<UnitName Value="SynEditViewedLineMap"/>
</Item>
<Item>
<Filename Value="syneditwrappedview.pp"/>
@ -389,6 +389,15 @@ If you wish to allow use of your version of these files only under the terms of
<Filename Value="synbeautifierpascal.pas"/>
<UnitName Value="SynBeautifierPascal"/>
</Item>
<Item>
<Filename Value="lazsyngtk2imm.pas"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="LazSynGtk2IMM"/>
</Item>
<Item>
<Filename Value="lazsynimmbase.pas"/>
<UnitName Value="LazSynIMMBase"/>
</Item>
</Files>
<LazDoc Paths="docs\xml"/>
<i18n>

View File

@ -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;

View File

@ -43,6 +43,7 @@ interface
{$I ide.inc}
uses
LazSynIMMBase,
{$IFDEF WinIME}
LazSynIMM,
{$ENDIF}