. 탭 관련 함수 수정

탭문자 처리코드가 추가됨으로써 여러 가지 함수들이 영향을 받게 되는데 그리 많지는 않다. 주로 화면 좌표를 다루는 함수들이 영향을 받는데 특별히 어려운 코드는 없다. 아무 생각없이 고치기만 하면 된다. 먼저 탭으로 인해 정렬이 영향을 받는다. 정렬은 GetLineSub에서 담당하고 있으므로 이 함수를 다음과 같이 수정한다.

 

int GetLineSub(TCHAR *&p)

{

          ....

          for (acwidth=0;;) {

            if (*p == ‘\t’) {

               len=1;

               acwidth =(acwidth/TabSize+1)*TabSize;

               EndPos=p;

            } else {

                   if (IsDBCS(p-buf)) {

                        len=2;

 

                        if (nWrap==2 || (nWrap==3 && IsPrevDBCS==FALSE)) {

                             EndPos=p;

                             if (*EndPos != ‘ ‘) {

                                 EndPosNoSpace=EndPos;

                             }

                        }

                        IsPrevDBCS=TRUE;

                   } else {

                        len=1;

 

                        if (IsPrevDBCS==TRUE) {

                             EndPos=p;

                             if (*EndPos != ‘ ‘) {

                                 EndPosNoSpace=EndPos;

                             }

                        }

                        IsPrevDBCS=FALSE;

                   }

                   acwidth+=GetCharWidth(hdc,p,len);

            }

 

               if (*p == ‘\r’) {

               ....

 

탭이 발견되면 누적폭을 다음 탭위치로 옮겨준다. 이 함수가 다루는 x 좌표는 문서상의 좌표이므로 스크롤 상태를 고려하지 않고 곧바로 공식을 적용해도 상관없다. 수학식을 이미 이해했으므로 아주 쉽게 이해가 될 것이다. 탭문자는 앞 문자가 한글인가 영문인가에 상관없이 무조건 자를 후보 위치가 된다. 그래서 탭이 발견되는 족족 EndPos를 탭위치로 옮겨 놓았다.

두 번째로 캐럿 위치도 탭을 인식하도록 해야 한다. SetCaret을 고쳐야겠지만 SetCaret은 건드릴 필요가 없고 대신 SetCaret이 호출하는 GetXYFromOff 함수를 수정하면 된다.

 

void GetXYFromOff(int nPos, int &x, int &y)

{

     HDC hdc;

     int r,c,s,e;

    TCHAR *p;

 

     GetRCFromOff(nPos, r, c);

     y=r*LineHeight;

 

     GetLine(r, s, e);

     hdc=GetDC(hWndMain);

    x=0;

    for (p=buf+s;p!=buf+nPos;) {

        if (*p == ‘\t’) {

            x = (x/TabSize+1)*TabSize;

            p++;

        } else {

            if (IsDBCS(p-buf)) {

               x += GetCharWidth(hdc,p,2);

               p+=2;

            } else {

               x += GetCharWidth(hdc,p,1);

               p++;

            }

        }

    }

     ReleaseDC(hWndMain, hdc);

}

 

GetCharWidth 함수 하나로 간단히 x 좌표를 구할 수 있었는데 이제 탭이 들어감으로써 그렇게 할 수가 없다. 한 문자씩 폭을 누적시키고 탭을 만나면 다음 탭위치로 옮기면서 누적폭을 계속 비교해 봐야 한다. 탭을 옮기는 공식은 역시 동일하다. 마지막으로 GetXPosOnLine 함수도 화면상의 좌표를 다루고 있으므로 탭문자를 인식하도록 수정한다.

 

int GetXPosOnLine(int r,int DestX)

{

          ...

     for (p=buf+s, acwidth=0;;) {

          if (p-buf == e)

               break;

 

        if (*p == ‘\t’) {

            len=1;

            acwidth =(acwidth/TabSize+1)*TabSize;

        } else {

               if (IsDBCS(p-buf)) {

                   len=2;

               } else {

                   len=1;

               }

               acwidth+=GetCharWidth(hdc,p,len);

        }

          p+=len;

          ....

 

더 설명이 필요없을 정도로 간단하다. 그래서 설명하지 않겠다. 지금 이 단계에서 도대체 코드가 어떻게 바뀌고 있는 거지?라는 의문이 든다면 아마 DrawSegment의 코드를 눈으로만 읽고 와서 그럴 것이다. 앞에서 이미 이론 점검이 끝난 코드를 계속 반복 적용하고 있기 때문에 한번만 이해하면 나머지는 아주 쉽게 이해되므로 눈으로만 코드를 보지 말고 직접 코드를 수정해보기 바란다. 이제 탭문자 지원이 완성되었다. 잘 동작하는지 앞에서 메모장으로 만들었던 성적표를 ApiEdit로 다시 만들어 보도록 하자.

과연 제대로 잘 입력되고 정렬과 출력이 정확하다. 캐럿을 이동해 봐도 탭위치가 잘 인식될 것이다.