. 엔터 입력

가장 먼저 추가할 기능은 엔터코드를 입력받아 줄바꿈을 하는 것이다. 텍스트 편집기라면 당연히 여러 줄을 한꺼번에 편집할 수 있어야 하며 줄 사이를 자유롭게 이동할 수도 있어야 한다. 여러 줄 출력을 위해서는 줄간의 개념이 필요하다. 줄간이란 말 그대로 줄 사이의 간격인데 줄간을 기억하기 위해 전역변수 두 개를 선언한다.

 

int LineRatio;

int LineHeight;

 

줄간이란 폰트 높이에 대한 비율로 표시되는데 실제 출력에 적용하려면 픽셀 단위로 변환되어야 한다. LineRatio 변수는 폰트 높이에 대한 줄간 비율을 백분율로 표시한 것이며 LineHeight는 이 비율대로 줄간을 픽셀 단위로 계산한 것이다. 비율로부터 픽셀 단위를 매번 계산해낼 수도 있지만 이 값은 자주 사용되므로 별도의 변수를 두는 것이 속도상 유리하다. OnCreate에서 이 두 변수를 다음과 같이 초기화한다.

 

BOOL OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)

{

     ....

     FontHeight=tm.tmHeight;

    LineRatio=120;

    LineHeight=int(FontHeight*LineRatio/100);

     ReleaseDC(hWnd,hdc);

     return TRUE;

}

 

줄간의 비율은 120%로 설정했으며 줄간은 FontHeight에서 이 비율을 곱해서 계산한다. 만약 FontHeight 20픽셀이라면 줄간은 24픽셀이 될 것이며 각 줄 사이에 4픽셀씩의 빈 공간이 삽입된다. LineRatio 200이라면 한 줄씩 띄어서 출력될 것이고 100이라면 폰트 높이와 똑같은 간격을 가지게 되는데 적당히 간격을 띄우는 것이 보기 좋으므로 120을 초기 줄간 비율로 설정하였다.

여러 줄을 입력받는다는 것은 곧 개행코드(Enter Code)를 인식한다는 뜻이다. 입력할 때 엔터코드를 버퍼에 넣고 출력할 때도 엔터코드를 만나면 줄을 바꾸도록 해야 한다. 먼저 OnChar에서 엔터코드를 버퍼에 넣도록 해보자.

 

void OnChar(HWND hWnd, TCHAR ch, int cRepeat)

{

     TCHAR szChar[3];

     int i;

 

    if ((ch < ‘ ‘ && ch != ‘\r’ && ch != ‘\t’) || ch==127)

        return;

   

    if (ch == ‘\r’) {

        szChar[0]=‘\r’;

        szChar[1]=‘\n’;

        szChar[2]=0;

    } else {

        szChar[0]=ch;

        szChar[1]=0;

    }

 

     for (i=0;i<cRepeat;i++) {

          Insert(off,szChar);

          off+=lstrlen(szChar);

     }

     bComp=FALSE;

     InvalidateRect(hWnd,NULL,TRUE);

     SetCaret();

}

 

<Enter>키의 문자코드는 \r이고 윈도우즈에서 개행코드는 \r\n으로 표현된다. 그래서 \r을 입력받으면 버퍼에 \r\n을 써 넣도록 하였다. 즉 엔터코드는 두 개의 연속적인 문자로 표현되는데 OnChar에서는 개행코드 자리에 \r\n만 넣으면 된다. 만약 우리나라+Enter+대한민국을 입력했다면 buf에는 다음과 같이 기록될 것이다.

OnChar에서 엔터코드를 기록만 하고 나머지 출력이나 커서이동 처리는 OnPaint SetCaret에서 처리한다.

앞쪽의 조건문은 불필요한 문자들이 입력되지 않도록 막아준다. <Ctrl+A>, <Ctrl+S> 등의 제어코드도 문자코드를 가지며 이 키입력도 WM_CHAR 메시지를 발생시키는데 이 문자들을 그대로 버퍼에 기록하면 이상한 문자들이 출력된다. Ime3까지는 BS 문자만 막았으며 나머지 제어코드들을 막지 않았기 때문에 <Ctrl>키와 알파벳키를 같이 누르면 이상한 모양의 제어코드가 그대로 출력될 것이다.

제어코드들은 모두 32(0x20) 미만의 코드값을 가지는데 이 코드값들이 입력된 경우 return하여 버퍼에 들어오지 못하도록 막았다. 단 제어코드 중 엔터코드와 탭은 텍스트 편집에 필요하므로 예외적으로 입력받는다. 127 <Ctrl+BS>인데 이 문자도 입력되지 못하도록 막아야 한다.

엔터코드가 \r\n 2바이트로 기록됨으로써 DBCS가 되었는데 따라서 해당 문자가 2바이트인지 확인하려면 IsDBCSLeadByte 함수 호출만으로는 부족하며 엔터코드인지 아닌지도 봐야 한다. IsDBCS 함수를 수정하여 nPos 위치의 문자가 정말 DBCS 문자인지 또는 엔터코드인지를 검사한다.

 

 

inline BOOL IsDBCS(int nPos)

{

     return (IsDBCSLeadByte(buf[nPos]) || (buf[nPos]==‘\r’ && buf[nPos+1]==‘\n’));

}

 

한글뿐만 아니라 엔터코드를 만날 때도 한글인 것처럼 인식하도록 했다. 따라서 오른쪽으로 이동할 때 엔터코드를 만나면 메모리상으로 두 칸 이동하여 \r \n을 모두 건너뛰며 줄 끝에서 <Del>키로 엔터코드를 삭제하면 \r\n이 같이 지워진다.