신틸라를 활용하지 못하는 notepad2-mod

77 views
Skip to first unread message

johnsonj

unread,
May 11, 2016, 9:43:18 AM5/11/16
to 파이썬문서고
notepad2-mod를 드디어 손을 대 보았다. vs2015로 하니까 컴파일 된다.
목표: 자동완성과 다중 선택...
일본어 입력할 때 자동완성되면 얼마나 좋을까...

테스트 결과:

인라인 ime ok
다중캐럿 ok
가상공백 ok
컬럼선택 ok
다중 선택 no - 시스템 충돌
자동 완성 no - ime 문자를 인식 못하는 거 같음.

이 중에 다중 선택을 했더니 프로그램이 충돌하는 거는 심각하다.
어디가 문제인지 못 찾겠다.
어쨌거나 다중 선택에서 에러가 나면..
다중 캐럿과 컬럼 선택은 사용할 수가 없는데...
그래서 막아 놓은거 같다.

그냥 뷰어로 써야지 아 신경쓰기 싫다.

notepad++에다 실험해 봐야겠다.


johnsonj

unread,
May 18, 2016, 11:22:58 PM5/18/16
to 파이썬문서고
드디어 깔끔하게 해결했다.

notepad2-mod.patch

blue...@gmail.com

unread,
May 19, 2016, 7:12:09 AM5/19/16
to 파이썬문서고
수고하셨습니다.
제가 해보고 싶은 건 다중선택인데, 이건 손을 못 대겠더군요.
undo/redo도 완전히 새로 구성해야 되고... ㅠㅠ

johnsonj

unread,
May 19, 2016, 7:17:15 PM5/19/16
to 파이썬문서고
다중 선택을 위해 다음 코드가 주석 처리되어 있습니다.

@@ -5105,16 +5142,18 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam)
 
             // Invalidate invalid selections
             // #pragma message("TODO: Remove check for invalid selections once fixed in Scintilla")
