. 파일 정보의 저장

변경 감시를 하려면 편집하고 있던 파일의 상태를 저장해놓아야 한다. 그래야 다른 프로그램이 파일을 변경할 때 변경되었는지 비교해 볼 수 있다. 다음 구조체는 편집파일의 현재 상태를 저장한다. Dangeun.cpp의 선두에 이 구조체를 선언하자.

 

struct FileInfo

{

     HWND hWnd;

     DWORD size;

     FILETIME st;

};

FileInfo *pEditings;

 

파일을 편집하고 있는 편집창의 핸들, 편집파일의 크기와 최후로 파일이 변경된 시간으로 구성되어 있다. 이 구조체의 배열을 정의하되 한 번에 편집할 수 있는 파일 수의 한계는 따로 없으므로 배열의 크기는 동적으로 결정해야 한다. 그래서 구조체 포인터 pEditings를 선언하고 편집파일의 개수만큼 이 구조체를 할당할 것이다.

이 구조체 배열에 파일의 현재 상태를 기록할 시점은 프로그램이 비활성화될 때이다. 다른 프로그램으로 파일을 열려면 당근 편집기가 비활성화되어야 하므로 이때 상태를 저장하면 된다. 이렇게 저장된 상태는 당근이 다시 활성화될 때 원래 저장해놓은 것과 비교해 본다. 비활성화될 때와 다시 활성화되었을 때의 상태를 비교해보면 편집중인 파일이 수정되었는지 아닌지를 알 수 있다. 두 시점 모두 WM_ACTIVATEAPP 메시지가 전달되며 wParam의 값만 다르므로 저장 코드, 비교 코드는 모두 OnActivateApp 함수에 작성된다.

 

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

{

     static BOOL bOnlyOne=TRUE;

     RECT drt;

     HWND hChild;

     SInfo *pSi;

     int idx=0;

     HANDLE hFile;

     DWORD size;

     FILETIME st;

     TCHAR Mes[512];

 

     if (bOnlyOne) {

          if (GetSystemMetrics(SM_CXSCREEN) < 800) {

              SetRect(&drt,10,10,500,300);

          } else {

              SetRect(&drt,10,10,700,500);

          }

          LoadPosition(hWnd,KEY"Position",&drt);

          bOnlyOne=FALSE;

     }

 

     if (wParam) {

     if (Option.bWatchChange && pEditings) {

     for (idx=0;pEditings[idx].hWnd!=NULL;) {

          pSi=(SInfo *)GetWindowLong(pEditings[idx].hWnd,0);

          hFile=CreateFile(pSi->NowFile,0,0,NULL,

              OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

          if (hFile!=INVALID_HANDLE_VALUE) {

              size=GetFileSize(hFile,NULL);

              GetFileTime(hFile,NULL,NULL,&st);

              if (pEditings[idx].size!=size ||

                   CompareFileTime(&pEditings[idx].st,&st)!=0) {

                   wsprintf(Mes,"%s 파일이 다른 프로그램에 의해 변경되었습니다. "

                        "이 파일을 다시 읽으시겠습니까?",pSi->NowFile);

                   if (Option.bReloadNoAsk || MessageBox(g_hFrameWnd, Mes,

                        "변경 감시", MB_YESNO)==IDYES) {

                        RevertFile(pEditings[idx].hWnd);

                   }

              }

              CloseHandle(hFile);

          }

          idx++;

     }

     free(pEditings);

     pEditings=NULL;

     }

     } else {

     if (Option.bWatchChange && g_ChildNum) {

          pEditings=(FileInfo *)malloc(sizeof(FileInfo)*(g_ChildNum+1));

          hChild=GetWindow(g_hMDIClient,GW_CHILD);

          while (hChild) {

              pSi=(SInfo *)GetWindowLong(hChild,0);

              if (strncmp(pSi->NowFile,"이름없음",8) && strnicmp(pSi->NowFile,"http",4)

                   && strnicmp(pSi->NowFile,"ftp",3)) {

                   pEditings[idx].hWnd=hChild;

                   hFile=CreateFile(pSi->NowFile,0,0,NULL,

                        OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

                   if (hFile!=INVALID_HANDLE_VALUE) {

                        pEditings[idx].size=GetFileSize(hFile,NULL);

                        GetFileTime(hFile,NULL,NULL,&pEditings[idx].st);

                        CloseHandle(hFile);

                        idx++;

                   }

              }

              hChild=GetWindow(hChild,GW_HWNDNEXT);

          }

          pEditings[idx].hWnd=NULL;

     }

     }

}

 

wParam은 활성화될 때 TRUE이며 비활성화될 때 FALSE이다. 먼저 비활성화될 때의 처리를 보자. 편집 상태를 저장할 조건은 두 가지인데 bWatchChange 옵션이 선택되어 있고 최소한 하나 이상의 편집창이 열려 있어야 한다. 사용자가 이 동작을 허락하지 않았거나 저장할 대상이 없다면 아무 것도 할 필요가 없다.

pEditings 배열은 편집창의 개수에 끝 표시를 위한 1을 더한 크기만큼 할당된다. 모든 차일드를 순회하면서 파일의 크기와 최후 수정 시간을 기록해놓는다. , 아직 저장되지 않은 문서, 그러니까 이름없음 n에 대한 정보는 기록할 필요없다. 왜냐하면 아직 메모리에만 있는 문서이므로 다른 프로그램이 이 문서를 변경할 리는 절대로 없기 때문이다. 원격지에 있는 파일도 비교하기가 어려우므로 변경 감시 대상에서 제외된다. 세 개의 문서를 편집하고 있을 때 pEditings에는 다음과 같이 정보가 기록된다.

이 프로그램이 다시 활성화될 때 이 정보와 파일의 현재 상태를 비교해보면 변경 여부를 알 수 있다.