Scintilla 1.77 한국어 IME 패치
Scintilla 1.77 버전이 나왔는데, 아직 패치를 실행하신 분은 없는 듯 해서 직접 패치 후 컴파일 했습니다. 패치 방법은 codewiz님, BlUE’nLIVE님이 작성하신 방법도 있는데, 너무 수정할 게 많아서 sixmen님께 힌트를 얻어 제 나름대로 수정했습니다. 덕분에 토요일 오후가 사라졌네요. ;;
다루어야 하는 파일은 ScintillaWin.cxx 파일 하나뿐입니다. 패치방법을 기억하기 쉽도록 아래에 적어둡니다. 그냥 바이너리 파일만 필요하신 분은 바로 아래에 있는 링크에서 받으시면 됩니다. 하지만, 현재 이 DLL에는 버그가 있습니다. 사용상에 중대한 영향을 끼치는 것은 아니라고 생각하지만, 경우에 따라서는 중요해질 수도 있습니다. 꼭 이 글 제일 아래에 있는 버그를 확인 후 사용하세요. 저한테는 중요한 버그가 아니라 일단 그냥 쓰기로 했습니다. -_-;;
패치 과정
아래의 모든 과정은 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가 정상적으로 작동하지 않는 버그가 있습니다.
좋은 정보 감사합니다.
(댓글이 안남았네요)
이런 고급 정보를 감사합니다. ㅎ