-            if (SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1 &&
+           /* if (SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1 &&
                 SendMessage(hwndEdit,SCI_GETSELECTIONMODE,0,0) != SC_SEL_RECTANGLE) {
               int iCurPos = (int)SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0);
               SendMessage(hwndEdit,WM_CANCELMODE,0,0);
               SendMessage(hwndEdit,SCI_CLEARSELECTIONS,0,0);
               SendMessage(hwndEdit,SCI_SETSELECTION,(WPARAM)iCurPos,(LPARAM)iCurPos);
-            }
+            }*/

undo/redo 건드리는 코드가 어디에 있나요?

blue...@gmail.com

unread,
May 19, 2016, 7:22:12 PM5/19/16
to 파이썬문서고
아... 그 뜻이 아니라, 제가 이거 해보고 싶었는데, undo/redo를 새로 구성해야 될 것 같아 손을 못 댔다는 뜻입니다... ☞☜

johnsonj

unread,
May 19, 2016, 7:38:50 PM5/19/16
to 파이썬문서고
이제 이해가 되었습니다.

용감한 패치라 아직 어떤 문제가 있을지 모릅니다.
코드 위치라든가 메뉴 등 깊게 생각해야 할 부분이 아직 많습니다.
일단 길을 냈으니 가 보는 거지요..

blue...@gmail.com

unread,
May 19, 2016, 7:41:03 PM5/19/16
to 파이썬문서고
저도 이리저리 계속 써보면서 오류가 발견되면 리포트하겠습니다.
혹시 블로그에 적어주셨던 "자동 완성" 기능도 공개 가능하실까요? ☞☜

johnsonj

unread,
May 19, 2016, 8:34:03 PM5/19/16
to 파이썬문서고
데모에 나온 자동 완성 말하는 건가요?

-  while (iStartWordPos > 0 && !StrChrIA(NON_WORD, pLine[iStartWordPos - 1])) {
+  while (iStartWordPos > 0 && !StrChrA(NON_WORD, pLine[iStartWordPos - 1])) {

 Ime문자를 인식시키기 위해 StrCharIA 를 StrCharA로 바꾸었습니다.

blue...@gmail.com

unread,
May 19, 2016, 8:57:24 PM5/19/16
to 파이썬문서고
아... 자동 완성을 위한 수정... 이군요.
이제 이해했습니다.
고맙습니다. ^^

johnsonj

unread,
May 20, 2016, 11:16:05 AM5/20/16
to 파이썬문서고
두 군데 개선
1. 자동 완성에서 제외되는 글자가 발생 -> (char) 을 (BYTE)로 바꿈.
 if (iPosFind != iCurrentPos - iRootLen) {
      while (wordEnd < iDocLen && !StrChrA(NON_WORD, (BYTE)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0)))

2. 다른 곳에서도 EditMarkAll()을 호출, 안전을 위해 아예 해당 함수에다 보초 설치
  // feature is off
  if ((!iMarkOccurrences) && (SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1))
    return;

개선해야 할것: case SCN_UPDATEUI: 아래에 있는 EditMarkAll() 함수를 seletion 메시지 아래로 이동해야 하는데...
                  case IDM_EDIT_SELECTWORD: 아래로 이동해서 작동시키지 못하고 있음.

Inline0521.patch

johnsonj

unread,
May 21, 2016, 8:22:13 AM5/21/16
to 파이썬문서고
마땅한 곳을 찾지 못해 선택이 바뀔 경우만 실행되도록 보초를 세움.

             // mark occurrences of text currently selected
-            EditMarkAll(hwndEdit, iMarkOccurrences, bMarkOccurrencesMatchCase, bMarkOccurrencesMatchWords);
+            if (scn->updated & SC_UPDATE_SELECTION)
+              EditMarkAll(hwndEdit, iMarkOccurrences, bMarkOccurrencesMatchCase, bMarkOccurrencesMatchWords);

inline0522.patch

blue...@gmail.com

unread,
May 21, 2016, 9:20:27 AM5/21/16
to 파이썬문서고
수고 많으십니다.
구현해주신 기능들을 좀 테스트해보고 있습니다.

1. 다중 선택시 paste하면 보통의 Scintilla 어플들은 선택행마다 각각 paste가 동작하는데(키보드 입력과 유사하게), 현재의 patch에서는 기존 Notepad2와 동일하게 동작합니다.
혹시 이 부분에 대해선 어떤 생각이 있으신가요?

2. IME Inline은 한국어로 번역하려니 뭐라고 할지 애매하네요.
혹시 적절한 번역을 추천해주실 수 있을까요?

3. Notepad2.c의 수정 중에

//cancel selection
int curPos = ...

부분은 변수 선언이 case 내에 위치하는데, 이건 {...}로 묶는 등의 처리가 있으면 좋겠습니다.
VS2015에선 컴파일이 잘 되지만, WDK에선 이 부분에서 오류가 발생합니다.

계속 테스트해보면서 리포트할 내용들 있으면 계속 올리겠습니다.

Scintilla

unread,
May 21, 2016, 9:46:59 AM5/21/16
to 파이썬문서고
(추가)

4. 아마 paste 기능을 사용하기 때문인 것 같은데...
다중 선택시에 자동완성 기능을 사용하면 선택영역 중 마지막 줄에만 선택한 내용이 출력됩니다.

johnsonj

unread,
May 21, 2016, 10:59:11 PM5/21/16
to 파이썬문서고

1. 추가: SendMessage(hwndEdit,SCI_SETMULTIPASTE,SC_MULTIPASTE_EACH,0);

2. IME 인라인

3. {...}로 묶음

4. 컬럼 블록 상태에서 paste 기능은 신틸라 내부에서 MULTIPASTE_ONCE로 출력 하는거 같네요.

참조 : http://scintillakr.sourceforge.net/ScintillaDoc.html

johnsonj

unread,
May 21, 2016, 11:01:16 PM5/21/16
to 파이썬문서고
패치 파일을 빼먹었네요.
inline0522-multiPaste.patch

Scintilla

unread,
May 22, 2016, 7:35:36 AM5/22/16
to 파이썬문서고
엄지 척!
계속 테스트해보겠습니ㅏㄷ.

그런데, case CMD_ESCAPE: 의 중괄호 위치는 수정이 필요합니다.

    case CMD_ESCAPE:
     
{
       
//close the autocomplete box
       
SendMessage(hwndEdit,SCI_AUTOCCANCEL,0, 0);

       
//cancel selection
       
int curPos = (int)SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0);
       
SendMessage(hwndEdit,SCI_SETEMPTYSELECTION,(WPARAM)curPos,(LPARAM)curPos);

       
if (iEscFunction == 1)
         
SendMessage(hwnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
       
else if (iEscFunction == 2)
         
SendMessage(hwnd,WM_CLOSE,0,0);
     
}
     
break;



    case CMD_ESCAPE:
       
//close the autocomplete box
       
SendMessage(hwndEdit,SCI_AUTOCCANCEL,0, 0);

       
//cancel selection
       
{
         
int curPos = (int)SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0);
         
SendMessage(hwndEdit,SCI_SETEMPTYSELECTION,(WPARAM)curPos,(LPARAM)curPos);
       
}

       
if (iEscFunction == 1)
         
SendMessage(hwnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
       
else if (iEscFunction == 2)
         
SendMessage(hwnd,WM_CLOSE,0,0);

     
break;


으로...

Scintilla

unread,
May 23, 2016, 7:15:54 PM5/23/16
to 파이썬문서고
현재까지 테스트 결과 문제는 발견되지 않고 있습니다.
혹시 정식으로 PR을 올려보시는 건 어떨까 합니다. ^^

johnsonj

unread,
May 23, 2016, 8:31:28 PM5/23/16
to 파이썬문서고
notepad2-mod는 너무 보수적입니다.
notepad3이 대신 나올 정도로 발전 속도가 느립니다.
게다가 지역화를 전혀 고려하지 않는 프로젝트라서... 별로 마음에 안 듭니다.

저는 한글화된 notepad2-mod만 씁니다.
메모장 대신 사용 프로그램으로 가볍고 빠르고 너무 좋습니다.
새로운 기능을 바로바로 반영해 주셔서 감사히 사용하고 있습니다.

저는 님께서 배포하시는 한글 노트패드2를 사용하는 것으로 만족하겠습니다.

Scintilla

unread,
May 24, 2016, 3:59:29 AM5/24/16
to 파이썬문서고
넵넵. 알겠습니다.
하루이틀 정도 더 테스트해보고 블로그에서 배포하도록 하겠습니다.

고맙습니다. ^^

johnsonj

unread,
May 25, 2016, 7:54:45 AM5/25/16
to 파이썬문서고
새로운 버그 발견...
처음으로 콘트롤 키를 눌러 추가로 선택을 할 때도 EditMarkAll이 실행되지 못하도록 방지.
(콘트롤 키를 클릭하는 순간에 EditMarkAll이 실행되면 가끔씩 충돌이 일어나는 경우가 있음)
따라서 다음과 같이 보초를 세움.

가만히 보면 EditMarkAll이 멀티 캐럿을 사용하지 못하는 문제의 근원 함수인 거 같음..
또 어디에서 문제가 나올지...

Edit.c 파일에서
void EditMarkAll(HWND hwnd, int iMarkOccurrences, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords)
{
...
 + if ((SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1) && (GetAsyncKeyState((VK_LBUTTON) < 0)))
 +   return;

  // feature is off
  if (!iMarkOccurrences)
    return;
...


johnsonj

unread,
May 25, 2016, 8:32:44 AM5/25/16
to 파이썬문서고
직접적인 방법보다 신틸라 스타일로..
점점 코드가 안드로메다로...

  if ((SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1) && (SendMessage(hwndEdit,SCI_GETSELECTIONMODE,0,0) == SC_SEL_STREAM))
    return;

johnsonj

unread,
May 26, 2016, 5:25:29 AM5/26/16
to 파이썬문서고
그래도 자동완성에서 빠지는 글자가 발생..
그래서 찾아본
StrChrIA, StrChrA의 정체
알고 보니 문자 기반이다.
참조: http://source.winehq.org/source/dlls/shlwapi/string.c#0205

신틸라에서는 바이트 기반으로 strchr을 써야 한다.
왜 대소문자를 생각하지 못했을까..
이름은 SCI_GETCHARAT 이지만 본질은 byte이다.

어쨋거나 strchr로 바꾸니 형변환 없이도 잘 작동하는 거 같다.
그런데 다른 곳에도 StrChrIA가 있는데 이걸 어찌해야 하나...아 복잡하다.


Scintilla

unread,
May 26, 2016, 7:58:55 AM5/26/16
to 파이썬문서고
혹시 자동완성에서 빠지는 경우를 알려주실 수 있을까요?
어떤 경우인지 좀 보고 싶습니다.


2016년 5월 26일 목요일 오후 6시 25분 29초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 26, 2016, 7:34:34 PM5/26/16
to 파이썬문서고
테스트 문구:

줄번호
1    아름다운 우리 한글
2    자동 완성 안정화

순서대로 치면 '안'이라는 글자에서 촉발되지 않습니다.
그러나 1번 줄이 없으면 촉발됩니다.

다행스러운 것은 두 번째 글자를 입력하면 확실하게 다 잘 촉발되는 것 같습니다.
영문자도 두 번째 문자부터 자동 완성 박스가 나오니까.. 오히려 이 쪽이 더 일관성이 있네요.

바이트에 손실이 있는 걸로 생각하고 있었는데..이게 아니라
신틸라 쪽과의 연동에 문제가 있는 거 아닐까 생각중...
이런 경우 무지하게 많이 봤었는데.. 오래 되서 기억이 안 나네요..

Scintilla

unread,
May 26, 2016, 7:45:36 PM5/26/16
to 파이썬문서고
아, 이제 무슨 말씀인지 알았습니다.
"아름다운"이 없을 때는 "안"-->"안정화"가 되는데
있을 때는 "안"에서 이벤트가 씹히는군요.

저도 해결책을 찾아보겠습니다.
아무래도 함수 하나 만들어야 되는 게 아닌가 하는 생각이 듭니다[...]


2016년 5월 27일 금요일 오전 8시 34분 34초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 26, 2016, 11:35:46 PM5/26/16
to 파이썬문서고
중성까지 이미 등록되어 있을 경우 이미 자동 완성 박스가 떠 있어서
종성을 칠 때 촉발되지 않은 것이었습니다.

Notepad2.c  파일에
          else if ((bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || scn->ch > 127))
            CompleteWord(hwndEdit, FALSE);

아스키가 아닐 경우 무조건 촉발되도록 바꿈.

johnsonj

unread,
May 27, 2016, 7:19:54 AM5/27/16
to 파이썬문서고
같은 아이디어..
그러나 scn->ch가 int 형이므로
scn->ch > '\xFF'로 교체함.
이제 제대로 작동하는 것인가...

          else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || scn->ch > '\xFF'))
            CompleteWord(hwndEdit, FALSE);


Scintilla

unread,
May 27, 2016, 8:36:39 AM5/27/16
to 파이썬문서고
그런 의도라면 직접 비교하는 것보다는 __isascii() 함수를 사용하는 것이 좀 더 그럴싸(?)합니다.

          else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || !__isascii(scn->ch)))
            CompleteWord(hwndEdit, FALSE);
          break;



