. 관련 함수 수정

각 함수들이 마진을 인식하도록 개별적으로 수정해보자. 많은 부분을 고칠 필요는 없고 수평좌표의 초기값을 0으로 주지 않고 마진폭에서부터 시작하도록 조금씩만 수정하면 된다. 오프셋으로부터 픽셀 좌표를 구하는 GetXYFromOff 함수를 보면 x=0;이라는 초기화 문장이 있는데 이 문장을 다음과 같이 변경한다.

 

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

{

     ....

     x=MarginWidth;

 

x는 줄 처음 문자의 수평좌표값인데 마진이 없을 때는 무조건 0이었지만 마진이 있으면 첫 문자의 좌표는 마진폭에서 시작되어야 한다. 그래야 첫 문자가 마진 바로 오른쪽에서부터 출력될 것이다. 마찬가지로 GetOffFromXY 함수도 왼쪽 끝이 0이 아니라 마진폭에서부터 누적 폭을 계산한다.

 

int GetOffFromXY(int x, int y)

{

     ....

     for (p=buf+pLine[r].Start,acwidth=MarginWidth;;) {

 

이 두 함수의 변화가 상식적으로 쉽게 이해가 되고 논리적으로 아무 문제가 없는 것 같은가? 잘 생각해보면 이렇게 코드를 수정하면 아주 중대한 의미적 변화가 발생한다. 오프셋과 픽셀 좌표간의 변환을 담당하는 두 함수가 이런 식으로 마진을 계산에 포함하면 이제 이 두 함수가 사용하는 XY 좌표값은 더 이상 문서상의 픽셀 좌표가 아니다.

문서상의 픽셀 좌표라면 문서의 첫 문자는 항상 (0,0)의 좌표를 가져야 하지만 마진이 있으면 (MarginWidth,0)의 좌표를 가지게 되는 것이다. 이 좌표값은 문서상의 좌표값에 화면상의 마진폭을 같이 고려하여 만들어진 짬뽕값이며 순수한 문서 좌표라 할 수 없다. 만약 이 두 함수가 계속 순수한 문서상의 좌표만을 다루도록 하고 싶다면 그렇게 할 수도 있다.

대신 SetCaret, OnMouseMove, Invalidate 함수들은 이 함수가 리턴하는 문서상의 좌표를 화면 좌표로 바꾸기 위해 마진값을 고려해야 하는 부담이 생기며 이는 무척 귀찮은 일이다. 논리적인 치밀함도 좋지만 코드량이 늘어날 수 있기 때문에 이 두 함수가 다루는 값에 약간의 의미적 변화가 생기는 것을 감수하기로 하였다. 이렇게 해도 별 문제는 없지만 논리에 약간의 변화가 생겼다는 것은 잘 기억해두어야 다음에 문제가 생겨도 원인을 쉽게 찾을 수 있다.

괜히 쓸데없이 복잡한 얘기를 꺼낸 것 같은데 헷갈리면 무시하고 넘어가도 상관없다. 다음은 한 줄을 출력하는 DrawLine을 수정하도록 하자. 이 함수는 조각의 처음 출력 좌표를 x=0-xPos;로 초기화하고 있다. x쪽으로 수평스크롤 된 만큼 왼쪽에서부터 출력을 해 온다는 뜻인데 자동개행 상태에서 xPos 0이므로 그냥 0이라고 생각해도 무방하다. 이 코드를 다음과 같이 수정한다.

 

int DrawLine(HDC hdc, int Line)

{

     ....

     x=MarginWidth-xPos;

 

마진폭 바로 다음부터 출력을 시작하도록 하였다. 이제 첫 조각은 이 좌표에 출력되고 이어지는 조각은 계속 뒤쪽에 연이어 출력된다. 이 함수를 수정하면 문자열들이 마진폭을 침범하지 않게 될 것이다. 다음 함수도 수정한다.

 

int GetXPosOnLine(int r,int DestX)

{

     TCHAR *p;

     int len, acwidth;

 

    if (DestX == MarginWidth) {

          return pLine[r].Start;

     }

    for (p=buf+pLine[r].Start, acwidth=MarginWidth;;) {

    ....

 

줄의 처음 위치가 0이 아니라 MarginWidth가 되며 누적 폭의 초기값도 MarginWidth가 된다. 마지막으로 정렬함수인 GetLine도 마진폭을 고려하여 정렬하도록 수정한다.

 

void GetLine(int Line, int &s, int &e)

{

     ....

     if (nWrap == 0) {

          while (*p != ‘\r’ && *p != 0)

              p++;

     } else {

        for (acwidth=MarginWidth;;) {

          ....

 

정렬의 시작 좌표도 마진폭 바로 다음에서 시작해야 제대로 정렬이 될 것이다. 여러 가지 함수를 이곳 저곳 수정했지만 모두 줄의 시작 좌표가 바뀌었을 뿐이며 동일한 작업들이었다. 보다시피 코드량이 늘어나면 한 가지만 바꿔도 손대야 할 곳이 점점 많아진다. 여기까지 작업한 후 실행해보자. 왼쪽에 마진이 깔끔하게 출력될 것이다.

정렬도 제대로 되었고 마우스로 작업영역을 찍어도 제 위치를 정확하게 찾고 아래위 이동도 정확하게 수직으로 동작한다. 일단은 만족스럽다.