. 북마크 관리

여기까지 작성한 후 북마크 기능을 테스트해보면 그럭저럭 제대로 동작한다. 그러나 북마크를 설정한 채로 문서를 편집할 때 북마크의 위치가 변경되므로 조정해야 한다. 북마크 정보는 arMark 배열에 따로 관리되는데 문서가 편집되면 이 정보가 무효해질 수 있기 때문이다.

예를 들어 위의 그림에서 2번 북마크는 4번 문단을 가리키고 있으므로 arMark[2] 4의 값을 가지고 있을 것이다. 이 상태에서 3번 문단 앞에 엔터코드를 입력하면 4번 문단이 5번 문단으로 내려가게 되고 이렇게 되면 arMark[2]가 가리키고 있는 문단번호는 틀리게 된다. 삭제할 때도 마찬가지로 북마크가 설정된 문단 앞의 문단이 사라지면 문단번호가 하나 감소하게 된다.

이런 문제 때문에 북마크는 한 번 설정해놓고 그대로 둘 수 없으며 문서 내용이 편집되면 arMark가 가진 정보 중 변경되어야 할 부분을 찾아 같이 변경해야 한다. 삽입, 삭제는 Insert, Delete에서 일어나므로 이 함수에서 북마크 정보를 관리하도록 하자.

 

void Insert(int nPos, TCHAR *str)

{

     int len;

     int movelen;

    int nCrLf=0,i;

    int r,c;

    int nowPara;

    TCHAR *p=str;

 

     len=lstrlen(str);

     if (len==0) return;

     movelen=lstrlen(buf+nPos)+1;

     memmove(buf+nPos+len,buf+nPos,movelen);

     memcpy(buf+nPos,str,len);

     bLineEnd=FALSE;

     UpdateLineInfo();

     UpdateScrollInfo();

 

    while (*p) {

        if (*p==‘\r’)

           nCrLf++;

        p++;

    }

 

    if (nCrLf) {

        GetRCFromOff(nPos,r,c);

        nowPara=pLine[r].nPara;

        if (c != 0) {

           nowPara++;

        }

 

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

           if (arMark[i] >= nowPara) {

               arMark[i]+=nCrLf;

           }

        }

    }

}

 

삽입되는 문자들 중 다른 문자는 북마크에 전혀 영향을 주지 않는다. 다만 개행코드만이 문단번호에 영향을 줄 뿐이다. Insert 함수는 문서에 문자열을 삽입하기 전에 엔터코드가 몇 개나 들어가는지 세어 본다. 그리고 만약 엔터코드가 하나라도 삽입되었다면 현재 문단 이후에 있는 모든 북마크를 삽입된 엔터코드 개수만큼 뒤로 이동시켜 주었다. 이 조정 대상에 현재 문단도 포함되는가 아닌가는 엔터를 누른 위치에 따라 달라진다.

문단의 선두에서 엔터를 눌렀다면 이 문단의 번호가 하나 증가되므로 이 문단을 가리키는 북마크도 같이 증가되어야 한다. 반면 문단의 중간쯤에서 엔터를 눌렀다면 이 문단의 일부가 아직 남아 있으므로 북마크는 그대로 유지된다. 북마크가 정확하게 문단의 어디쯤을 가리키고 있는가에 따라 현재 문단의 북마크 조정 여부가 달라지는데 ApiEdit는 북마크가 문단의 선두를 가리키고 있는 것으로 정의한다. Delete도 비슷한 방법으로 북마크를 관리한다.

 

void Delete(int nPos, int nCount)

{

     int movelen;

    int nCrLf=0,i;

    int sr,sc,er,ec;

    int sPara,ePara;

    TCHAR *p=buf+nPos;

 

     if (nCount == 0) return;

     if (lstrlen(buf) < nPos+nCount) return;

 

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

        if (p[i]==‘\r’)

           nCrLf++;

    }

 

    if (nCrLf) {

        GetRCFromOff(nPos,sr,sc);

        sPara=pLine[sr].nPara;

        GetRCFromOff(nPos+nCount,er,ec);

        ePara=pLine[er].nPara;

 

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

           if (arMark[i] >= sPara && arMark[i] < ePara) {

               arMark[i]=-1;

           }

           if (arMark[i] >= ePara) {

               arMark[i]-=nCrLf;

           }

        }

    }

 

     movelen=lstrlen(buf+nPos+nCount)+1;

     memmove(buf+nPos, buf+nPos+nCount, movelen);

     UpdateLineInfo();

     UpdateScrollInfo();

}

 

삭제되는 문자 중에 개행코드가 있는지 보고 그 개수만큼 북마크를 앞으로 이동시키면 된다. Insert와는 달리 Delete는 개행문자를 먼저 삭제하면 북마크를 어떻게 조정해야 하는지 알 수 없기 때문에 먼저 조정한 후 문자열을 삭제해야 한다. 이제 실행해보면 문서가 편집되어도 북마크는 항상 제자리를 유지할 것이다.