2016년 5월 27일 금요일 오후 8시 19분 54초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 27, 2016, 9:26:46 AM5/27/16
to 파이썬문서고
그런 함수가 있는 줄은 몰랐습니다.
Iso-8859-1(라틴) 인코딩 때문에 ascii로 비교하기는 곤란할 거 같습니다.

scn->ch > '\xFF'의 뜻은 1바이트가 넘으면이란 뜻입니다.
1바이트짜리는 원래의 룰을 따르고 2바이트가 넘으면 다시 무조건 갱신...

다음과 같이 무조건 다시 갱신해도 아무 문제 없읍니다. 단지 효율성이 좀 떨어질 뿐....
else if (bAutoCompleteWords)
            CompleteWord(hwndEdit, FALSE);
이 코드로도 훌륭하게 잘 작동합니다.

무엇 때문에 그런지는 짐작되는 바가 있는데 아직 확신이 없어서 신틸라 코드를 고쳐보아야 알 것 같습니다.
진작에 좀 커밋좀 해달라도 몇달 전부터 졸랐는데.. 번번히 거절 당해서리..
앞으로도 3개월간 신틸라 사이트 업데이트 없습니다.

최대한 원래 코드를 유지하고..
최초의 패치에서
먼 길을 돌아온 결과 두 군데를 갱신했습니다.

