. 문자 반복

문자 반복 기능은 아래 또는 윗줄의 대응되는 문자를 현재 위치에 복사하는 기능이다. 소스파일 편집시 윗줄의 문자를 반복해서 입력할 때가 많은데 예를 들어 다음과 같은 문장을 입력할 때이다.

 

WndClass.cbClsExtra=0;

WndClass.cbWndExtra=0;

WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

 

각 줄마다 WndClass.이라는 문자열이 같은 위치에서 반복되고 있는데 이럴 때 윗줄 문자 하나를 그대로 복사하는 기능이 있다면 편리할 것 같다. 마찬가지로 아랫줄 문자 하나를 복사하는 기능도 필요한데 다음 함수가 이 일을 한다. dir 0이면 윗줄의 문자를 현재 캐럿 위치로 복사하고 1이면 아랫줄 문자를 복사한다. 여기서 줄이라고 표현하는 개념은 정확하게 말하자면 문단을 의미한다.

 

void CApiEdit::CopyChar(int dir)

{

     int pr,pc;

     int col;

     int toff;

     TCHAR szTemp[3]={0,};

     BOOL bSpace=FALSE;

 

     if (bReadOnly) {

          return;

     }

 

     GetParaFromOff(off,pr,pc);

     if (dir==0) {

          if (pr > 0) {

              pr--;

          } else {

              return;

          }

     }

     if (dir==1) {

          if (pr < pLine[TotalLine-1].nPara) {

              pr++;

          } else {

              return;

          }

     }

 

     ClearSelection();

 

     toff=GetOffFromPara(pr,0);

     for (col=0;;) {

          if (AeIsLineEnd(buf[toff])) {

              return;

          }

          if (col==pc) {

              break;

          }

          if (col>pc) {

              bSpace=TRUE;

              break;

          }

          if (IsDBCS(toff)) {

              toff+=2;

              col+=2;

          } else {

              toff++;

              col++;

          }

     }

 

     if (bSpace) {

          szTemp[0]=‘ ‘;

     } else {

          szTemp[0]=buf[toff];

          if (IsDBCS(toff)) {

              szTemp[1]=buf[toff+1];

          }

     }

     Insert(off,szTemp);

     Invalidate(FindParaStart(off));

     off=off+lstrlen(szTemp);

     SetCaret();

}

 

이 함수도 문서를 변경하기 때문에 일단 읽기전용이 아니어야 한다. dir 방향에 따라 아래 또는 위 문단의 번호를 구하되 한계 점검은 반드시 해야 한다. 첫 문단에서 윗줄 복사 기능이나 마지막 문단에서 아래줄 복사 기능은 복사할 대상이 없기 때문에 아무 것도 할 수 없다. 한계를 벗어났으면 아무 것도 하지 않고 그냥 리턴하도록 했다.

복사할 문단번호를 찾았으면 일단 선택영역을 제거한다. 항상 어떤 문자를 입력할 때는 선택영역을 먼저 제거한 후 입력해야 한다. 읽어야 할 문단번호 pr과 문단 내의 칸 번호 pc를 알고 있으므로 이 문단의 대응되는 문자를 읽어 반복하면 된다. 이때 GetOffFromPara(pr,pc)로 간단하게 이 문자 위치를 구할 수는 없다. 왜냐하면 pc의 위치가 한글의 경계에 걸친 무효한 위치일 수도 있기 때문이다.

그래서 pr문단의 첫 번째 칸부터 읽어 오면서 pc위치와 대응되는 문자를 찾아 본다. 현재 위치와 대응되는 문자를 정확하게 찾았으면 이 문자를 현재 위치에 삽입하면 된다. 대응 문자를 찾는 중에 줄 끝을 만났다면 현재 캐럿 위치와 대응되는 문자가 없으므로 그냥 리턴한다. 만약 대응되는 칸을 넘어섰으면 윗줄의 대응되는 위치가 한글의 중간인 경우이며 이때는 공백 하나를 대신 삽입한다.

여기서 대응된다는 말의 뜻은 칸 번호가 같다는 뜻이지 화면상의 수직위치가 같다는 뜻이 아니다. 고정폭 폰트를 사용한다면 대응되는 칸 번호와 화면 위치가 같겠지만 가변폭 폰트를 사용한다면 그렇지 않을 수도 있다. 대응되는 문자를 복사한 후 다음 위치로 캐럿을 이동하여 이 명령을 반복적으로 사용할 수 있도록 하였다. OnCommand에서 이 함수를 호출한다.

 

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     ....

     case IDM_EDIT_COPYUP:

          pSi->Ae.CopyChar(0);

          break;

     case IDM_EDIT_COPYDOWN:

          pSi->Ae.CopyChar(1);

          break;

 

이 두 기능에 대해 <Ctrl+I>, <Ctrl+Shift+I> 액셀러레이터가 작성되어 있으므로 윗줄에서 복사해 오고 싶은 만큼 단축키를 계속 누르고 있으면 된다. 간단한 기능이지만 나름대로 실용성이 있는 것 같고 개인적으로 무척 마음에 드는 기능이다. 물론 이런 목적이라면 클립보드를 사용하는 것이 정석이지만 아래위로 이동하는 것보다는 <Ctrl+I>를 꾹 누르고 있는 것이 훨씬 더 쉽다.