mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 14:09:16 +02:00
LCL/SynEdit: w32 IME improvements
git-svn-id: trunk@35901 -
This commit is contained in:
parent
ad8b5a310d
commit
68b6823948
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -2388,6 +2388,7 @@ components/synedit/languages/synmacrorecorder.uk.po svneol=native#text/plain
|
||||
components/synedit/languages/synmacrorecorder.zh_CN.po svneol=native#text/utf8
|
||||
components/synedit/lazsyneditmousecmdstypes.pp svneol=native#text/pascal
|
||||
components/synedit/lazsynedittext.pas svneol=native#text/pascal
|
||||
components/synedit/lazsynimm.pas svneol=native#text/pascal
|
||||
components/synedit/lazsyntextarea.pp svneol=native#text/pascal
|
||||
components/synedit/synbeautifier.pas svneol=native#text/plain
|
||||
components/synedit/syncompletion.pas svneol=native#text/pascal
|
||||
|
@ -2,44 +2,40 @@
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
unit allsynedit;
|
||||
unit allsynedit;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SynBeautifier, SynCompletion, SynDesignStringConstants, SynEdit,
|
||||
SynEditAutoComplete, SynEditExport, SynEditFoldedView, SynEditHighlighter,
|
||||
SynEditHighlighterFoldBase, SynEditHighlighterXMLBase, SynEditKeyCmds,
|
||||
SynEditLazDsgn, SynEditLines, SynEditMarks, SynEditMarkup,
|
||||
SynEditMarkupBracket, SynEditMarkupCtrlMouseLink, SynEditMarkupHighAll,
|
||||
SynBeautifier, SynCompletion, SynDesignStringConstants, SynEdit, SynEditAutoComplete,
|
||||
SynEditExport, SynEditFoldedView, SynEditHighlighter, SynEditHighlighterFoldBase,
|
||||
SynEditHighlighterXMLBase, SynEditKeyCmds, SynEditLazDsgn, SynEditLines, SynEditMarks,
|
||||
SynEditMarkup, SynEditMarkupBracket, SynEditMarkupCtrlMouseLink, SynEditMarkupHighAll,
|
||||
SynEditMarkupSelection, SynEditMarkupSpecialLine, SynEditMarkupWordGroup,
|
||||
SynEditMiscClasses, SynEditMiscProcs, SynEditMouseCmds, SynEditPlugins,
|
||||
SynEditPointClasses, SynEditRegexSearch, SynEditSearch, SynEditStrConst,
|
||||
SynEditTextBase, SynEditTextBuffer, SynEditTextDoubleWidthChars,
|
||||
SynEditTextTabExpander, SynEditTextTrimmer, SynEditTypes, SynExportHTML,
|
||||
SynGutter, SynGutterBase, SynGutterChanges, SynGutterCodeFolding,
|
||||
SynGutterLineNumber, SynGutterLineOverview, SynGutterMarks,
|
||||
SynEditPointClasses, SynEditRegexSearch, SynEditSearch, SynEditStrConst, SynEditTextBase,
|
||||
SynEditTextBuffer, SynEditTextDoubleWidthChars, SynEditTextTabExpander, SynEditTextTrimmer,
|
||||
SynEditTypes, SynExportHTML, SynGutter, SynGutterBase, SynGutterChanges,
|
||||
SynGutterCodeFolding, SynGutterLineNumber, SynGutterLineOverview, SynGutterMarks,
|
||||
SynHighlighterAny, SynHighlighterCpp, SynHighlighterCss, SynHighlighterDiff,
|
||||
SynHighlighterHashEntries, SynHighlighterHTML, SynHighlighterJava,
|
||||
SynHighlighterJScript, SynHighlighterLFM, SynHighlighterMulti,
|
||||
SynHighlighterPas, SynHighlighterPerl, SynHighlighterPHP,
|
||||
SynHighlighterPosition, SynHighlighterPython, SynHighlighterSQL,
|
||||
SynHighlighterTeX, synhighlighterunixshellscript, SynHighlighterVB,
|
||||
SynHighlighterXML, SynMacroRecorder, SynMemo, SynPluginSyncroEdit,
|
||||
SynPluginSyncronizedEditBase, SynPluginTemplateEdit,
|
||||
SynPropertyEditObjectList, SynRegExpr, SynTextDrawer,
|
||||
SynEditMarkupGutterMark, SynHighlighterBat, SynHighlighterIni,
|
||||
SynEditMarkupSpecialChar, LazSynEditText, LazSynTextArea,
|
||||
LazSynEditMouseCmdsTypes, SynHighlighterPo, LazarusPackageIntf;
|
||||
SynHighlighterHashEntries, SynHighlighterHTML, SynHighlighterJava, SynHighlighterJScript,
|
||||
SynHighlighterLFM, SynHighlighterMulti, SynHighlighterPas, SynHighlighterPerl,
|
||||
SynHighlighterPHP, SynHighlighterPosition, SynHighlighterPython, SynHighlighterSQL,
|
||||
SynHighlighterTeX, synhighlighterunixshellscript, SynHighlighterVB, SynHighlighterXML,
|
||||
SynMacroRecorder, SynMemo, SynPluginSyncroEdit, SynPluginSyncronizedEditBase,
|
||||
SynPluginTemplateEdit, SynPropertyEditObjectList, SynRegExpr, SynTextDrawer,
|
||||
SynEditMarkupGutterMark, SynHighlighterBat, SynHighlighterIni, SynEditMarkupSpecialChar,
|
||||
LazSynEditText, LazSynTextArea, LazSynEditMouseCmdsTypes, SynHighlighterPo, LazSynIMM,
|
||||
LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
procedure Register;
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterUnit('SynEdit', @SynEdit.Register);
|
||||
RegisterUnit('SynEditLazDsgn', @SynEditLazDsgn.Register);
|
||||
end;
|
||||
RegisterUnit('SynEdit', @SynEdit.Register);
|
||||
RegisterUnit('SynEditLazDsgn', @SynEditLazDsgn.Register);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterPackage('SynEdit', @Register);
|
||||
RegisterPackage('SynEdit', @Register);
|
||||
end.
|
||||
|
725
components/synedit/lazsynimm.pas
Normal file
725
components/synedit/lazsynimm.pas
Normal file
@ -0,0 +1,725 @@
|
||||
unit LazSynIMM;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{off $DEFINE WinIMEDebug}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
windows, imm, Classes, SysUtils, LMessages, LazLoggerBase, LCLType, LCLProc, Controls,
|
||||
Graphics, SynEditMiscClasses, SynTextDrawer, SynEditPointClasses, SynEditMarkupSelection,
|
||||
SynEditMarkup, SynEditTypes, SynEditKeyCmds, SynEditTextBase, LazSynEditText;
|
||||
|
||||
type
|
||||
|
||||
{ LazSynIme }
|
||||
|
||||
LazSynIme = class(TSynEditFriend)
|
||||
private
|
||||
FInvalidateLinesMethod: TInvalidateLines;
|
||||
protected
|
||||
FInCompose: Boolean;
|
||||
procedure InvalidateLines(FirstLine, LastLine: integer);
|
||||
procedure StopIme(Success: Boolean);
|
||||
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;
|
||||
end;
|
||||
|
||||
{ LazSynImeSimple }
|
||||
|
||||
LazSynImeSimple = class(LazSynIme)
|
||||
private
|
||||
FImeBlockSelection: TSynEditSelection;
|
||||
FImeWinX, FImeWinY: Integer;
|
||||
FTextDrawer: TheTextDrawer;
|
||||
procedure SetTextDrawer(AValue: TheTextDrawer);
|
||||
procedure UpdateImeWinXY(aX, aY: Integer; aImc: HIMC = 0; aForce: Boolean = False);
|
||||
procedure UpdateImeWinFont(aImc: HIMC = 0);
|
||||
procedure DoStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
|
||||
procedure DoDrawerFontChanged(Sender: TObject);
|
||||
procedure DoOnCommand(Sender: TObject; AfterProcessing: boolean; var Handled: boolean;
|
||||
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
procedure DoOnMouse(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
|
||||
Y: Integer);
|
||||
public
|
||||
constructor Create(AOwner: TSynEditBase);
|
||||
destructor Destroy; override;
|
||||
procedure WMImeNotify(var Msg: TMessage); override;
|
||||
procedure WMImeComposition(var Msg: TMessage); override;
|
||||
procedure WMImeStartComposition(var Msg: TMessage); override;
|
||||
procedure WMImeEndComposition(var Msg: TMessage); override;
|
||||
procedure FocusKilled; override;
|
||||
property TextDrawer: TheTextDrawer read FTextDrawer write SetTextDrawer;
|
||||
end;
|
||||
|
||||
{ LazSynImeFull }
|
||||
|
||||
LazSynImeFull = class(LazSynIme)
|
||||
private
|
||||
FImeBlockSelection, FImeBlockSelection2: TSynEditSelection;
|
||||
FImeMarkupSelection, FImeMarkupSelection2: TSynEditMarkupSelection;
|
||||
FInImeMsg: Boolean;
|
||||
FRedoList: TSynEditUndoList;
|
||||
FUndoList: TSynEditUndoList;
|
||||
procedure SetImeTempText(const s: string);
|
||||
procedure DoOnCommand(Sender: TObject; AfterProcessing: boolean; var Handled: boolean;
|
||||
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
procedure DoOnMouse(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
|
||||
Y: Integer);
|
||||
procedure DoStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
|
||||
public
|
||||
constructor Create(AOwner: TSynEditBase);
|
||||
destructor Destroy; override;
|
||||
procedure WMImeRequest(var Msg: TMessage); override;
|
||||
procedure WMImeNotify(var Msg: TMessage); override;
|
||||
procedure WMImeComposition(var Msg: TMessage); override;
|
||||
procedure WMImeStartComposition(var Msg: TMessage); override;
|
||||
procedure WMImeEndComposition(var Msg: TMessage); override;
|
||||
procedure FocusKilled; override;
|
||||
|
||||
property UndoList: TSynEditUndoList read FUndoList write FUndoList;
|
||||
property RedoList: TSynEditUndoList read FRedoList write FRedoList;
|
||||
end;
|
||||
|
||||
implementation
|
||||
uses SynEdit;
|
||||
|
||||
{ LazSynIme }
|
||||
|
||||
procedure LazSynIme.InvalidateLines(FirstLine, LastLine: integer);
|
||||
begin
|
||||
FInvalidateLinesMethod(FirstLine, LastLine);
|
||||
end;
|
||||
|
||||
procedure LazSynIme.StopIme(Success: Boolean);
|
||||
var
|
||||
imc: HIMC;
|
||||
begin
|
||||
if (not FInCompose) or (not FriendEdit.HandleAllocated) then exit;
|
||||
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
if (imc <> 0) then begin
|
||||
if Success then
|
||||
ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0)
|
||||
else
|
||||
ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
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;
|
||||
|
||||
{ LazSynImeSimple }
|
||||
|
||||
procedure LazSynImeSimple.DoStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
|
||||
begin
|
||||
UpdateImeWinXY(TCustomSynEdit(FriendEdit).CaretXPix, TCustomSynEdit(FriendEdit).CaretYPix);
|
||||
if Changes * [scCaretX, scCaretY] <> [] then
|
||||
StopIme(False);
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.DoDrawerFontChanged(Sender: TObject);
|
||||
var
|
||||
imc: HIMC;
|
||||
begin
|
||||
if not FriendEdit.HandleAllocated then
|
||||
exit;
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
if (imc <> 0) then begin
|
||||
UpdateImeWinFont(imc);
|
||||
UpdateImeWinXY(TCustomSynEdit(FriendEdit).CaretXPix, TCustomSynEdit(FriendEdit).CaretYPix, imc);
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.DoOnCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.DoOnMouse(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
|
||||
X, Y: Integer);
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.UpdateImeWinXY(aX, aY: Integer; aImc: HIMC; aForce: Boolean);
|
||||
var
|
||||
cf: CompositionForm;
|
||||
imc: HIMC;
|
||||
begin
|
||||
if not FriendEdit.HandleAllocated then exit;
|
||||
if (not aForce) and (aX = FImeWinX) and (aY = FImeWinY) then exit;
|
||||
FImeWinX := aX;
|
||||
FImeWinY := aY;
|
||||
|
||||
cf.dwStyle := CFS_POINT;
|
||||
cf.ptCurrentPos := Point(aX, aY);
|
||||
if aImc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle)
|
||||
else
|
||||
imc := aImc;
|
||||
if (imc <> 0) then begin
|
||||
ImmSetCompositionWindow(imc, @cf);
|
||||
if (aImc = 0) then
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.SEtTextDrawer(AValue: TheTextDrawer);
|
||||
begin
|
||||
if FTextDrawer = AValue then Exit;
|
||||
if FTextDrawer <> nil then
|
||||
FTextDrawer.UnRegisterOnFontChangeHandler(@DoDrawerFontChanged);
|
||||
FTextDrawer := AValue;
|
||||
if FTextDrawer <> nil then
|
||||
FTextDrawer.RegisterOnFontChangeHandler(@DoDrawerFontChanged);
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.UpdateImeWinFont(aImc: HIMC);
|
||||
var
|
||||
imc: HIMC;
|
||||
logFont: TLogFont;
|
||||
begin
|
||||
if not FriendEdit.HandleAllocated then exit;
|
||||
if aImc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle)
|
||||
else
|
||||
imc := aImc;
|
||||
if (imc <> 0) then begin
|
||||
GetObject(FriendEdit.Font.Handle, SizeOf(TLogFont), @logFont);
|
||||
ImmSetCompositionFontA(imc, @logFont);
|
||||
if (aImc = 0) then
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor LazSynImeSimple.Create(AOwner: TSynEditBase);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FImeBlockSelection := TSynEditSelection.Create(ViewedTextBuffer, False);
|
||||
FImeBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
|
||||
|
||||
TCustomSynEdit(FriendEdit).RegisterStatusChangedHandler(@DoStatusChanged, [scCaretX, scCaretY, scLeftChar, scTopLine, scModified]);
|
||||
TCustomSynEdit(FriendEdit).RegisterCommandHandler(@DoOnCommand, nil, [hcfInit]);
|
||||
TCustomSynEdit(FriendEdit).RegisterBeforeMouseDownHandler(@DoOnMouse);
|
||||
end;
|
||||
|
||||
destructor LazSynImeSimple.Destroy;
|
||||
begin
|
||||
TextDrawer := nil;
|
||||
FreeAndNil(FImeBlockSelection);
|
||||
TCustomSynEdit(FriendEdit).UnregisterBeforeMouseDownHandler(@DoOnMouse);
|
||||
TCustomSynEdit(FriendEdit).UnregisterCommandHandler(@DoOnCommand);
|
||||
TCustomSynEdit(FriendEdit).UnRegisterStatusChangedHandler(@DoStatusChanged);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.WMImeNotify(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
{$IFDEF WinIMEDebug}
|
||||
s: String;
|
||||
{$ENDIF}
|
||||
begin
|
||||
{$IFDEF WinIMEDebug}
|
||||
case msg.wParam of
|
||||
IMN_CLOSESTATUSWINDOW: s:= 'IMN_CLOSESTATUSWINDOW, ';
|
||||
IMN_OPENSTATUSWINDOW: s:= 'IMN_OPENSTATUSWINDOW, ';
|
||||
IMN_CHANGECANDIDATE: s:= 'IMN_CHANGECANDIDATE, ';
|
||||
IMN_CLOSECANDIDATE: s:= 'IMN_CLOSECANDIDATE, ';
|
||||
IMN_OPENCANDIDATE: s:= 'IMN_OPENCANDIDATE, ';
|
||||
IMN_SETCONVERSIONMODE: s:= 'IMN_SETCONVERSIONMODE, ';
|
||||
IMN_SETSENTENCEMODE: s:= 'IMN_SETSENTENCEMODE, ';
|
||||
IMN_SETOPENSTATUS: s:= 'IMN_SETOPENSTATUS, ';
|
||||
IMN_SETCANDIDATEPOS: s:= 'IMN_SETCANDIDATEPOS, ';
|
||||
IMN_SETCOMPOSITIONFONT: s:= 'IMN_SETCOMPOSITIONFONT, ';
|
||||
IMN_SETCOMPOSITIONWINDOW: s:= 'IMN_SETCOMPOSITIONWINDOW, ';
|
||||
IMN_SETSTATUSWINDOWPOS: s:= 'IMN_SETSTATUSWINDOWPOS, ';
|
||||
IMN_GUIDELINE: s:= 'IMN_GUIDELINE, ';
|
||||
IMN_PRIVATE: s:= 'IMN_PRIVATE, ';
|
||||
end;
|
||||
debugln(['TCustomSynEdit.WMImeNotify ',s,' ', dbgHex(Msg.lParam), ' , ', dbgHex(Msg.wParam)]);
|
||||
{$ENDIF}
|
||||
|
||||
case Msg.WParam of
|
||||
IMN_SETOPENSTATUS: begin
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
if (imc <> 0) then begin
|
||||
UpdateImeWinFont(imc);
|
||||
UpdateImeWinXY(TCustomSynEdit(FriendEdit).CaretXPix, TCustomSynEdit(FriendEdit).CaretYPix, imc, True);
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
end;
|
||||
IMN_CLOSESTATUSWINDOW:
|
||||
StopIme(True);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.WMImeComposition(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
ImeCount: LongWord;
|
||||
p: PChar;
|
||||
begin
|
||||
if ((Msg.LParam and GCS_RESULTSTR) <> 0) then begin
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
try
|
||||
if imc <> 0 then begin
|
||||
ImeCount := ImmGetCompositionStringW(imc, GCS_RESULTSTR, nil, 0);
|
||||
{$IFDEF WinIMEDebug}
|
||||
DebugLn(['--- GCS_RESULTSTR ', dbgHex(ImeCount)]);
|
||||
{$ENDIF}
|
||||
if ImeCount > 0 then begin
|
||||
GetMem(p, ImeCount + 2);
|
||||
try
|
||||
TCustomSynEdit(FriendEdit).BeginUpdate;
|
||||
ImmGetCompositionStringW(imc, GCS_RESULTSTR, p, ImeCount + 2);
|
||||
p[ImeCount] := #0;
|
||||
p[ImeCount+1] := #0;
|
||||
FImeBlockSelection.SelText := UTF16ToUTF8(PWCHAR(p));
|
||||
FImeBlockSelection.StartLineBytePos := FImeBlockSelection.EndLineBytePos;
|
||||
CaretObj.LineBytePos := FImeBlockSelection.StartLineBytePos;
|
||||
Msg.Result := 1;
|
||||
finally
|
||||
FreeMem(p, ImeCount + 2);
|
||||
TCustomSynEdit(FriendEdit).EndUpdate;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.WMImeStartComposition(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
begin
|
||||
//debugln(['TCustomSynEdit.WMImeStartComposition ']);
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
if (imc <> 0) then begin
|
||||
UpdateImeWinFont(imc);
|
||||
UpdateImeWinXY(TCustomSynEdit(FriendEdit).CaretXPix, TCustomSynEdit(FriendEdit).CaretYPix, imc, True);
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
end;
|
||||
FInCompose := True;
|
||||
FImeBlockSelection.StartLineBytePos := CaretObj.LineBytePos;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.WMImeEndComposition(var Msg: TMessage);
|
||||
begin
|
||||
FInCompose := False;
|
||||
end;
|
||||
|
||||
procedure LazSynImeSimple.FocusKilled;
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
{ LazSynImeFull }
|
||||
|
||||
procedure LazSynImeFull.DoOnCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.DoOnMouse(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
|
||||
X, Y: Integer);
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.DoStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
|
||||
begin
|
||||
if FInImeMsg then exit;
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.SetImeTempText(const s: string);
|
||||
var
|
||||
p1, p2: TPoint;
|
||||
f: Boolean;
|
||||
begin
|
||||
p1 := FImeBlockSelection.FirstLineBytePos;
|
||||
|
||||
f := FInImeMsg;
|
||||
FInImeMsg := True;
|
||||
fUndoList.Lock;
|
||||
fRedoList.Lock;
|
||||
FImeBlockSelection.SelText := s;
|
||||
fUndoList.Unlock;
|
||||
fRedoList.Unlock;
|
||||
FInImeMsg := f;
|
||||
|
||||
p2 := FImeBlockSelection.FirstLineBytePos;
|
||||
FImeBlockSelection.StartLineBytePos := p1;
|
||||
FImeBlockSelection.EndLineBytePos := p2;
|
||||
end;
|
||||
|
||||
constructor LazSynImeFull.Create(AOwner: TSynEditBase);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
|
||||
FImeBlockSelection := TSynEditSelection.Create(ViewedTextBuffer, False);
|
||||
FImeBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
|
||||
FImeBlockSelection2 := TSynEditSelection.Create(ViewedTextBuffer, False);
|
||||
FImeBlockSelection2.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
|
||||
|
||||
FImeMarkupSelection := TSynEditMarkupSelection.Create(FriendEdit, FImeBlockSelection);
|
||||
FImeMarkupSelection2 := TSynEditMarkupSelection.Create(FriendEdit, FImeBlockSelection2);
|
||||
|
||||
TSynEditMarkupManager(MarkupMgr).AddMarkUp(FImeMarkupSelection);
|
||||
TSynEditMarkupManager(MarkupMgr).AddMarkUp(FImeMarkupSelection2);
|
||||
|
||||
FImeMarkupSelection.MarkupInfo.Clear;
|
||||
FImeMarkupSelection.MarkupInfo.FramePriority := 999;
|
||||
FImeMarkupSelection.MarkupInfo.FrameColor := clDefault;
|
||||
FImeMarkupSelection.MarkupInfo.FrameStyle := slsDotted;
|
||||
FImeMarkupSelection.MarkupInfo.FrameEdges := sfeAround;
|
||||
|
||||
FImeMarkupSelection2.MarkupInfo.Clear;
|
||||
FImeMarkupSelection2.MarkupInfo.FramePriority := 999+1;
|
||||
FImeMarkupSelection2.MarkupInfo.FrameColor := clDefault;
|
||||
FImeMarkupSelection2.MarkupInfo.FrameStyle := slsSolid;
|
||||
FImeMarkupSelection2.MarkupInfo.FrameEdges := sfeBottom;
|
||||
|
||||
TCustomSynEdit(FriendEdit).RegisterStatusChangedHandler(@DoStatusChanged, [scCaretX, scCaretY, scModified]);
|
||||
TCustomSynEdit(FriendEdit).RegisterCommandHandler(@DoOnCommand, nil, [hcfInit]);
|
||||
TCustomSynEdit(FriendEdit).RegisterBeforeMouseDownHandler(@DoOnMouse);
|
||||
|
||||
end;
|
||||
|
||||
destructor LazSynImeFull.Destroy;
|
||||
begin
|
||||
TCustomSynEdit(FriendEdit).UnregisterBeforeMouseDownHandler(@DoOnMouse);
|
||||
TCustomSynEdit(FriendEdit).UnregisterCommandHandler(@DoOnCommand);
|
||||
TCustomSynEdit(FriendEdit).UnRegisterStatusChangedHandler(@DoStatusChanged);
|
||||
|
||||
FreeAndNil(FImeBlockSelection);
|
||||
FreeAndNil(FImeBlockSelection2);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.WMImeRequest(var Msg: TMessage);
|
||||
var
|
||||
{$IFDEF WinIMEDebug}
|
||||
s: String;
|
||||
{$ENDIF}
|
||||
cp: PIMECHARPOSITION;
|
||||
p1: TPoint;
|
||||
CWidth: TPhysicalCharWidths;
|
||||
i, x: integer;
|
||||
begin
|
||||
{$IFDEF WinIMEDebug}
|
||||
case msg.wParam of
|
||||
IMR_COMPOSITIONWINDOW: s:= 'IMR_COMPOSITIONWINDOW, ';
|
||||
IMR_CANDIDATEWINDOW: s:= 'IMR_CANDIDATEWINDOW, ';
|
||||
IMR_COMPOSITIONFONT: s:= 'IMR_COMPOSITIONFONT, ';
|
||||
IMR_RECONVERTSTRING: s:= 'IMR_RECONVERTSTRING, ';
|
||||
IMR_CONFIRMRECONVERTSTRING: s:= 'IMR_CONFIRMRECONVERTSTRING, ';
|
||||
IMR_DOCUMENTFEED: s:= 'IMR_DOCUMENTFEED, ';
|
||||
end;
|
||||
if s <> '' then debugln(['TCustomSynEdit.WMImeRequest ', s,' ' , dbgHex(Msg.lParam)]);
|
||||
{$ENDIF}
|
||||
|
||||
case msg.wParam of
|
||||
IMR_QUERYCHARPOSITION: begin
|
||||
cp := PIMECHARPOSITION(Msg.lParam);
|
||||
p1 := FImeBlockSelection.StartLineBytePos;
|
||||
|
||||
CWidth := ViewedTextBuffer.GetPhysicalCharWidths(FImeBlockSelection.StartLinePos - 1);
|
||||
x := p1.x - 1;
|
||||
i := cp^.dwCharPos;
|
||||
while (i > 0) and (x < length(CWidth)) do begin
|
||||
inc(x);
|
||||
while (x < length(CWidth)) and (CWidth[x] = 0) do
|
||||
inc(x);
|
||||
dec(i);
|
||||
end;
|
||||
p1.x := x + i + 1;
|
||||
p1 := FriendEdit.ClientToScreen(TCustomSynEdit(FriendEdit).RowColumnToPixels(ViewedTextBuffer.LogicalToPhysicalPos(p1)));
|
||||
|
||||
cp^.pt.y := p1.y;
|
||||
cp^.pt.x := p1.x;
|
||||
cp^.cLineHeight := TCustomSynEdit(FriendEdit).LineHeight;
|
||||
cp^.rcDocument.TopLeft := FriendEdit.ClientToScreen(FriendEdit.ClientRect.TopLeft);
|
||||
cp^.rcDocument.BottomRight := FriendEdit.ClientToScreen(FriendEdit.ClientRect.BottomRight);
|
||||
{$IFDEF WinIMEDebug}
|
||||
debugln(['--- TCustomSynEdit.WMImeRequest ** IMR_QUERYCHARPOSITION ', dbgs(cp^.dwCharPos), ' ', dbgs(x),' ', dbgs(p1.x)]);
|
||||
{$ENDIF}
|
||||
Msg.Result := 1;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.WMImeNotify(var Msg: TMessage);
|
||||
{$IFDEF WinIMEDebug}
|
||||
var
|
||||
s: String;
|
||||
{$ENDIF}
|
||||
begin
|
||||
{$IFDEF WinIMEDebug}
|
||||
case msg.wParam of
|
||||
IMN_CLOSESTATUSWINDOW: s:= 'IMN_CLOSESTATUSWINDOW, ';
|
||||
IMN_OPENSTATUSWINDOW: s:= 'IMN_OPENSTATUSWINDOW, ';
|
||||
IMN_CHANGECANDIDATE: s:= 'IMN_CHANGECANDIDATE, ';
|
||||
IMN_CLOSECANDIDATE: s:= 'IMN_CLOSECANDIDATE, ';
|
||||
IMN_OPENCANDIDATE: s:= 'IMN_OPENCANDIDATE, ';
|
||||
IMN_SETCONVERSIONMODE: s:= 'IMN_SETCONVERSIONMODE, ';
|
||||
IMN_SETSENTENCEMODE: s:= 'IMN_SETSENTENCEMODE, ';
|
||||
IMN_SETOPENSTATUS: s:= 'IMN_SETOPENSTATUS, ';
|
||||
IMN_SETCANDIDATEPOS: s:= 'IMN_SETCANDIDATEPOS, ';
|
||||
IMN_SETCOMPOSITIONFONT: s:= 'IMN_SETCOMPOSITIONFONT, ';
|
||||
IMN_SETCOMPOSITIONWINDOW: s:= 'IMN_SETCOMPOSITIONWINDOW, ';
|
||||
IMN_SETSTATUSWINDOWPOS: s:= 'IMN_SETSTATUSWINDOWPOS, ';
|
||||
IMN_GUIDELINE: s:= 'IMN_GUIDELINE, ';
|
||||
IMN_PRIVATE: s:= 'IMN_PRIVATE, ';
|
||||
end;
|
||||
debugln(['TCustomSynEdit.WMImeNotify ',s,' ', dbgHex(Msg.lParam), ' , ', dbgHex(Msg.wParam)]);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.WMImeComposition(var Msg: TMessage);
|
||||
var
|
||||
CWidth: TPhysicalCharWidths;
|
||||
|
||||
function CharToByte(AStart, AChars: integer): integer;
|
||||
begin
|
||||
if length(CWidth) = 0 then
|
||||
CWidth := ViewedTextBuffer.GetPhysicalCharWidths(FImeBlockSelection.StartLinePos - 1);
|
||||
dec(AStart);
|
||||
Result := AStart;
|
||||
while (AChars > 0) and (Result < length(CWidth)) do begin
|
||||
inc(Result);
|
||||
while (Result < length(CWidth)) and (CWidth[Result] = 0) do
|
||||
inc(Result);
|
||||
dec(AChars);
|
||||
end;
|
||||
Result := Result - AStart + AChars;
|
||||
end;
|
||||
var
|
||||
{$IFDEF WinIMEDebug}
|
||||
s: String;
|
||||
{$ENDIF}
|
||||
imc: HIMC;
|
||||
p: PChar;
|
||||
ImeCount: LongWord;
|
||||
x, i: Integer;
|
||||
xy: TPoint;
|
||||
begin
|
||||
{$IFDEF WinIMEDebug}
|
||||
s := '';
|
||||
if (Msg.lparam and GCS_COMPREADSTR)<>0 then s := s + 'GCS_COMPREADSTR, ';
|
||||
if (Msg.lparam and GCS_COMPREADATTR)<>0 then s := s + 'GCS_COMPREADATTR, ';
|
||||
if (Msg.lparam and GCS_COMPREADCLAUSE)<>0 then s := s + 'GCS_COMPREADCLAUSE, ';
|
||||
//if (Msg.lparam and GCS_COMPSTR)<>0 then s := s + 'GCS_COMPSTR, ';
|
||||
if (Msg.lparam and GCS_COMPATTR)<>0 then s := s + 'GCS_COMPATTR, ';
|
||||
if (Msg.lparam and GCS_COMPCLAUSE)<>0 then s := s + 'GCS_COMPCLAUSE, ';
|
||||
//if (Msg.lparam and GCS_CURSORPOS)<>0 then s := s + 'GCS_CURSORPOS, ';
|
||||
//if (Msg.lparam and GCS_DELTASTART)<>0 then s := s + 'GCS_DELTASTART, ';
|
||||
if (Msg.lparam and GCS_RESULTREADSTR)<>0 then s := s + 'GCS_RESULTREADSTR, ';
|
||||
if (Msg.lparam and GCS_RESULTREADCLAUSE)<>0 then s := s + 'GCS_RESULTREADCLAUSE, ';
|
||||
//if (Msg.lparam and GCS_RESULTSTR)<>0 then s := s + 'GCS_RESULTSTR, ';
|
||||
if (Msg.lparam and GCS_RESULTCLAUSE)<>0 then s := s + 'GCS_RESULTCLAUSE, ';
|
||||
if (Msg.lparam and CS_INSERTCHAR)<>0 then s := s + ' ** CS_INSERTCHAR, ';
|
||||
if (Msg.lparam and CS_NOMOVECARET)<>0 then s := s + ' ** CS_NOMOVECARET, ';
|
||||
if s <> '' then debugln(['TCustomSynEdit.WMImeComposition ', s]);
|
||||
{$ENDIF}
|
||||
|
||||
if ((Msg.LParam and (GCS_RESULTSTR or GCS_COMPSTR or GCS_CURSORPOS or GCS_COMPATTR)) = 0) then
|
||||
exit;
|
||||
|
||||
imc := 0;
|
||||
FInImeMsg := True;
|
||||
SetLength(CWidth, 0);
|
||||
try
|
||||
|
||||
if ((Msg.LParam and GCS_RESULTSTR) <> 0) then begin
|
||||
if imc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
ImeCount := ImmGetCompositionStringW(imc, GCS_RESULTSTR, nil, 0);
|
||||
{$IFDEF WinIMEDebug}
|
||||
DebugLn(['--- GCS_RESULTSTR ', dbgHex(ImeCount)]);
|
||||
{$ENDIF}
|
||||
if ImeCount > 0 then begin
|
||||
GetMem(p, ImeCount + 2);
|
||||
try
|
||||
CaretObj.LineBytePos := FImeBlockSelection.StartLineBytePos;
|
||||
TCustomSynEdit(FriendEdit).BeginUpdate;
|
||||
ImmGetCompositionStringW(imc, GCS_RESULTSTR, p, ImeCount + 2);
|
||||
p[ImeCount] := #0;
|
||||
p[ImeCount+1] := #0;
|
||||
SetImeTempText('');
|
||||
FImeBlockSelection.SelText := UTF16ToUTF8(PWCHAR(p));
|
||||
FImeBlockSelection.StartLineBytePos := FImeBlockSelection.EndLineBytePos;
|
||||
CaretObj.LineBytePos := FImeBlockSelection.StartLineBytePos;
|
||||
Msg.Result := 1;
|
||||
finally
|
||||
TCustomSynEdit(FriendEdit).EndUpdate;
|
||||
FreeMem(p, ImeCount + 2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if ((Msg.LParam and GCS_COMPSTR) <> 0) then begin
|
||||
if imc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
ImeCount := ImmGetCompositionStringW(imc, GCS_COMPSTR, nil, 0);
|
||||
{$IFDEF WinIMEDebug}
|
||||
DebugLn(['--- GCS_COMPSTR ', dbgHex(ImeCount)]);
|
||||
{$ENDIF}
|
||||
if ImeCount > 0 then begin
|
||||
GetMem(p, ImeCount + 2);
|
||||
try
|
||||
ImmGetCompositionStringW(imc, GCS_COMPSTR, p, ImeCount + 2);
|
||||
p[ImeCount] := #0;
|
||||
p[ImeCount+1] := #0;
|
||||
SetImeTempText(UTF16ToUTF8(PWCHAR(p)));
|
||||
Msg.Result := 1;
|
||||
finally
|
||||
FreeMem(p, ImeCount + 2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if ((Msg.LParam and GCS_COMPATTR) <> 0) then begin
|
||||
if imc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
ImeCount := ImmGetCompositionStringW(imc, GCS_COMPATTR, nil, 0);
|
||||
{$IFDEF WinIMEDebug}
|
||||
DebugLn(['***** GCS_COMPATTR ', dbgHex(ImeCount)]);
|
||||
{$ENDIF}
|
||||
if ImeCount > 0 then begin
|
||||
xy := FImeBlockSelection.StartLineBytePos;
|
||||
FImeBlockSelection2.StartLineBytePos := xy;
|
||||
FImeBlockSelection2.EndLineBytePos := xy;
|
||||
GetMem(p, ImeCount + 2);
|
||||
try
|
||||
ImmGetCompositionStringW(imc, GCS_COMPATTR, p, ImeCount + 2);
|
||||
//DebugLn(dbgMemRange(PByte( p), ImeCount));
|
||||
i := 0;
|
||||
while i < ImeCount do begin
|
||||
if ord(p[i]) = ATTR_TARGET_CONVERTED then begin
|
||||
x := FImeBlockSelection.StartBytePos;
|
||||
xy.x := x + CharToByte(x, i);
|
||||
FImeBlockSelection2.StartLineBytePos := xy;
|
||||
inc(i);
|
||||
while i < ImeCount do begin
|
||||
if (ord(p[i]) <> ATTR_TARGET_CONVERTED) or (i = ImeCount-1) then begin
|
||||
if (ord(p[i]) = ATTR_TARGET_CONVERTED) then
|
||||
inc(i);
|
||||
xy.x := x + CharToByte(x, i);
|
||||
FImeBlockSelection2.EndLineBytePos := xy;
|
||||
break;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
break;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
Msg.Result := 1;
|
||||
finally
|
||||
FreeMem(p, ImeCount + 2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if ((Msg.LParam and GCS_CURSORPOS) <> 0) then begin
|
||||
if imc = 0 then
|
||||
imc := ImmGetContext(FriendEdit.Handle);
|
||||
|
||||
ImeCount := ImmGetCompositionStringW(imc, GCS_CURSORPOS, nil, 0);
|
||||
{$IFDEF WinIMEDebug}
|
||||
DebugLn(['--- GCS_CURSORPOS ', dbgs(ImeCount)]);
|
||||
{$ENDIF}
|
||||
if ImeCount >= 0 then begin
|
||||
ImeCount := ImeCount and $ffff;
|
||||
x := FImeBlockSelection.StartBytePos;
|
||||
x := x + CharToByte(x, ImeCount);
|
||||
CaretObj.CharPos := ViewedTextBuffer.LogicalToPhysicalPos(Point(x, FImeBlockSelection.StartLinePos)).x;
|
||||
end;
|
||||
end;
|
||||
|
||||
finally
|
||||
if imc <> 0 then
|
||||
ImmReleaseContext(FriendEdit.Handle, imc);
|
||||
FInImeMsg := False;
|
||||
end;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.WMImeStartComposition(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
begin
|
||||
//debugln(['TCustomSynEdit.WMImeStartComposition ']);
|
||||
FImeBlockSelection.StartLineBytePos := CaretObj.LineBytePos;
|
||||
FInCompose := True;
|
||||
Msg.Result := 1;
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.WMImeEndComposition(var Msg: TMessage);
|
||||
begin
|
||||
//debugln(['TCustomSynEdit.WMImeEndComposition ']);
|
||||
SetImeTempText('');
|
||||
CaretObj.LineBytePos := FImeBlockSelection.LastLineBytePos;
|
||||
FImeBlockSelection.StartLineBytePos := CaretObj.LineBytePos;
|
||||
FImeBlockSelection2.StartLineBytePos := CaretObj.LineBytePos;
|
||||
FInCompose := False;
|
||||
Msg.Result := 1;
|
||||
end;
|
||||
|
||||
procedure LazSynImeFull.FocusKilled;
|
||||
begin
|
||||
StopIme(True);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -38,7 +38,6 @@ Known Issues:
|
||||
-Font.CharSet
|
||||
-THintWindow
|
||||
-DragAcceptFiles
|
||||
-Font DBCS / MBCS double, multi byte character set
|
||||
|
||||
-------------------------------------------------------------------------------}
|
||||
|
||||
@ -46,6 +45,7 @@ unit SynEdit;
|
||||
{$IFDEF Windows}
|
||||
{$IFnDEF WithoutWinIME}
|
||||
{$DEFINE WinIME}
|
||||
{$DEFINE WinIMEFull}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
@ -73,16 +73,13 @@ interface
|
||||
|
||||
uses
|
||||
{$IFDEF WinIME}
|
||||
windows, imm,
|
||||
LazSynIMM,
|
||||
{$ENDIF}
|
||||
{$IFDEF USE_UTF8BIDI_LCL}
|
||||
FreeBIDI, utf8bidi,
|
||||
{$ENDIF}
|
||||
Types, LCLIntf, LCLType, LMessages, LazUTF8, LCLProc,
|
||||
SysUtils, Classes, Messages, Controls, Graphics, Forms, StdCtrls, ExtCtrls, Menus,
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
Imm,
|
||||
{$ENDIF}
|
||||
SynEditTypes, SynEditSearch, SynEditKeyCmds, SynEditMouseCmds, SynEditMiscProcs,
|
||||
SynEditPointClasses, SynBeautifier, SynEditMarks,
|
||||
// Markup
|
||||
@ -121,26 +118,6 @@ const
|
||||
// maximum scroll range
|
||||
MAX_SCROLL = 32767;
|
||||
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
{$IFNDEF SYN_COMPILER_4_UP}
|
||||
{Windows.pas in D4}
|
||||
const
|
||||
C3_NONSPACING = 1; { nonspacing character }
|
||||
C3_DIACRITIC = 2; { diacritic mark }
|
||||
C3_VOWELMARK = 4; { vowel mark }
|
||||
C3_SYMBOL = 8; { symbols }
|
||||
C3_KATAKANA = $0010; { katakana character }
|
||||
C3_HIRAGANA = $0020; { hiragana character }
|
||||
C3_HALFWIDTH = $0040; { half width character }
|
||||
C3_FULLWIDTH = $0080; { full width character }
|
||||
C3_IDEOGRAPH = $0100; { ideographic character }
|
||||
C3_KASHIDA = $0200; { Arabic kashida character }
|
||||
C3_LEXICAL = $0400; { lexical character }
|
||||
C3_ALPHA = $8000; { any linguistic char (C1_ALPHA) }
|
||||
C3_NOTAPPLICABLE = 0; { ctype 3 is not applicable }
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
TSynEditMarkupClass = SynEditMarkup.TSynEditMarkupClass;
|
||||
TSynReplaceAction = (raCancel, raSkip, raReplace, raReplaceAll);
|
||||
@ -395,6 +372,16 @@ type
|
||||
|
||||
{ TLazSynKeyDownEventList }
|
||||
|
||||
{ TLazSynMouseDownEventList }
|
||||
|
||||
TLazSynMouseDownEventList = Class(TMethodList)
|
||||
public
|
||||
procedure CallMouseDownHandlers(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
end;
|
||||
|
||||
{ TLazSynKeyDownEventList }
|
||||
|
||||
TLazSynKeyDownEventList = Class(TMethodList)
|
||||
public
|
||||
procedure CallKeyDownHandlers(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
@ -437,11 +424,12 @@ type
|
||||
procedure SelAvailChange(Sender: TObject);
|
||||
private
|
||||
{$IFDEF WinIME}
|
||||
FImeWinX, FImeWinY: Integer;
|
||||
procedure UpdateImeWinXY(aX, aY: Integer; aImc: HIMC = 0; aForce: Boolean = False);
|
||||
procedure UpdateImeWinFont(aImc: HIMC = 0);
|
||||
//procedure WMImeComposition(var Msg: TMessage); message WM_IME_COMPOSITION;
|
||||
FImeHandler: LazSynIme;
|
||||
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}
|
||||
procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES;
|
||||
procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
|
||||
@ -473,10 +461,6 @@ type
|
||||
fMarkupSpecialChar : TSynEditMarkupSpecialChar;
|
||||
fFontDummy: TFont;
|
||||
FLastSetFontSize: Integer;
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
fImeCount: Integer;
|
||||
fMBCSStepAside: Boolean;
|
||||
{$ENDIF}
|
||||
fInserting: Boolean;
|
||||
fLastMouseCaret: TPoint; // Char; physical (screen)
|
||||
FLastMousePoint: TPoint; // Pixel
|
||||
@ -543,6 +527,7 @@ type
|
||||
fTSearch: TSynEditSearch;
|
||||
fHookedCommandHandlers: TList;
|
||||
FHookedKeyTranslationList: TSynHookedKeyTranslationList;
|
||||
FMouseDownEventList: TLazSynMouseDownEventList;
|
||||
FKeyDownEventList: TLazSynKeyDownEventList;
|
||||
FKeyPressEventList: TLazSynKeyPressEventList;
|
||||
FUtf8KeyPressEventList: TLazSynUtf8KeyPressEventList;
|
||||
@ -813,10 +798,6 @@ type
|
||||
function GetTopView : Integer;
|
||||
procedure SetTopView(AValue : Integer);
|
||||
procedure MarkListChange(Sender: TSynEditMark; Changes: TSynEditMarkChangeReasons);
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
procedure MBCSGetSelRangeInLineWhenColumnSelectionMode(const s: string;
|
||||
var ColFrom, ColTo: Integer);
|
||||
{$ENDIF}
|
||||
procedure NotifyHookedCommandHandlers(var Command: TSynEditorCommand;
|
||||
var AChar: TUTF8Char; Data: pointer; ATime: THookedCommandFlag); virtual;
|
||||
function NextWordLogicalPos(ABoundary: TLazSynWordBoundary = swbWordBegin; WordEndForDelete : Boolean = false): TPoint;
|
||||
@ -1000,6 +981,9 @@ type
|
||||
procedure RegisterStatusChangedHandler(AStatusChangeProc: TStatusChangeEvent; AChanges: TSynStatusChanges);
|
||||
procedure UnRegisterStatusChangedHandler(AStatusChangeProc: TStatusChangeEvent);
|
||||
|
||||
procedure RegisterBeforeMouseDownHandler(AHandlerProc: TMouseEvent);
|
||||
procedure UnregisterBeforeMouseDownHandler(AHandlerProc: TMouseEvent);
|
||||
|
||||
procedure RegisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
|
||||
procedure UnregisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
|
||||
procedure RegisterBeforeKeyPressHandler(AHandlerProc: TKeyPressEvent);
|
||||
@ -1373,7 +1357,6 @@ type
|
||||
constructor Create(AEvent: THookedCommandEvent; AData: pointer; AFlags: THookedCommandFlags);
|
||||
end;
|
||||
|
||||
|
||||
{ TSynEditUndoCaret }
|
||||
|
||||
function TSynEditUndoCaret.IsEqualContent(AnItem: TSynEditUndoItem): Boolean;
|
||||
@ -1989,6 +1972,18 @@ begin
|
||||
fMarkupManager.Caret := FCaret;
|
||||
fMarkupManager.InvalidateLinesMethod := @InvalidateLines;
|
||||
|
||||
{$IFDEF WinIME}
|
||||
{$IFDEF WinIMEFull}
|
||||
FImeHandler := LazSynImeFull.Create(Self);
|
||||
LazSynImeFull(FImeHandler).UndoList := fUndoList;
|
||||
LazSynImeFull(FImeHandler).RedoList := fRedoList;
|
||||
{$ELSE}
|
||||
FImeHandler := LazSynImeSimple.Create(Self);
|
||||
LazSynImeSimple(FImeHandler).TextDrawer := FTextDrawer;
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
FImeHandler.InvalidateLinesMethod := @InvalidateLines;
|
||||
|
||||
fFontDummy.Name := SynDefaultFontName;
|
||||
fFontDummy.Height := SynDefaultFontHeight;
|
||||
fFontDummy.Pitch := SynDefaultFontPitch;
|
||||
@ -2045,10 +2040,6 @@ begin
|
||||
FMouseActionSearchHandlerList := TSynEditMouseActionSearchList.Create;
|
||||
FMouseActionExecHandlerList := TSynEditMouseActionExecList.Create;
|
||||
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
fImeCount := 0;
|
||||
fMBCSStepAside := False;
|
||||
{$ENDIF}
|
||||
fWantTabs := False;
|
||||
fTabWidth := 8;
|
||||
FOldTopView := 1;
|
||||
@ -2302,6 +2293,9 @@ begin
|
||||
FreeAndNil(FRightGutter);
|
||||
FreeAndNil(FPaintLineColor);
|
||||
FreeAndNil(FPaintLineColor2);
|
||||
{$IFDEF WinIME}
|
||||
FreeAndNil(FImeHandler);
|
||||
{$ENDIF}
|
||||
FreeAndNil(fTextDrawer);
|
||||
FreeAndNil(fFontDummy);
|
||||
DestroyMarkList; // before detach from FLines
|
||||
@ -2323,6 +2317,7 @@ begin
|
||||
FBeautifier := nil;
|
||||
FreeAndNil(FDefaultBeautifier);
|
||||
FreeAndNil(FKeyDownEventList);
|
||||
FreeAndNil(FMouseDownEventList);
|
||||
FreeAndNil(FKeyPressEventList);
|
||||
FreeAndNil(FUtf8KeyPressEventList);
|
||||
inherited Destroy;
|
||||
@ -2519,91 +2514,29 @@ begin
|
||||
end;
|
||||
|
||||
{$IFDEF WinIME}
|
||||
procedure TCustomSynEdit.UpdateImeWinXY(aX, aY: Integer; aImc: HIMC; aForce: Boolean);
|
||||
var
|
||||
cf: CompositionForm;
|
||||
imc: HIMC;
|
||||
procedure TCustomSynEdit.WMImeRequest(var Msg: TMessage);
|
||||
begin
|
||||
if not HandleAllocated then exit;
|
||||
if (not aForce) and (aX = FImeWinX) and (aY = FImeWinY) then exit;
|
||||
FImeWinX := aX;
|
||||
FImeWinY := aY;
|
||||
|
||||
cf.dwStyle := CFS_POINT;
|
||||
cf.ptCurrentPos := Point(aX, aY);
|
||||
if aImc = 0 then
|
||||
imc := ImmGetContext(Handle)
|
||||
else
|
||||
imc := aImc;
|
||||
if (imc <> 0) then begin
|
||||
ImmSetCompositionWindow(imc, @cf);
|
||||
if (aImc = 0) then
|
||||
ImmReleaseContext(Handle, imc);
|
||||
end;
|
||||
FImeHandler.WMImeRequest(Msg);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.UpdateImeWinFont(aImc: HIMC);
|
||||
var
|
||||
imc: HIMC;
|
||||
logFont: TLogFont;
|
||||
begin
|
||||
if not HandleAllocated then exit;
|
||||
if aImc = 0 then
|
||||
imc := ImmGetContext(Handle)
|
||||
else
|
||||
imc := aImc;
|
||||
if (imc <> 0) then begin
|
||||
GetObject(Font.Handle, SizeOf(TLogFont), @logFont);
|
||||
ImmSetCompositionFontW(imc, @logFont);
|
||||
if (aImc = 0) then
|
||||
ImmReleaseContext(Handle, imc);
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
procedure TCustomSynEdit.WMImeComposition(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
p: PChar;
|
||||
begin
|
||||
if ((Msg.LParam and GCS_RESULTSTR) <> 0) then begin
|
||||
imc := ImmGetContext(Handle);
|
||||
try
|
||||
fImeCount := ImmGetCompositionString(imc, GCS_RESULTSTR, nil, 0);
|
||||
GetMem(p, fImeCount + 1);
|
||||
try
|
||||
ImmGetCompositionString(imc, GCS_RESULTSTR, p, fImeCount + 1);
|
||||
p[fImeCount] := #0;
|
||||
CommandProcessor(ecImeStr, #0, p);
|
||||
finally
|
||||
FreeMem(p, fImeCount + 1);
|
||||
end;
|
||||
finally
|
||||
ImmReleaseContext(Handle, imc);
|
||||
end;
|
||||
end;
|
||||
inherited;
|
||||
end;
|
||||
*)
|
||||
|
||||
procedure TCustomSynEdit.WMImeNotify(var Msg: TMessage);
|
||||
var
|
||||
imc: HIMC;
|
||||
logFont: TLogFont;
|
||||
begin
|
||||
debugln(['TCustomSynEdit.WMImeNotify ', dbgHex(Msg.lParam), ' , ', dbgHex(Msg.wParam)]);
|
||||
FImeHandler.WMImeNotify(Msg);
|
||||
end;
|
||||
|
||||
case Msg.WParam of
|
||||
IMN_SETOPENSTATUS: begin
|
||||
imc := ImmGetContext(Handle);
|
||||
if (imc <> 0) then begin
|
||||
UpdateImeWinFont(imc);
|
||||
UpdateImeWinXY(CaretXPix, CaretYPix, imc, True);
|
||||
ImmReleaseContext(Handle, imc);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
inherited;
|
||||
procedure TCustomSynEdit.WMImeComposition(var Msg: TMessage);
|
||||
begin
|
||||
FImeHandler.WMImeComposition(Msg);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.WMImeStartComposition(var Msg: TMessage);
|
||||
begin
|
||||
FImeHandler.WMImeStartComposition(Msg);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.WMImeEndComposition(var Msg: TMessage);
|
||||
begin
|
||||
FImeHandler.WMImeEndComposition(Msg);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
@ -3199,6 +3132,10 @@ begin
|
||||
//DebugLn(['TCustomSynEdit.MouseDown START Mouse=',X,',',Y,' Caret=',CaretX,',',CaretY,', BlockBegin=',BlockBegin.X,',',BlockBegin.Y,' BlockEnd=',BlockEnd.X,',',BlockEnd.Y]);
|
||||
Exclude(FStateFlags, sfHideCursor);
|
||||
FInMouseClickEvent := True;
|
||||
|
||||
if FMouseDownEventList <> nil then
|
||||
FMouseDownEventList.CallMouseDownHandlers(Self, Button, Shift, X, Y);
|
||||
|
||||
if (X>=ClientWidth-ScrollBarWidth) or (Y>=ClientHeight-ScrollBarWidth) then
|
||||
begin
|
||||
inherited MouseDown(Button, Shift, X, Y);
|
||||
@ -4307,9 +4244,6 @@ begin
|
||||
x := CaretXPix;
|
||||
y := CaretYPix;
|
||||
FScreenCaret.DisplayPos := Point(x, y);
|
||||
{$IFDEF WinIME}
|
||||
UpdateImeWinXY(x, y);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -4484,6 +4418,9 @@ begin
|
||||
end;
|
||||
if FHideSelection and SelAvail then
|
||||
Invalidate;
|
||||
{$IFDEF WinIME}
|
||||
FImeHandler.FocusKilled;
|
||||
{$ENDIF}
|
||||
inherited;
|
||||
end;
|
||||
|
||||
@ -6000,11 +5937,6 @@ var
|
||||
WP: TPoint;
|
||||
Caret: TPoint;
|
||||
CaretNew: TPoint;
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
StartOfBlock: TPoint;
|
||||
i: integer;
|
||||
s: string;
|
||||
{$ENDIF}
|
||||
counter: Integer;
|
||||
LogCounter: integer;
|
||||
LogCaretXY: TPoint;
|
||||
@ -6511,47 +6443,6 @@ begin
|
||||
begin
|
||||
DefaultSelectionMode := SEL_MODE[Command];
|
||||
end;
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
ecImeStr:
|
||||
if not ReadOnly then begin
|
||||
SetString(s, PChar(Data), StrLen(Data));
|
||||
if SelAvail then begin
|
||||
SetSelTextExternal(s);
|
||||
end else begin
|
||||
Temp := LineText;
|
||||
Len := Length(Temp);
|
||||
if Len < CaretX then
|
||||
Temp := Temp + StringOfChar(' ', CaretX - Len);
|
||||
try
|
||||
FCaret.IncForcePastEOL;
|
||||
StartOfBlock := CaretXY;
|
||||
// Processing of case character covers on LeadByte.
|
||||
Len := Length(s);
|
||||
if not fInserting then begin
|
||||
i := (CaretX + Len);
|
||||
if (ByteType(Temp, i) = mbTrailByte) then begin
|
||||
s := s + Temp[i - 1];
|
||||
Helper := Copy(Temp, CaretX, Len - 1);
|
||||
end else
|
||||
Helper := Copy(Temp, CaretX, Len);
|
||||
Delete(Temp, CaretX, Len);
|
||||
end;
|
||||
Insert(s, Temp, CaretX);
|
||||
CaretX := (CaretX + Len);
|
||||
FTheLinesView[CaretY - 1] := Temp;
|
||||
if fInserting then
|
||||
Helper := '';
|
||||
fUndoList.AddChange(crInsert, StartOfBlock,
|
||||
LogicalCaretXY,
|
||||
Helper, smNormal);
|
||||
if CaretX >= LeftChar + CharsInWindow then
|
||||
LeftChar := LeftChar + min(25, CharsInWindow - 1);
|
||||
finally
|
||||
FCaret.DecForcePastEOL;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
EcFoldLevel1..EcFoldLevel9:
|
||||
FoldAll(Command - EcFoldLevel1);
|
||||
EcFoldLevel0:
|
||||
@ -7185,28 +7076,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
|
||||
procedure TCustomSynEdit.MBCSGetSelRangeInLineWhenColumnSelectionMode(
|
||||
const s: string; var ColFrom, ColTo: Integer);
|
||||
// --ColFrom and ColTo are in/out parameter. their range
|
||||
// will be from 1 to MaxInt.
|
||||
// --a range of selection means: Copy(s, ColFrom, ColTo - ColFrom);
|
||||
// be careful what ColTo means.
|
||||
var
|
||||
Len: Integer;
|
||||
begin
|
||||
Len := Length(s);
|
||||
if (0 < ColFrom) and (ColFrom <= Len) then
|
||||
if mbTrailByte = ByteType(s, ColFrom) then
|
||||
Inc(ColFrom);
|
||||
if (0 < ColTo) and (ColTo <= Len) then
|
||||
if mbTrailByte = ByteType(s, ColTo) then
|
||||
Inc(ColTo);
|
||||
end;
|
||||
|
||||
{$ENDIF}
|
||||
|
||||
function TCustomSynEdit.IsPointInSelection(Value: TPoint): boolean;
|
||||
var
|
||||
ptBegin, ptEnd: TPoint;
|
||||
@ -7590,10 +7459,6 @@ begin
|
||||
FScreenCaret.UnLock;
|
||||
end;
|
||||
UpdateScrollBars;
|
||||
|
||||
{$IFDEF WinIME}
|
||||
UpdateImeWinFont;
|
||||
{$ENDIF}
|
||||
//debugln('TCustomSynEdit.RecalcCharExtent UseUTF8=',dbgs(UseUTF8),' Font.CanUTF8=',dbgs(Font.CanUTF8));
|
||||
end;
|
||||
|
||||
@ -8627,6 +8492,19 @@ begin
|
||||
TSynStatusChangedHandlerList(FStatusChangedList).Remove(AStatusChangeProc);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.RegisterBeforeMouseDownHandler(AHandlerProc: TMouseEvent);
|
||||
begin
|
||||
if FMouseDownEventList = nil then
|
||||
FMouseDownEventList := TLazSynMouseDownEventList.Create;
|
||||
FMouseDownEventList.Add(TMethod(AHandlerProc));
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.UnregisterBeforeMouseDownHandler(AHandlerProc: TMouseEvent);
|
||||
begin
|
||||
if FMouseDownEventList <> nil then
|
||||
FMouseDownEventList.Remove(TMethod(AHandlerProc));
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.RegisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
|
||||
begin
|
||||
if FKeyDownEventList = nil then
|
||||
@ -8953,6 +8831,18 @@ begin
|
||||
TKeyPressEvent(Items[i])(Sender, Key);
|
||||
end;
|
||||
|
||||
{ TLazSynMouseDownEventList }
|
||||
|
||||
procedure TLazSynMouseDownEventList.CallMouseDownHandlers(Sender: TObject;
|
||||
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
i:=Count;
|
||||
while NextDownIndex(i) do
|
||||
TMouseEvent(Items[i])(Sender, Button, Shift, X, Y);
|
||||
end;
|
||||
|
||||
{ TLazSynKeyDownEventList }
|
||||
|
||||
procedure TLazSynKeyDownEventList.CallKeyDownHandlers(Sender: TObject; var Key: Word;
|
||||
|
@ -1095,6 +1095,10 @@ begin
|
||||
begin
|
||||
{IME Windows the composition has finished}
|
||||
WindowInfo^.IMEComposed:=True;
|
||||
LMessage.Msg := Msg;
|
||||
LMessage.WParam := WParam;
|
||||
LMessage.LParam := LParam;
|
||||
//WinProcess := False;
|
||||
end;
|
||||
WM_CANCELMODE:
|
||||
begin
|
||||
@ -2184,12 +2188,20 @@ begin
|
||||
Assigned(Win32WidgetSet.FOnAsyncSocketMsg) then
|
||||
Exit(Win32WidgetSet.FOnAsyncSocketMsg(WParam, LParam))
|
||||
end;
|
||||
WM_IME_NOTIFY:
|
||||
WM_IME_COMPOSITION,
|
||||
WM_IME_COMPOSITIONFULL,
|
||||
WM_IME_CONTROL,
|
||||
//WM_IME_ENDCOMPOSITION,
|
||||
WM_IME_NOTIFY,
|
||||
WM_IME_REQUEST,
|
||||
WM_IME_SELECT,
|
||||
WM_IME_SETCONTEXT,
|
||||
WM_IME_STARTCOMPOSITION:
|
||||
begin
|
||||
LMessage.Msg := Msg;
|
||||
LMessage.WParam := WParam;
|
||||
LMessage.LParam := LParam;
|
||||
//WinProcess := False;
|
||||
WinProcess := False;
|
||||
end;
|
||||
else
|
||||
// pass along user defined messages
|
||||
@ -2446,6 +2458,18 @@ begin
|
||||
WinProcess := LMKey.Result = 0;
|
||||
WParam := LMKey.CharCode;
|
||||
end;
|
||||
WM_IME_COMPOSITION,
|
||||
WM_IME_COMPOSITIONFULL,
|
||||
WM_IME_CONTROL,
|
||||
WM_IME_ENDCOMPOSITION,
|
||||
WM_IME_NOTIFY,
|
||||
WM_IME_REQUEST,
|
||||
WM_IME_SELECT,
|
||||
WM_IME_SETCONTEXT,
|
||||
WM_IME_STARTCOMPOSITION:
|
||||
begin
|
||||
WinProcess := LMessage.Result = 0;
|
||||
end;
|
||||
else
|
||||
case Msg of
|
||||
WM_LBUTTONDOWN, WM_LBUTTONUP:
|
||||
|
Loading…
Reference in New Issue
Block a user