2바이트 이상일 경우 무조건 다시 자동 완성 계산
-          else if (bAutoCompleteWords && !SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
+          else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || scn->ch > '\xFF'))

추가 선택을 할 때 콘트롤 키를 누른다음 클릭 키를 누르는 순간 EditMarkAll이 실행되는 걸 방지.
+  if ((SendMessage(hwndEdit,SCI_GETSELECTIONS,0,0) > 1)
+     && (SendMessage(hwndEdit,SCI_GETSELECTIONMODE,0,0) == SC_SEL_STREAM))
+    return;

이제 거의 막바지 같은데..확신은 없습니다.
inline0527.patch

Scintilla

unread,
May 27, 2016, 10:23:09 AM5/27/16
to 파이썬문서고
ISO-8859-1을 고려한다면 32~255 인지 확인하는 게 맞겠네요.
그리고, 그런 경우는 아래와 같이

else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || (scn->ch < 32) || (scn->ch > 255)))

상하 범위를 모두 확인하는 게 맞아보입니다.



2016년 5월 27일 금요일 오후 10시 26분 46초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 27, 2016, 9:44:24 PM5/27/16
to 파이썬문서고
scn->ch > 255
scn->ch > '\xFF'

같은 코드가 아닌 것 같습니다..
같은 코드라면
 

else
if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || (scn->ch < 32) || (scn->ch > 255)))


작동해야 할텐데 작동하지 않습니다.


johnsonj

unread,
May 27, 2016, 9:48:47 PM5/27/16
to 파이썬문서고
그리고 현재 신틸라 문자 고지 루틴에 문제가 있어서 코드 포인트로 비교하기가 좀 곤란한 면이 있습니다.

        int byte = static_cast<unsigned char>(s[0]);
        if ((byte < 0xC0) || (1 == len)) {
            // Handles UTF-8 characters between 0x01 and 0x7F and single byte
            // characters when not in UTF-8 mode.
            // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
            // characters representing themselves.
        } else {
            unsigned int utf32[1] = { 0 };
            UTF32FromUTF8(s, len, utf32, ELEMENTS(utf32));
            byte = utf32[0];
        }
        NotifyChar(byte);

1바이트이거나 utf8이 아니면 코드 포인트가 뒤죽박죽 되어 버림.
그래도 원래 비트는 그대로 살아 있으므로 반대로 변환하면 원래의 로컬 바이트를 얻을 수 있습니다.

Scintilla

unread,
May 28, 2016, 8:41:19 AM5/28/16
to 파이썬문서고
32~255와 비교하면 정상동작하는 것 같은데요...

그리고, '\xff'와 비교하는 건 틀린 접근 방법입니다.
'\xff'로 코딩하면 컴파일러는 이 값을 signed char로 해석하기 때문에 -1로 계산합니다.

Visual Studio 2015로 컴파일하면 아래와 같이 의도와는 달리 -1보다 큰 값인지 확인하게 됩니다.

