// CS_NOMOVECARET: keep caret at beginning of composition string which already moved in InsertCharacter().
// GCS_CURSORPOS: current caret position is provided by IME.
Sci::Position imeEndToImeCaretU16 = -static_cast<Sci::Position>(wcs.size());
if (!(lParam & CS_NOMOVECARET) && (lParam & GCS_CURSORPOS)) {
imeEndToImeCaretU16 += imc.GetImeCaretPos();
}
This code deprives korean Ime of the chance to get its ime caret position.
So korean ime move its ime caret blindly to the start of compStr.
This is a buggy behavior, not desirible.
It should honor ime caret position if possible rather than CS_NOMOVECARET.
In addition, All Other excution flows have to go through "if CS_NOMOVECARET check" to see MoveImeCarets().
There is no need to introduce CS_NOMOVECARET.
It is not efficent.
This is more reasonable patch. simple, intuitive and no need comments!
+ Sci::Position imeEndToImeCaretU16 = static_cast<Sci::Position>(-wcs.size() + imc.GetImeCaretPos());
Previous discussion [feature-requests:#1304].
Current code does not break Korean IME:
result for above log:
Related
Feature Requests:
#1304I think current code is not wrong:
https://learn.microsoft.com/en-us/windows/win32/intl/wm-ime-composition
https://learn.microsoft.com/en-us/windows/win32/intl/ime-composition-string-values
It is too bad you assume the original code as wrong.
what can I say about?
This is not about simplication, but about reverting.
Why does one line need to expand five lines?
Maybe the cause is what the comments give.
But the comments do not give any excuse and is deceptive to code readers.
The real behivor of the codes expanded I found is to filter korean ime out and to discriminate it.
Currntly korean ime is blind not to know its ime caret position while other imes do.
The codes expanded are very rude for korean.
Reverting seems has no impact for other IME.
probably need to test the revert on wine where Korean IME seems not work: GCS_CURSORPOS is always composition string length, and CS_NOMOVECARET is never set or accompanied with GCS_CURSORPOS.
The more if checks, the more difficult to debug, the less we are sure that we are right.
One liner can give sure that we are right.
Not find a way to test IME on Wine.
I think revert (no bug here, just to simplify the code) is safe as only Korean IME set CS_INSERTCHAR and CS_NOMOVECARET (do in-place composition), other IME composition string grows on typing more.
the one liner code was used before 2019 changes, and no bug caused by that line. it just leaves one question: it relies on
imc.GetImeCaretPos()returns zero when(lParam & GCS_CURSORPOS)is zero?One line code expects any value IMM32 can return.
If CS_NOMOVECARET is intruduced,
it should depends on that imc.GetImeCaretPos() return zero when (lParam & GCS_CURSORPOS) is zero.
How can I reproduce this bug?
Your question confirms current code should be reverted.
It compromises readability.
On korean ime, imc.GetImeCaretPos() should return the start position of the last character for imeblokcaretoverride regardless of CS_NOMOVECARET.
If CS_NOMOVECARET, then imc.GetImeCaretPos() returns 0 which is the start position of the last character.
Even If not CS_NOMOVECARET, it also returns the start position of the last character.
Current code exploits imc.GetImeCaretPos() absolutely is 0 when CS_NOMOVECARET set.
It is OK to never mind CS_NOMOVECARET.
That's all? There is no actual problem that can be seen by a user?
A user can not see any actual problem.
But an implementer should catch hidden problems.
Here are same effect for korean on imm32.
ime caret is located at:
I think 3 is right behavior.
Previous code 3 did show any actual problem to user neither.
but current code selects 1 with a discriminative cause.
This is not simplication, but reverting with a right cause.
IME knows at which ime caret should be located.
so for one caracter input, it must be the start of one compStr by CS_NOMOVECARET.
for clause input, it must be the start of the last character by no CS_NOMOVECARET.
But for korean ime, current code implement as this.
If (CS_NOMOVECARET) {
// do nothing
} else {
imeEndToImeCaretU16 += imc.GetImeCaretPos();
}
Is this implemeted according to MS document?
equals to :
Why does it adopt discrimination?
The comments does not give clear explanations.
Last edit: johnsonj 2023-07-05
It is implementing the behaviour specified by Microsoft documentation in WM_IME_COMPOSITION.
There is some ambiguity over how to handle a message with both
CS_NOMOVECARETand a non-zeroGCS_CURSORPOSbut the documentation forCS_NOMOVECARETis emphatic so that should receive priority.Code that implements a specification more fully and has no known problems should be preferred even when it covers cases that have not been observed. There are a wide variety of IMEs and some may produce these cases now or with future updates.
The reason why I want reverting is exactly for
It is desirable to implement ime codes as simple as possible.
We do not use GCS_COMPCLAUSE for ime attributes.
We do not CS_INSERTCHAR to insert characters.
from https://github.com/ONLYOFFICE/desktop-sdk/blob/master/ChromiumBasedEditors/lib/src/cef/windows/tests/cefclient/browser/osr_ime_handler_win.cc
.....
.....
I think this is the case "Otherwise"
we should honour the GCS_CURSORPOS value.
CS_NOMOVECARET breakes the rule already since the caret moved to the end of compStr.
So does it break the rule for korean ime to honor ime caret potision which is pointed IME?
Last edit: johnsonj 2023-07-06
The caret movement is caused by reusing the implementation of
InsertCharacterfor displaying the composition string since it handles some complexities like multiple carets and protected regions. The caret position is corrected before it is visible to the user.Yes, this is ignoring
CS_NOMOVECARETfor no visible improvement.GCS_CURSORPOS is primary.
but CS_NOMOVECARET is secondary.
it really breaks the rule to ignore GCS_CURSORPOS.
Rejecting as the change has no effect.