Scintilla 1.77 버전이 나왔는데, 아직 패치를 실행하신 분은 없는 듯 해서 직접 패치 후 컴파일 했습니다. 패치 방법은 codewiz님, BlUE'nLIVE님이 작성하신 방법도 있는데, 너무 수정할 게 많아서 sixmen님께 힌트를 얻어 제 나름대로 수정했습니다. 덕분에 토요일 오후가 사라졌네요. ;;
다루어야 하는 파일은 ScintillaWin.cxx 파일 하나뿐입니다. 패치방법을 기억하기 쉽도록 아래에 적어둡니다. 그냥 바이너리 파일만 필요하신 분은 바로 아래에 있는 링크에서 받으시면 됩니다. 하지만, 현재 이 DLL에는 버그가 있습니다. 사용상에 중대한 영향을 끼치는 것은 아니라고 생각하지만, 경우에 따라서는 중요해질 수도 있습니다. 꼭 이 글 제일 아래에 있는 버그를 확인 후 사용하세요. 저한테는 중요한 버그가 아니라 일단 그냥 쓰기로 했습니다. -_-;;
[download id="2"]
[adsense]
패치 과정
아래의 모든 과정은 ScintillaWin.cxx 파일에서 이루어집니다.
1. case WM_IME_STARTCOMPOSITION: 를 찾습니다.
아래의 소스를 다음과 같이 수정합니다. 한글 키보드일 때만 작동하도록 되어있으며 이 부분은 sixmen님 소스를 그대로 사용했습니다.
case WM_IME_STARTCOMPOSITION:// dbcs
ImeStartComposition();
// 여기부터
if (LOWORD(GetKeyboardLayout(0))==MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)) {
// if the current IME is the Korean IME, do not show the default IME window
return 0;
}
// 여기까지가 추가된 부분입니다.
2. ScintillaWin::HandleComposition을 찾습니다.
이 메소드를 다음과 같이 수정합니다. 소스는 길지만 원리를 설명하자면... 조합을 시작하기 전에, Undo 수집여부, 캐럿 스타일을 저장하고 조합이 끝나면 이를 원래대로 돌려주는 것입니다. 몇 시간을 투자했는데, 설명하고 보니 아무 것도 없네요. OTL
sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) {
#ifdef __DMC__
// Digital Mars compiler does not include Imm library
return 0;
#else
// 여기부터
static int cs = -1;
static int undo = -1;
static bool comp = false;
if (LOWORD(GetKeyboardLayout(0))==MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN) && (lParam & GCS_COMPSTR)) {
HIMC hIMC = ::ImmGetContext(MainHWND());
if (hIMC) {
const int maxLenInputIME = 200;
wchar_t wcs[maxLenInputIME];
LONG bytes = ::ImmGetCompositionStringW(hIMC, GCS_COMPSTR, wcs, (maxLenInputIME-1)*2);
int wides = bytes / 2;
int selBegin = currentPos;
if (bytes == 0) {
if (cs >= 0) {
vs.caretStyle = cs;
cs = -1;
}
if (undo >= 0) {
pdoc->SetUndoCollection(!!undo);
undo = -1;
}
if (comp) {
comp = false;
DelChar();
}
} else {
if (cs < 0) {
cs = vs.caretStyle;
vs.caretStyle = CARETSTYLE_BLOCK;
}
if (undo < 0) {
undo = pdoc->IsCollectingUndo()?1:0;
pdoc->SetUndoCollection(false);
}
if (!comp) {
comp = true;
if(inOverstrike) {
pdoc->SetUndoCollection(undo);
DelChar();
pdoc->SetUndoCollection(false);
pdoc->InsertChar(selBegin = currentPos, ' ');
MovePositionTo(selBegin);
}
} else if(!inOverstrike) {
DelChar();
}
}
if (IsUnicodeMode()) {
char utfval[maxLenInputIME * 3];
unsigned int len = UTF8Length(wcs, wides);
UTF8FromUTF16(wcs, wides, utfval, len);
utfval[len] = '\0';
AddCharUTF(utfval, len);
} else {
char dbcsval[maxLenInputIME * 2];
int size = ::WideCharToMultiByte(InputCodePage(),
0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
for (int i=0; i= 0) {
vs.caretStyle = cs;
cs = -1;
}
if (undo >= 0) {
pdoc->SetUndoCollection(!!undo);
undo = -1;
}
// 여기까지
HIMC hIMC = ::ImmGetContext(MainHWND());
if (hIMC) {
const int maxLenInputIME = 200;
wchar_t wcs[maxLenInputIME];
LONG bytes = ::ImmGetCompositionStringW(hIMC,
GCS_RESULTSTR, wcs, (maxLenInputIME-1)*2);
int wides = bytes / 2;
if (IsUnicodeMode()) {
char utfval[maxLenInputIME * 3];
unsigned int len = UTF8Length(wcs, wides);
UTF8FromUTF16(wcs, wides, utfval, len);
utfval[len] = '\0';
AddCharUTF(utfval, len);
} else {
char dbcsval[maxLenInputIME * 2];
int size = ::WideCharToMultiByte(InputCodePage(),
0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
for (int i=0; i
버그
겹쳐쓰기 모드에서 한글을 입력하면 undo가 정상적으로 작동하지 않는 버그가 있습니다.
이런 고급 정보를 감사합니다. ㅎ
좋은 정보 감사합니다.
(댓글이 안남았네요)
이거보구
Scintilla 2.2.6 에 적용해봄
----
이것두역시
겹쳐쓰기 모드에서 한글을 입력하면 undo가 정상적으로 작동하지 않는 버그가 있습니다
-------
sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) {
#ifdef __DMC__
// Digital Mars compiler does not include Imm library
return 0;
#else
#define maxLenInputIME 10
static int caretStyle_IME_backup = 0;
static bool flag_IME_first = true;
static bool flag_IME_busy = false;
if (lParam & GCS_COMPSTR) { ////IME busy
HIMC hIMC = ::ImmGetContext(MainHWND());
if (hIMC) {
wchar_t wcs[maxLenInputIME];
LONG bytes = ::ImmGetCompositionStringW(hIMC, GCS_COMPSTR, wcs, (maxLenInputIME-1)*2);
::ImmReleaseContext(MainHWND(), hIMC);
wcs[bytes]=0;
int wides = bytes / 2;
if(flag_IME_first) {
flag_IME_first = false;
caretStyle_IME_backup = vs.caretStyle;
vs.caretStyle = CARETSTYLE_BLOCK;
pdoc->SetUndoCollection(false);
}
// pdoc->InsertChar(CurrentPosition(), ' ');
// pdoc->InsertCString(insertPos, sz);
// int startChar = pdoc->NextPosition(selBegin, -1);
// pdoc->DeleteChars(startChar, pos - startChar);
if (flag_IME_busy)
pdoc->DeleteChars(CurrentPosition(), 2);
flag_IME_busy = (wides != 0);
if (IsUnicodeMode()) {
char utfval[maxLenInputIME * 3];
unsigned int len = UTF8Length(wcs, wides);
UTF8FromUTF16(wcs, wides, utfval, len);
utfval[len] = '';
pdoc->InsertCString(CurrentPosition(), utfval);
} else {
char dbcsval[maxLenInputIME * 2];
int size = ::WideCharToMultiByte(InputCodePage(),
0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
dbcsval[size] = '';
pdoc->InsertCString(CurrentPosition(), dbcsval);
}
ShowCaretAtCurrentPosition();
if(!bytes) {
flag_IME_first = true;
flag_IME_busy = false;
vs.caretStyle = caretStyle_IME_backup;
pdoc->SetUndoCollection(true);
}
}
} else if (lParam & GCS_RESULTSTR) { //IME complete
HIMC hIMC = ::ImmGetContext(MainHWND());
if (hIMC) {
wchar_t wcs[maxLenInputIME];
LONG bytes = ::ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, wcs, (maxLenInputIME-1)*2);
::ImmReleaseContext(MainHWND(), hIMC);
int wides = bytes / 2;
if (!inOverstrike)
pdoc->DeleteChars(CurrentPosition(), 2);
if(!flag_IME_first) {
flag_IME_first = true;
flag_IME_busy = false;
pdoc->SetUndoCollection(true);
vs.caretStyle = caretStyle_IME_backup;
}
if (IsUnicodeMode()) {
char utfval[maxLenInputIME * 3];
unsigned int len = UTF8Length(wcs, wides);
UTF8FromUTF16(wcs, wides, utfval, len);
utfval[len] = '';
AddCharUTF(utfval, len);
} else {
char dbcsval[maxLenInputIME * 2];
int size = ::WideCharToMultiByte(InputCodePage(),
0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
for (int i=0; i<size; i++) {
AddChar(dbcsval[i]);
}
}
}
return 0;
}
return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam);
#undef maxLenInputIME
#endif
}