1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-06-12 22:07:39 +02:00

Partial fix for issue #413 Chinese IME bug in OSR

This commit is contained in:
salvadordf
2022-04-23 16:49:11 +02:00
parent b94d03b678
commit 63bd707553
4 changed files with 148 additions and 147 deletions

View File

@ -92,7 +92,7 @@ type
procedure GetCompositionInfo(imc : HIMC; aParam : LPARAM; var composition_text : ustring; var underlines : TCefCompositionUnderlineDynArray; var composition_start : integer);
function GetString(imc : HIMC; aParam : WParam; aType : integer; var aResult : ustring) : boolean;
{$IFDEF MSWINDOWS}
function IsSelectionAttribute(aAttribute : byte) : boolean;
function IsSelectionAttribute(aAttribute : AnsiChar) : boolean;
{$ENDIF}
procedure GetCompositionSelectionRange(imc : HIMC; var target_start, target_end : integer);
procedure GetCompositionUnderlines(imc : HIMC; target_start, target_end : integer; var underlines : TCefCompositionUnderlineDynArray);
@ -125,6 +125,12 @@ type
end;
// Original Chromium source code :
// https://source.chromium.org/chromium/chromium/src/+/main:ui/base/ime/win/imm32_manager.cc
// Original CEF source code :
// https://bitbucket.org/chromiumembedded/cef/src/master/tests/cefclient/browser/osr_ime_handler_win.cc
implementation
uses
@ -209,10 +215,7 @@ procedure TCEFOSRIMEHandler.GetCompositionInfo( imc : HIMC;
var underlines : TCefCompositionUnderlineDynArray;
var composition_start : integer);
var
TempStart : integer;
TempEnd : integer;
TempLen : integer;
i : integer;
TempTargetStart, TempTargetEnd, TempLen, i : integer;
begin
if (underlines <> nil) then
begin
@ -220,13 +223,13 @@ begin
underlines := nil;
end;
TempLen := length(composition_text);
TempStart := TempLen;
TempEnd := TempLen;
TempLen := length(composition_text);
TempTargetStart := TempLen;
TempTargetEnd := TempLen;
{$IFDEF MSWINDOWS}
if ((aParam and GCS_COMPATTR) <> 0) then
GetCompositionSelectionRange(imc, TempStart, TempEnd);
GetCompositionSelectionRange(imc, TempTargetStart, TempTargetEnd);
if ((aParam and CS_NOMOVECARET) = 0) and ((aParam and GCS_CURSORPOS) <> 0) then
composition_start := ImmGetCompositionString(imc, GCS_CURSORPOS, nil, 0)
@ -234,51 +237,51 @@ begin
composition_start := 0;
if ((aParam and GCS_COMPCLAUSE) <> 0) then
GetCompositionUnderlines(imc, TempStart, TempEnd, underlines);
GetCompositionUnderlines(imc, TempTargetStart, TempTargetEnd, underlines);
{$ENDIF}
if (underlines = nil) or (length(underlines) = 0) then
begin
i := 0;
if (TempStart > 0) then inc(i);
if (TempEnd > TempStart) then inc(i);
if (TempEnd < TempLen) then inc(i);
if (TempTargetStart > 0) then inc(i);
if (TempTargetEnd > TempTargetStart) then inc(i);
if (TempTargetEnd < TempLen) then inc(i);
if (i > 0) then
begin
SetLength(underlines, i);
i := 0;
if (TempStart > 0) then
if (TempTargetStart > 0) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := 0;
underlines[i].range.to_ := TempStart;
underlines[i].range.to_ := TempTargetStart;
underlines[i].thick := 0;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
inc(i);
end;
if (TempEnd > TempStart) then
if (TempTargetEnd > TempTargetStart) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := TempStart;
underlines[i].range.to_ := TempEnd;
underlines[i].range.from := TempTargetStart;
underlines[i].range.to_ := TempTargetEnd;
underlines[i].thick := 1;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
inc(i);
end;
if (TempEnd < TempLen) then
if (TempTargetEnd < TempLen) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := TempEnd;
underlines[i].range.from := TempTargetEnd;
underlines[i].range.to_ := TempLen;
underlines[i].thick := 0;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
@ -287,103 +290,89 @@ begin
end;
end;
function TCEFOSRIMEHandler.GetString(imc : HIMC; aParam : WParam; aType : integer; var aResult : ustring) : boolean;
function TCEFOSRIMEHandler.GetString( imc : HIMC;
aParam : WParam;
aType : integer;
var aResult : ustring) : boolean;
{$IFDEF MSWINDOWS}
var
TempBufferLen : integer;
TempBuffer : PWChar;
TempStringSize : integer;
TempBuffer : PWideChar;
{$ENDIF}
begin
Result := False;
{$IFDEF MSWINDOWS}
if ((aParam and aType) = 0) then exit;
{$IFDEF MSWINDOWS}
{$IFDEF FPC}
TempBufferLen := ImmGetCompositionStringW(imc, aType, nil, 0);
{$ELSE}
TempBufferLen := ImmGetCompositionString(imc, aType, nil, 0);
{$ENDIF}
TempStringSize := ImmGetCompositionStringW(imc, aType, nil, 0);
if (GetLastError <> 0) or (TempBufferLen <= 0) then exit;
{$ENDIF}
if (TempStringSize <= 0) then exit;
TempBuffer := nil;
TempBufferLen := TempBufferLen + SizeOf(wchar);
TempStringSize := TempStringSize + SizeOf(WideChar);
TempBuffer := nil;
try
try
GetMem(TempBuffer, TempBufferLen);
FillChar(TempBuffer^, TempBufferLen, 0);
{$IFDEF MSWINDOWS}
{$IFDEF FPC}
TempBufferLen := ImmGetCompositionStringW(imc, aType, TempBuffer, TempBufferLen);
{$ELSE}
TempBufferLen := ImmGetCompositionString(imc, aType, TempBuffer, TempBufferLen);
{$ENDIF}
{$ENDIF}
if (TempBufferLen > 0) then
begin
aResult := TempBuffer;
Result := True;
end;
GetMem(TempBuffer, TempStringSize);
FillChar(TempBuffer^, TempStringSize, 0);
ImmGetCompositionStringW(imc, aType, TempBuffer, TempStringSize);
aResult := TempBuffer;
Result := True;
except
on e : exception do
if CustomExceptionHandler('TCEFOSRIMEHandler.GetString', e) then raise;
end;
finally
if (TempBuffer <> nil) then FreeMem(TempBuffer);
if (TempBuffer <> nil) then
FreeMem(TempBuffer);
end;
{$ENDIF}
end;
{$IFDEF MSWINDOWS}
function TCEFOSRIMEHandler.IsSelectionAttribute(aAttribute : byte) : boolean;
function TCEFOSRIMEHandler.IsSelectionAttribute(aAttribute : AnsiChar) : boolean;
begin
Result := (aAttribute = ATTR_TARGET_CONVERTED) or
(aAttribute = ATTR_TARGET_NOTCONVERTED);
Result := (ord(aAttribute) = ATTR_TARGET_CONVERTED) or
(ord(aAttribute) = ATTR_TARGET_NOTCONVERTED);
end;
{$ENDIF}
procedure TCEFOSRIMEHandler.GetCompositionSelectionRange(imc : HIMC; var target_start, target_end : integer);
{$IFDEF MSWINDOWS}
var
i : integer;
TempBufferLen : integer;
TempBuffer : array of byte;
i, TempStart, TempEnd, TempBufferLen : integer;
TempBuffer : array of AnsiChar;
{$ENDIF}
begin
TempBuffer := nil;
{$IFDEF MSWINDOWS}
TempBuffer := nil;
try
try
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPATTR, nil, 0);
TempBufferLen := ImmGetCompositionStringW(imc, GCS_COMPATTR, nil, 0);
if (GetLastError = 0) and (TempBufferLen > 0) then
if (TempBufferLen > 0) then
begin
SetLength(TempBuffer, TempBufferLen);
for i := 0 to pred(TempBufferLen) do TempBuffer[i] := 0;
for i := 0 to pred(TempBufferLen) do TempBuffer[i] := #0;
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPATTR, @TempBuffer[0], TempBufferLen);
TempBufferLen := ImmGetCompositionStringW(imc, GCS_COMPATTR, @TempBuffer[0], TempBufferLen);
if (TempBufferLen > 0) then
begin
i := 0;
while (i < TempBufferLen) do
if IsSelectionAttribute(TempBuffer[i]) then
begin
target_start := i;
break;
end
else
inc(i);
TempStart := 0;
while (TempStart < TempBufferLen) do
if IsSelectionAttribute(TempBuffer[TempStart]) then
break
else
inc(TempStart);
while (i < TempBufferLen) do
if not(IsSelectionAttribute(TempBuffer[i])) then
begin
target_end := i;
break;
end
else
inc(i);
end;
TempEnd := TempStart;
while (TempEnd < TempBufferLen) do
if not(IsSelectionAttribute(TempBuffer[TempEnd])) then
break
else
inc(TempEnd);
target_start := TempStart;
target_end := TempEnd;
end;
except
on e : exception do
@ -403,57 +392,52 @@ procedure TCEFOSRIMEHandler.GetCompositionUnderlines( imc : HIMC;
target_start : integer;
target_end : integer;
var underlines : TCefCompositionUnderlineDynArray);
{$IFDEF MSWINDOWS}
var
i, j, TempSize : integer;
TempUndLen : integer;
TempBufferLen : integer;
TempLen : integer;
TempBuffer : array of cardinal;
{$ENDIF}
begin
TempBuffer := nil;
{$IFDEF MSWINDOWS}
TempBuffer := nil;
try
try
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPCLAUSE, nil, 0);
TempSize := ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, nil, 0);
TempLen := TempSize div SizeOf(cardinal);
if (GetLastError = 0) and (TempBufferLen > 0) then
if (TempLen > 0) then
begin
TempSize := TempBufferLen div SizeOf(cardinal);
SetLength(TempBuffer, TempSize);
for i := 0 to pred(TempSize) do TempBuffer[i] := 0;
SetLength(TempBuffer, TempLen);
for i := 0 to pred(TempLen) do TempBuffer[i] := 0;
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempBufferLen);
ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempSize);
if (TempBufferLen > 0) then
if (underlines <> nil) then
TempUndLen := length(underlines)
else
TempUndLen := 0;
SetLength(underlines, TempUndLen + pred(TempSize));
i := 0;
while (i < pred(TempLen)) do
begin
TempSize := TempBufferLen div SizeOf(cardinal);
j := i + TempUndLen;
if (underlines <> nil) then
TempUndLen := length(underlines)
underlines[j].range.from := TempBuffer[i];
underlines[j].range.to_ := TempBuffer[succ(i)];
underlines[j].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[j].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[j].style := DEFAULT_BLINK_UNDERLINE_STYLE;
if (underlines[j].range.from >= target_start) and
(underlines[j].range.to_ <= target_end) then
underlines[j].thick := 1
else
TempUndLen := 0;
underlines[j].thick := 0;
SetLength(underlines, TempUndLen + pred(TempSize));
i := 0;
while (i < pred(TempSize)) do
begin
j := i + TempUndLen;
underlines[j].range.from := TempBuffer[i];
underlines[j].range.to_ := TempBuffer[succ(i)];
underlines[j].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[j].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[j].style := DEFAULT_BLINK_UNDERLINE_STYLE;
if (underlines[j].range.from >= target_start) and
(underlines[j].range.to_ <= target_end) then
underlines[j].thick := 1
else
underlines[j].thick := 0;
inc(i);
end;
inc(i);
end;
end;
except
@ -679,10 +663,11 @@ end;
procedure TCEFOSRIMEHandler.MoveImeWindow;
{$IFDEF MSWINDOWS}
var
TempRect : TCefRect;
TempLocation : integer;
TempIMC : HIMC;
TempCandidate : TCandidateForm;
TempRect : TCefRect;
TempLocation : integer;
TempIMC : HIMC;
TempCandidatePos : TCandidateForm;
TempCandidateExc : TCandidateForm;
const
CARET_MARGIN = 1;
{$ENDIF}
@ -717,16 +702,16 @@ begin
try
if (PrimaryLangID = LANG_CHINESE) then
begin
TempCandidate.dwIndex := 0;
TempCandidate.dwStyle := CFS_CANDIDATEPOS;
TempCandidate.ptCurrentPos.X := TempRect.x;
TempCandidate.ptCurrentPos.Y := TempRect.y;
TempCandidate.rcArea.Left := 0;
TempCandidate.rcArea.Top := 0;
TempCandidate.rcArea.Right := 0;
TempCandidate.rcArea.Bottom := 0;
TempCandidatePos.dwIndex := 0;
TempCandidatePos.dwStyle := CFS_CANDIDATEPOS;
TempCandidatePos.ptCurrentPos.X := TempRect.x;
TempCandidatePos.ptCurrentPos.Y := TempRect.y;
TempCandidatePos.rcArea.Left := 0;
TempCandidatePos.rcArea.Top := 0;
TempCandidatePos.rcArea.Right := 0;
TempCandidatePos.rcArea.Bottom := 0;
ImmSetCandidateWindow(TempIMC, @TempCandidate);
ImmSetCandidateWindow(TempIMC, @TempCandidatePos);
end;
if FSystemCaret then
@ -735,20 +720,19 @@ begin
else SetCaretPos(TempRect.x, TempRect.y);
end;
if (PrimaryLangID = LANG_KOREAN) then
TempRect.y := TempRect.y + CARET_MARGIN;
TempCandidate.dwIndex := 0;
TempCandidate.dwStyle := CFS_EXCLUDE;
TempCandidate.ptCurrentPos.X := TempRect.x;
TempCandidate.ptCurrentPos.Y := TempRect.y;
TempCandidate.rcArea.Left := TempRect.x;
TempCandidate.rcArea.Top := TempRect.y;
TempCandidate.rcArea.Right := TempRect.x + TempRect.width;
TempCandidate.rcArea.Bottom := TempRect.y + TempRect.height;
TempCandidateExc.dwIndex := 0;
TempCandidateExc.dwStyle := CFS_EXCLUDE;
TempCandidateExc.ptCurrentPos.X := TempRect.x;
TempCandidateExc.ptCurrentPos.Y := TempRect.y;
TempCandidateExc.rcArea.Left := TempRect.x;
TempCandidateExc.rcArea.Top := TempRect.y;
TempCandidateExc.rcArea.Right := TempRect.x + TempRect.width;
TempCandidateExc.rcArea.Bottom := TempRect.y + TempRect.height;
ImmSetCandidateWindow(TempIMC, @TempCandidate);
ImmSetCandidateWindow(TempIMC, @TempCandidateExc);
finally
ImmReleaseContext(FHWND, TempIMC);
end;