by BLUEnLIVE | 2010/03/04 21:32
notepad2가 4.1.24로 업데이트 되었다. 이전 버전인 4.0.23으로 충분히 완벽해졌다고 생각했는데, Florian Balmer 님께선 아직 업뎃이 고픈가...
이전 포스트에서 얘기한 notepad2 4.1.24의 한글 IME 패치방법을 설명하기에 앞서, 몇 가지 작업을 해야한다.
0. 들어가기 전에
다음과 같은 내용은 모두 준비가 되어있다고 가정하고 설명함.
a. Visual C++ v6.0 및 Service Pack 6 설치
b. Platform SDK 설치 (Windows® Server 2003 R2 Platform SDK ISO Download)
c. Scintilla 2.03
a. Visual C++ v6.0 및 Service Pack 6 설치
b. Platform SDK 설치 (Windows® Server 2003 R2 Platform SDK ISO Download)
c. Scintilla 2.03
1. Visual C++ 6.0을 위한 dsp 파일 생성
notepad2의 소스에는 VC6을 위한 dsp 파일이 없다. VC7을 기준으로 만들어졌기 때문이다.
얼마전까지(정확히는 4.0.22-beta5 까지) notepad2의 기능추가 패치를 제작하시던 Kai Liu님이 notepad2 패치 작업을 중단했는데, Kai Liu 님의 패치 중에 VC6을 위한 dsp 파일 생성이 포함되어 있었다.
따라서, VC6에서 notepad2를 컴파일하려면 dsp 파일을 다시 만들어야 한다.
아래 파일을 다운받아 압축을 푼 뒤에 notepad2 소스의 루트 폴더에 저장한다.
얼마전까지(정확히는 4.0.22-beta5 까지) notepad2의 기능추가 패치를 제작하시던 Kai Liu님이 notepad2 패치 작업을 중단했는데, Kai Liu 님의 패치 중에 VC6을 위한 dsp 파일 생성이 포함되어 있었다.
따라서, VC6에서 notepad2를 컴파일하려면 dsp 파일을 다시 만들어야 한다.
아래 파일을 다운받아 압축을 푼 뒤에 notepad2 소스의 루트 폴더에 저장한다.
2. Edit.c 버그 수정
EditTitleCase() 함수에서 아래와 같은 부분을 찾는다.
이 부분을 아래와 같이 수정한다.
이건 그냥 notepad2의 버그다. 제작자 Balmer 님께 문의를 했는데, 패치할 의지가 없다는 답장을 받았다. 헐~
if (!IsCharAlphaNumericW(pszTextW[i]) && !StrChr(L"'?,pszTextW[i])) {
이 부분을 아래와 같이 수정한다.
if (!IsCharAlphaNumericW(pszTextW[i]) && !StrChr(L"'",pszTextW[i])) {
이건 그냥 notepad2의 버그다. 제작자 Balmer 님께 문의를 했는데, 패치할 의지가 없다는 답장을 받았다. 헐~
3. ScintillaWin.cxx 수정 #1
짜잔~ 이제야 한글 IME 패치를 할 차례가 되었다.
수정할 곳은 이전 패치과 같이 두 군데다. 그 중 첫번째는 WndProc().
WM_IME_STARTCOMPOSITION: 을 찾아 아래와 같이 수정한다.
이 부분은 이전 패치 그대로이다.
수정할 곳은 이전 패치과 같이 두 군데다. 그 중 첫번째는 WndProc().
WM_IME_STARTCOMPOSITION: 을 찾아 아래와 같이 수정한다.
이 부분은 이전 패치 그대로이다.
case WM_IME_STARTCOMPOSITION: // dbcs
ImeStartComposition();
// added from here-------------------------------------------------
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;
}
// added to here-------------------------------------------------
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
4. ScintillaWin.cxx 수정 #2
HandleComposition()을
찾아 아래 내용으로 대체한다.
이 부분은 이전 패치보다 좀 길어지고, 복잡해졌다.
이 부분은 이전 패치보다 좀 길어지고, 복잡해졌다.
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;
static bool bEndOfLine, bOverstrike;
static bool wasSelection = false;
bool bKoreanIME = LOWORD(GetKeyboardLayout(0))==MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
if (bKoreanIME && (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 lastitem = sel.Count()-1;
int selBegin = sel.Range(lastitem).End().Position();
int selEnd = selBegin;
if (bytes) {
//comp==false 이면 최초 진입
//undo를 마비시키기 전에 삭제할 글자/블럭 삭제
if (!comp)
{
FilterSelections();
{
UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
for (size_t r=0; r<sel.Count(); r++) {
if (!RangeContainsProtected(sel.Range(r).Start().Position(),
sel.Range(r).End().Position())) {
selBegin = sel.Range(r).Start().Position();
if (!sel.Range(r).Empty()) {
if (sel.Range(r).Length()) {
pdoc->DeleteChars(selBegin, sel.Range(r).Length());
sel.Range(r).ClearVirtualSpace();
} else {
// Range is all virtual so collapse to start of virtual space
sel.Range(r).MinimizeVirtualSpace();
}
} else if (inOverstrike) {
if (selBegin < pdoc->Length()) {
if (!IsEOLChar(pdoc->CharAt(selBegin))) {
pdoc->DelChar(selBegin);
sel.Range(r).ClearVirtualSpace();
}
}
}
selBegin = InsertSpace(selBegin, sel.Range(r).caret.VirtualSpace());
sel.Range(r).ClearVirtualSpace();
// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
if (wrapState != eWrapNone) {
AutoSurface surface(this);
if (surface) {
WrapOneLine(surface, pdoc->LineFromPosition(selBegin));
}
}
}
}
}
bOverstrike = inOverstrike;
}
if (cs < 0 && !bOverstrike) {
cs = vs.caretStyle;
vs.caretStyle = CARETSTYLE_BLOCK;
}
if (undo < 0) {
undo = pdoc->IsCollectingUndo()?1:0;
pdoc->SetUndoCollection(false);
}
if (!comp) {
comp = true;
} else {
DelChar();
}
} else {
//조합 중 조합중인 글자를 다 지운 경우
if (cs >= 0) {
vs.caretStyle = cs;
cs = -1;
}
if (comp) {
comp = false;
DelChar();
}
if (undo >= 0) {
pdoc->SetUndoCollection(undo==1);
undo = -1;
}
}
MovePositionTo(selBegin);
inOverstrike = false;
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<size; i++)
AddChar(dbcsval[i]);
}
inOverstrike = bOverstrike;
MovePositionTo(selBegin);
}
}
if (lParam & GCS_RESULTSTR) {
//앞의 if문 6개는 모두 한글 입력기에서만 동작
//다른 언어 IME에서는 패스
if (comp) {
comp = false;
DelChar();
}
if (cs >= 0) {
vs.caretStyle = cs;
cs = -1;
}
if (undo >= 0){
pdoc->SetUndoCollection(undo==1);
undo = -1;
}
//덮어쓰기에서 한글 조합 중 마지막에 숫자나 기호를 붙인 경우 한 글자 더 삭제(가9)
bool bKoreanPlusOneMore = false;
if (bKoreanIME && bOverstrike)
{
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;
char dbcsval[maxLenInputIME * 2];
int size = ::WideCharToMultiByte(InputCodePage(),
0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
bKoreanPlusOneMore = (size==3);
::ImmReleaseContext(MainHWND(), hIMC);
}
}
if (bKoreanPlusOneMore) DelChar();
if (bKoreanIME) inOverstrike = false;
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<size; i++)
AddChar(dbcsval[i]);
}
// Set new position after converted
Point pos = LocationFromPosition(sel.Range(0).End().Position());
COMPOSITIONFORM CompForm;
CompForm.dwStyle = CFS_POINT;
CompForm.ptCurrentPos.x = pos.x;
CompForm.ptCurrentPos.y = pos.y;
::ImmSetCompositionWindow(hIMC, &CompForm);
::ImmReleaseContext(MainHWND(), hIMC);
}
if (bKoreanIME) inOverstrike = bOverstrike;
return 0;
}
return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam);
#endif
}
이렇게 수정하면 아래와 같이 언제나 정상적으로 한글 입력이 가능한 notepad2를 만날 수 있다.
쿠헬헬~
그렇군요... [emo=023]
답글삭제오오... 역쉬라능~
답글삭제(근데 수정버전은 아직인가요?[emo=031])
ㅋ~ 그냥 평범하게 메모장 대신 쓰고 있는 저는 예전버젼으로 만족할래요^^
답글삭제좋은 프로그램을 위한 노력! 보기 좋습니다.
@okto - 2010/03/05 11:10
답글삭제요즘 먹고사니즘으로 좀 바쁘다능. 토욜도 출근 크리...
@애쉬 - 2010/03/05 14:46
답글삭제아잉... 새버전이 나오면 써주세용...
trackback from: 메모장2 (4.1.24)
답글삭제오랜만에 메모장2 4.1.24버전이 공개되었다.4.0.23버전에 비해 눈에 띄는 변경사항은 없다!워드랩 설정에서 줄바꿈 기호 위치 옵션을 좀더 늘린 정도?솔까말 지금 상태에서 더 고칠 필요는 없을 듯 한데 개발자 양반 분위기를 봐선 계속 뭔가를 뜯어고칠 기세다ㄷㄷㄷ공식 패치를 제공하던 Kai Liu가 그만두어 BLUEnLIVE님께서 혼자 도맡아 고생해 주셨다. 매번 ㄳ~BLUEnLIVE님의 패치 내역은 이 글과 이 글에 나와있다.내려받기 : 412...