. 변경 시점 저장

취소/재실행시 변경상태를 관리하려면 문서가 저장된 시점, bModified FALSE가 되는 시점의 문서 상태를 저장해두어야 한다. 이때 문서의 상태란 문서가 현재 어떤 모양인지, 어디까지 편집되었는지에 대한 정보인데 이상적으로는 문서 내용을 몽땅 저장해놓으면 되지만 너무 비효율적이다. 좀 더 단순한 방법으로 문서의 상태를 저장할 수 있는 방법이 필요한데 현재 취소 레코드의 인덱스를 저장해두면 된다. 이런 목적으로 다음 변수를 선언한다.

 

class CApiEdit

{

     ....

     int saveur;

 

이 변수는 bModified FALSE가 되는 시점의 nowur값을 가지게 되는데 취소/재실행 코드는 이 값을 참조하여 문서의 변경상태를 관리하게 된다. 이 변수에 문서의 상태를 저장하는 함수를 다음과 같이 작성한다.

 

void CApiEdit::SaveModified()

{

     if (pUR[nowur].status!=UR_CANCELED && pUR[nowur].action != UR_NONE) {

          NextRecord();

     }

 

     saveur=nowur;

}

 

이 함수는 saveur nowur의 첨자를 대입함으로 문서가 저장될 때 취소 레코드가 어느 위치에 있었는지를 기록한다. 이때 nowur의 레코드를 작성중이라면 즉, 삽입중이거나 삭제중이라면 NextRecord 함수를 호출하여 강제로 분할시킨다. , saveur은 작성중인 레코드의 첨자는 기억하지 않으며 빈 레코드나 또는 취소된 레코드만 기억한다. 작성중인 레코드의 상태는 복잡해서 첨자만 비교해서는 문서의 상태를 짐작하기 어렵다. 그래서 레코드 하나를 더 쓰더라도 저장시점의 문서 상태를 좀 간단한 형태로 기억하기로 하였다.

이 함수는 문서를 초기화할 때인 InitDoc bModified를 변경하는 SetModified 함수에서 호출해야 한다. 어디까지 편집하다가 문서를 저장했는지를 saveur 변수에 기록해놓는 것이다. 호스트는 문서를 저장할 때 SetModified(FALSE) 함수를 호출하는데 이때 문서의 상태를 저장하도록 하였다.

 

void CApiEdit::SetModified(BOOL aModi)

{

     bModified=aModi;

    if (aModi==FALSE) {

        SaveModified();

    }

}

 

void CApiEdit::InitDoc()

{

     ....

    SaveModified();

     Invalidate(-1);

}

 

다음 함수는 저장된 레코드 번호 saveur과 현재 레코드 번호 nowur을 비교하여 변경플래그를 재조정한다.

 

void CApiEdit::ArrangeModified()

{

     if (bModified == TRUE) {

          if (nowur==saveur && (pUR[nowur].status==UR_CANCELED || pUR[nowur].action==UR_NONE)) {

              SetModified(FALSE);

          }

     } else {

          SetModified(TRUE);

     }

}

 

문서가 변경되어 있는 상태에서 nowur saveur이 같고 현재 레코드가 취소된 레코드나 빈 레코드라면 이 문서는 다시 변경되지 않은 상태가 되어야 한다. 그 외의 경우, 즉 문서가 변경되지 않은 상태거나 saveur nowur과 다르거나 설사 같다 하더라도 작성중인 레코드이면 bModified TRUE인 상태로 그대로 두어야 한다. 문서가 변경되지 않은 상태에서 이 함수가 호출되었다면 문서는 변경된 것으로 기록되는데 사실 이런 경우는 절대로 없다. 왜냐하면 이 함수를 호출하는 곳에서 이미 Insert Delete를 호출했기 때문에 bModified는 항상 TRUE이다. 취소와 재실행을 하는 Undo, Redo 함수의 끝에서 이 함수를 호출하여 변경상태를 관리하도록 한다.

 

void CApiEdit::Undo()

     ....

     ArrangeModified();

}

 

void CApiEdit::Redo()

{

     ....

     ArrangeModified();

}

 

취소/재실행할 때마다 저장시점과 비교해보고 변경플래그를 조정하도록 하였다. 취소/재실행에 의해 nowur이 아래위로 이동하는데 이 위치가 문서가 저장될 때인 saveur과 같아지고 몇 가지 조건이 만족되면 bModified는 다시 FALSE가 된다. 코드는 간단하지만 ArrangeModified 함수의 조건문이 얼른 이해가 되지 않을 것이다. 문서가 편집되는 일련의 과정을 그림으로 그려보았다.

최초 를 입력한 후 문서를 저장했다. 이때 두 개의 삽입 레코드와 하나의 빈 레코드가 작성되고 nowur saveur은 세 번째 레코드를 가리키고 있으며 모든 레코드의 status 0(UR_MAKING)이다. 각 문자열은 뒤에 공백을 같이 입력하여 병합되지 않도록 했다고 하자. 그림에서 a action의 값이며 s status의 값이다. n s는 각각 nowur saveur이 가리키는 레코드 번호이다.

이 상태에서 를 추가로 입력하면 nowur이 한 칸 위로 올라가고 문서가 편집되었으므로 bModified TRUE가 될 것이다.

입력중인 를 취소하면 네 번째 레코드의 status 1(UR_CANCELED)로 변경된다. 이때 ArrangeModified 함수가 nowur saveur을 비교해보면 값이 다르므로 bModified는 아직 TRUE이다.

의 입력을 다시 한 번 더 취소하면 nowur saveur의 위치가 같아지며 세 번째 레코드의 status 1이 된다. ArrangeModified 함수에서 조건이 만족되므로 bModified FALSE로 바꿀 것이다. 만 입력되어 있던 첫 번째 상태, 즉 저장할 때의 문서 상태와 같아졌으므로 문서는 변경되지 않은 것으로 기록된다.

를 다시 입력하면 네 번째 레코드는 삭제되며 세 번째 레코드의 status 0이 되면서 새로운 레코드가 작성된다. nowur saveur이 일치하지만 action 0이 아니고 status 1이 아니므로 bModified는 다시 TRUE가 된다.

 

이 예에서 최초 상태와 동일한 문서 상태는 네 번째 상태뿐이다. 그 외의 나머지 경우는 문서가 최초 저장할 때와는 조금씩 다른 모습을 가지고 있다. ArrangeModified는 두 상태가 완전히 일치하는지를 비교하고 그 결과에 따라 bModified 플래그를 관리한다. 변경 관리의 핵심은 문서 저장 상태와 똑같은 상태로 돌아갈 때 bModified FALSE로 바꾸는 것이다.