; 5626 :                   }
; 5627 :                 }
; 5628 :               }
; 5629 :             }
; 5630 :           }
; 5631 :           else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || scn->ch > '\xFF'))

    cmp    DWORD PTR _bAutoCompleteWords
, 0
    je    $LN90@MsgNotify
    push    
0
    push    
0
    push    
2102                    ; 00000836H
    push    DWORD PTR _hwndEdit
    call    DWORD PTR __imp__SendMessageW@16
    test    eax
, eax
    je    SHORT $LN63@MsgNotify
    cmp    DWORD PTR
[esi+16], -1
    jle    SHORT $LN90@MsgNotify
$LN63@MsgNotify
:

반면, 32~255와 비교하면 아래와 같은 결과가 나옵니다.

; 5626 :                   }
; 5627 :                 }
; 5628 :               }
; 5629 :             }
; 5630 :           }
; 5631 :           else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || (scn->ch < 32) || (scn->ch > 255)))

    cmp    DWORD PTR _bAutoCompleteWords
, 0
    je    $LN90@MsgNotify
    push    
0
    push    
0
    push    
2102                    ; 00000836H
    push    DWORD PTR _hwndEdit
    call    DWORD PTR __imp__SendMessageW@16
    test    eax
, eax
    je    SHORT $LN63@MsgNotify
    mov    eax
, DWORD PTR [esi+16]
    cmp    eax
, 32                    ; 00000020H
    jl    SHORT $LN63@MsgNotify
    cmp    eax
, 255                ; 000000ffH
    jle    SHORT $LN90@MsgNotify
$LN63@MsgNotify
:

Scintilla 내부적으로 UTF8을 사용하는 것 같은데, 그렇다면 아래와 같이 비교하는 게 맞겠군요.

else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || (scn->ch < 32) || ((scn->ch > 0x7f) && (scn->ch < 0xc2)) || (scn->ch > 0xc3)))

이 부분은 좀 더 확인이 필요해보입니다.



2016년 5월 28일 토요일 오전 10시 48분 47초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 28, 2016, 9:56:22 AM5/28/16
to 파이썬문서고
else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || (scn->ch < 32) || ((scn->ch > 0x7f) && (scn->ch < 0xc2)) || (scn->ch > 0xc3)))

코드 포인터 정말 굉장하네요.
이 코드는 잘 작동하는 것 같습니다.

저는 신틸라 자체에서 해결하려고 시도중..
노드패드++에서도 똑 같은 문제가 있네요.

johnsonj

unread,
May 28, 2016, 9:59:02 AM5/28/16
to 파이썬문서고
"""
그리고, '\xff'와 비교하는 건 틀린 접근 방법입니다.
'\xff'로 코딩하면 컴파일러는 이 값을 signed char로 해석하기 때문에 -1로 계산합니다.

Visual Studio 2015로 컴파일하면 아래와 같이 의도와는 달리 -1보다 큰 값인지 확인하게 됩니다."""

감사합니다. 제 의도와 다른 것이었군요.




johnsonj

unread,
May 28, 2016, 11:24:58 AM5/28/16
to 파이썬문서고
일단 자기 전에 발견한 것
ScintillaWin.cxx,  sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam)

    if (pdoc->TentativeActive()) {
        pdoc->TentativeUndo();
+       AutoCompleteCharacterDeleted();
    } else {
        // No tentative undo means start of this composition so
        // fill in any virtual spaces.
        initialCompose = true;
    }

한 줄 추가해야 할 듯. 확실한 것은 써보면서..알아 보겠습니다.
TentativeUndo() 안에서 호출할 수도 있을 거고..
어쨌거나 맥은 잡은 거 같습니다.

이건 신틸라 문제라서...자꾸 일이 커지네요.

johnsonj

unread,
May 28, 2016, 10:39:57 PM5/28/16
to 파이썬문서고
SCI_AUTOCSETMULTI 새로 발견.

  if (bImeInline)
  {
    SendMessage(hwndEdit,SCI_SETVIRTUALSPACEOPTIONS,SCVS_RECTANGULARSELECTION|SCVS_USERACCESSIBLE,0);
    SendMessage(hwndEdit,SCI_SETMULTIPASTE,SC_MULTIPASTE_EACH,0);
+    SendMessage(hwndEdit,SCI_AUTOCSETMULTI,SC_MULTIAUTOC_EACH,0);
  }
  else
  {
    SendMessage(hwndEdit,SCI_SETVIRTUALSPACEOPTIONS,SCVS_NONE,0);
    SendMessage(hwndEdit,SCI_SETMULTIPASTE,SC_MULTIPASTE_ONCE,0);
+    SendMessage(hwndEdit,SCI_AUTOCSETMULTI,SC_MULTIAUTOC_ONCE,0);
  }


Scintilla

unread,
May 29, 2016, 4:50:56 AM5/29/16
to 파이썬문서고
이걸 어떻게 설명해야 될 지는 모르겠는데요...
여튼 오류 하나를 설명해보겠습니다.

IME인라인 켜고, 다중 선택한 뒤 한글을 입력할 때...

어쩌면 _그것보다
어쩌면 _그것보다
어쩌면 _그것보다

위의 내용을 입력한 뒤, 선택을 _ 3개 위에 둔 상태로...
(언더라인은 입력 내용이 아니라 그냥 커서 위치 표시용...)
한글을 입력하면 몇 가지 이상한 동작이 눈에 띕니다.

1. "ㄱ"을 입력하면 "ㄱ그것보다"가 자동 입력으로 뜹니다.
2. 여기서 다시 Back space를 눌러 "ㄱ"를 제거해도 자동 입력창에 "ㄱ그것보다"가 남아있습니다.

이런 동작방식은 이상하기도 하지만, 영문과 완전히 다른데...
영문은...

Do you _love me?
Do you _love me?
Do you _love me?

이렇게 입력하고 언더라인 위치의 3개를 선택한 뒤에
(역시 언더라인은 내용이 아니라 그냥 커서...)
영문을 입력하면 2, 4, 6...(짝수) 개를 입력하면 자동입력 활성화,
홀수 개를 입력하거나 Back space를 입력하면 자동입력 비활성화가 됩니다.

일단, 여기까지 반영된 내용은 블로그에 올려두겠습니다.
이후 오류는 계속 수정해야 될 것 같습니다.



2016년 5월 29일 일요일 오전 11시 39분 57초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 29, 2016, 5:05:09 AM5/29/16
to 파이썬문서고
ime 인라인이 되니까 정말 일이 많아졌습니다.

자동 완성과 ime 인라인 지금까지 정리.
신틸라쪽 언두 미비점: 자동 완성 박스가 있을 때 언두를 해도 박스가 사라지지 않는다 (여전히 자동 완성중).
                           언두가 한글자 씩이 아니라 왕창 삭제되므로 당연히 자동 완성 매커니즘 파괴됨.
                           인라인 ime에서 언두 메커니즘을 사용하므로 위의 미비점이 그대로 반영됨.

따라서 다음과 같이
    bool initialCompose = false;

    if (pdoc->TentativeActive()) {
        pdoc->TentativeUndo();
+        AutoCompleteCancel();

    } else {
        // No tentative undo means start of this composition so
        // fill in any virtual spaces.
        initialCompose = true;
    }

일단 AutoCompleteCancel();을 추가해 해결함..




johnsonj

unread,
May 29, 2016, 5:41:51 AM5/29/16
to 파이썬문서고
자동 완성 새로운 문제

"한글 하나" 를 입력한 후
'한글'과 '하나'에 대하여 자동 완성을 시도해 보면,
둘 사이에 차이가 있고,
영문 버전을 기준으로 하면 '하나'는 제대로 박스가 뜨지,
'한글'은 박스가 사라짐.

자동 완성 리스트가 하나만 있을 경우 어떤 글자에 대해서는 박스가 사라지고 다시 안 뜨는 이유를 규명할 필요가 있습니다.

Scintilla

unread,
May 29, 2016, 11:12:02 AM5/29/16
to 파이썬문서고
이것도 흥미로운(?) 소재군요.
그렇네요. 박스 동작 방식이 다르네요.


2016년 5월 29일 일요일 오후 6시 41분 51초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 30, 2016, 10:24:38 PM5/30/16
to 파이썬문서고
자동 완성 문제 해결.


          else if (bAutoCompleteWords && !SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0)) 
            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_MODIFIED:
+          if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
+            SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);
+          break;

        case SCN_ZOOM:
          UpdateLineNumberWidth();
          break;


johnsonj

unread,
May 30, 2016, 10:49:33 PM5/30/16
to 파이썬문서고
더 섬세하게 제어

        case SCN_MODIFIED:
          if (scn->modificationType & SC_LASTSTEPINUNDOREDO)
            if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
              SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);
          break;


johnsonj

unread,
May 31, 2016, 12:38:18 AM5/31/16
to 파이썬문서고
한국어는 case SCN_MODIFIED: 추가로 충분한데
일본어가 있어서 다음과 같이 다시 복구..

 
        else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0)
             || (scn->ch < 32) || ((scn->ch > 0x7f) && (scn->ch < 0xc2)) || (scn->ch > 0xc3)))  
            CompleteWord(hwndEdit, FALSE);
          break;

johnsonj

unread,
May 31, 2016, 1:20:46 AM5/31/16
to 파이썬문서고


2016년 5월 31일 화요일 오후 1시 38분 18초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 31, 2016, 1:37:30 AM5/31/16
to 파이썬문서고

IME인라인 켜고, 다중 선택한 뒤 한글을 입력할 때...

어쩌면 _그것보다
어쩌면 _그것보다
어쩌면 _그것보다

1. "ㄱ"을 입력하면 "ㄱ그것보다"가 자동 입력으로 뜹니다.
2. 여기서 다시 Back space를 눌러 "ㄱ"를 제거해도 자동 입력창에 "ㄱ그것보다"가 남아있습니다.


조립중에 백스페이스가 눌리면 한글자씩 지워지는데
자동 완성은 지워진 후에 새로 조립되어 들어오는 글자에서 일어납니다.
조립중인 "그"에서 백스페이스를 두 번 누르면 조립되어 들어오는 글자가 없습니다.
그러므로 SCN_CHARACTERADDED 메시지 발생하지 않음. 그래서 그 상태로 자동 완성 박스에  'ㄱ'이 남음
이걸 죽이기 위해 SCN_MODIFIED에서 자동 완성 취소해 버림.


 
Do you _love me?
Do you _love me?
Do you _love me?

이렇게 입력하고 언더라인 위치의 3개를 선택한 뒤에
(역시 언더라인은 내용이 아니라 그냥 커서...)
영문을 입력하면 2, 4, 6...(짝수) 개를 입력하면 자동입력 활성화,
홀수 개를 입력하거나 Back space를 입력하면 자동입력 비활성화가 됩니다.


처음 자동완성 박스가 뜨고 두 번째는 자동 완성 박스가 떠 있으므로
그냥 신틸라에게 맡김. 신틸라가 비교해 보고 일치하지 않는 거로 판단하고 자동 완성 취소..
세번째 자동 완성 박스가 없으므로 다시 자동완성 시도해서 박스 뜸.
네 번째 자동 완성 박스가 있으므로 그냥 신틸라에게 맡김..역시 자동 완성 취소..

왜 취소되는지는 잘 모르겠습니다.

일본어에서도 똑 같은 패턴이 발견됩니다.
이상 여기까지..

Scintilla

unread,
May 31, 2016, 2:05:09 AM5/31/16
to 파이썬문서고
수고하셨습니다. 일단 여기까지를 반영해서 블로그 공개본을 저녁에 업데이트 해놓도록 하겠습니다.

짝짝짝
.

2016년 5월 31일 화요일 오후 2시 37분 30초 UTC+9, johnsonj 님의 말:

Scintilla

unread,
May 31, 2016, 6:33:48 AM5/31/16
to 파이썬문서고
참, Notepad2.c 에서 아래와 같이

        case SCN_MODIFIED:
         
if (scn->modificationType & SC_LASTSTEPINUNDOREDO)
           
if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
             
SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);


       
case SCN_ZOOM:
         
UpdateLineNumberWidth();
         
break;

case SCN_MODIFIED: 아래에서 break를 빼거나,
UpdateLineNumberWidth();를  추가해야 될 것 같습니다.

원래의 코드와는 달리 UpdateLineNumberWidth()를 실행하지 않는데,
실행하는 게 맞아보입니다.



2016년 5월 31일 화요일 오후 3시 5분 9초 UTC+9, Scintilla 님의 말:

johnsonj

unread,
May 31, 2016, 7:21:20 AM5/31/16
to 파이썬문서고
넵.. 다른데 신경 쓰다 보니..나머지는 저도 잘 모릅니다.
결론: 1. 문자가 하나 등록되었는데 자동 완성 박스가 있다는 이유로 그냥 방치하는 것은 있을 수 없음. 이게 버그의 원인.
       2. 백스페이스로 하나 지워도 자동 완성 박스에 반영...

          //else if (bAutoCompleteWords && !SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))

          else if (bAutoCompleteWords)
            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_AUTOCCHARDELETED:
            CompleteWord(hwndEdit, FALSE);
          break;


        case SCN_MODIFIED:
          if (scn->modificationType & SC_LASTSTEPINUNDOREDO)
            if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
              SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);

        case SCN_ZOOM:
          UpdateLineNumberWidth();
          break;

이제 완벽하게 작동하는 거 같음.

johnsonj

unread,
May 31, 2016, 7:46:36 AM5/31/16
to 파이썬문서고
마구 올리다 보니 코드에 실수가 많습니다.
잘 다듬어 주십시오.


          //else if (bAutoCompleteWords && !SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
          else if (bAutoCompleteWords)
            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_AUTOCCHARDELETED:
          if (bAutoCompleteWords)
            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_MODIFIED:
          if (scn->modificationType & SC_LASTSTEPINUNDOREDO)
            if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
              SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);
          UpdateLineNumberWidth();

Scintilla

unread,
May 31, 2016, 10:42:15 AM5/31/16
to 파이썬문서고
여기까지 반영된 버전을 블로그에 올려뒀습니다: http://teus.me/366

2016년 5월 31일 화요일 오후 8시 46분 36초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
May 31, 2016, 6:12:53 PM5/31/16
to 파이썬문서고
전광석화 같은 적용 감사합니다.

일본어 자동 완성도 일단 예상대로 작동...

johnsonj

unread,
Jun 2, 2016, 9:08:16 AM6/2/16
to 파이썬문서고
아무리 생각해도 찜찜해서리...
ime 인라인을 선택하지 않으면 이전과 똑 같이 자동 완성이 작동하도록 ...
bImeInline을 끝에다 추가..

          else if (bAutoCompleteWords && (!SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0) || bImeInline))

            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_AUTOCCHARDELETED:
          if (bAutoCompleteWords && bImeInline)

            CompleteWord(hwndEdit, FALSE);
          break;

        case SCN_MODIFIED:
          if ((scn->modificationType & SC_LASTSTEPINUNDOREDO) && bImeInline)

            if (SendMessage(hwndEdit, SCI_AUTOCACTIVE, 0, 0))
              SendMessage(hwndEdit, SCI_AUTOCCANCEL, 0, 0);
          UpdateLineNumberWidth();
          break;

멀티 캐럿 모드인데 ime 인라인이 안되면 정말 해괴한 모습이 되므로 역시 계획대로 bImeInline 하나로 통일함.

Scintilla

unread,
Jun 13, 2016, 9:09:53 PM6/13/16
to 파이썬문서고
덕분에 IME인라인을 잘 쓰고 있습니다.

그런데, 쓰다보니 이 기능이 좀 과한(?) 게 아닌가하는 생각이 들 때가 있습니다.

어떤 얘기인가 하면 여백에 클릭을 하면 IME인라인 모드에서는 거기에 문자가 없는 경우에도 무조건 클릭이 되는데,
대부분의 편집기에서는 Alt+클릭 으로 선택을 하는 경우는 허공까지 선택이 되고 단순 클릭 시에는 문자가 없으면 선택되지 않습니다.

혹시 이 부분에 대해 어떻게 생각하시나요?

johnsonj

unread,
Jun 13, 2016, 9:45:34 PM6/13/16
to 파이썬문서고
ime  인라인 메뉴 다음에 가름선을 넣어 두었는데..
컬럼 블록을 지원하려면 어차피 가상 공백을 지원하는 것이 안정적이고
하나씩 옵션을 지원하려니 복잡해서 bImeInline 변수 하나에 묶어 버렸습니다.

원래는 다음과 같이 나뉘어 있었습니다.

인라인 ime  -- ime 도움 없이 직접 입력하기 (한국어는 이미 인라인 ime)
다중캐럿     -- 여러 캐럿을 통해 입력..
가상공백     -- 실제로 문자가 입력되지 않은 공간도 마음대로 이동...

이 중에 가상 공백을 말씀하시는 것이라면... 다음을 바꾸면 됩니다.

          SendMessage(hwndEdit,SCI_SETVIRTUALSPACEOPTIONS,SCVS_RECTANGULARSELECTION|SCVS_USERACCESSIBLE,0);

그리고 블록 컬럼일 때 캐럿이 다 보이는 이유는 다음 덕분입니다.

        SendMessage(hwndEdit,SCI_SETADDITIONALCARETSVISIBLE,bImeInline,0);

원칙적으로는 개념도 다르고 구현도 다르니 따로 메뉴를 분리하는 것이 더 좋다고 생각합니다.

Scintilla

unread,
Jun 13, 2016, 10:19:48 PM6/13/16
to 파이썬문서고
고맙습니다.
그렇다면 혹시 이런 시나리오도 가능할까요?

Alt+선택 으로 동작할 때만 가상공백을 지원하고, 그 외의 경우엔 가상공백을 지원하지 않음[...]

참, 제 블로그에 올린 글을 보셨는지 모르겠는데...
Visual Studio Update 3 RC를 설치하면서 Windows XP 지원을 중단할 생각입니다.
혹시 이 쪽은 어떻게 생각하시나요?


2016년 6월 14일 화요일 오전 10시 45분 34초 UTC+9, johnsonj 님의 말:

johnsonj

unread,
Jun 13, 2016, 11:34:01 PM6/13/16
to 파이썬문서고
일단 따로따로 테스트해 보기 쉽도록 기능을 분리하였습니다.
최대한 원래 코드에 영향을 미치지 않도록 신경을 썼습니다만...

notepad2는 xp와 어울립니다.
작고 빠르고 가볍고....

방법이 없을 경우가 아니면 끝까지 하위 버전을 지원하는 것이 옳다고 생각합니다.
언젠가는 사라지겠지만 의도적으로 없애는 것은 바람직하지 않습니다.

XhmikosR
님이 지원하지 않을 정도면 그 때는 포기해도 좋을 것이라고 생각합니다.


imeInlineSplited.patch

Scintilla

unread,
Jun 14, 2016, 8:46:23 AM6/14/16
to 파이썬문서고
그런 관점도 한번 생각해보겠습니다.

전 굳이 XP를 지원할 생각은 없거든요.


2016년 6월 14일 화요일 오후 12시 34분 1초 UTC+9, johnsonj 님의 말:
Reply all
Reply to author
Forward
0 new messages