. 포맷변경

다른 포맷의 텍스트를 읽는 기능이 있다면 반대로 윈도우즈 포맷을 강제로 다른 포맷으로 바꾸어 저장하는 기능도 제공해야 한다. 윈도우즈 포맷의 파일을 읽어서 편집한 후 유니코드로 바꾸어 저장하고 싶다면 그렇게 할 수도 있다. 포맷변환 함수가 다 작성되어 있으므로 전혀 어려운 일이 아니다. OnCommand에서 파일의 포맷을 변경하는 명령을 처리하도록 하자.

 

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

{

     ....

     case IDM_FILE_WIN:

          pSi->Ae.SetFormat(AE_FORMAT_WIN);

          SetStatusText(0x10);

          break;

     case IDM_FILE_UNIX:

          pSi->Ae.SetFormat(AE_FORMAT_UNIX);

          SetStatusText(0x10);

          break;

     case IDM_FILE_MAC:

          pSi->Ae.SetFormat(AE_FORMAT_MAC);

          SetStatusText(0x10);

          break;

     case IDM_FILE_UNICODE:

          pSi->Ae.SetFormat(AE_FORMAT_UNICODE);

          SetStatusText(0x10);

          break;

 

사용자가 포맷을 변경했다고 하더라도 당장 어떤 동작을 할 필요는 없다. 내부 포맷 정보인 dwFormat만 변경해놓고 상태란에 변경된 포맷 이름을 출력하기만 하면 된다. 어차피 편집은 윈도우즈 포맷으로만 할 수 있으므로 편집중인 데이터를 건드릴 수도 없다. 파일 포맷이 실제로 변경되는 시점은 저장할 때이다. SaveToFile 함수를 다음과 같이 수정한다.

 

BOOL SaveToFile(HWND hChild,TCHAR *Path)

{

     ....

     len=pSi->Ae.GetTextLength();

    TextBuf=(TCHAR *)malloc(len+2);

    pSi->Ae.GetText(TextBuf,len+2);

     WriteFile(hFile,TextBuf,len,&dwWritten,NULL);

     CloseHandle(hFile);

     ....

}

 

유니코드 포맷을 지원하기 위해 버퍼의 길이를 1바이트 더 늘려 주었을 뿐이다. 파일로 저장되는 데이터는 GetText 함수가 구하므로 이 함수가 내부 포맷을 dwFormat으로 변경하기만 하면 된다. dwFormat이 윈도우즈 포맷이 아닐 경우 문서의 길이는 변환해 봐야 알 수 있기 때문에 doclen을 읽어서는 정확하게 알 수 없게 되었다. 그래서 문서의 길이를 구하는 GetTextLength 함수도 수정되어야 한다.

 

void CApiEdit::GetText(TCHAR *TextBuf, int BufSize , int s/*=-1*/, int e/*=-1*/)

{

     TCHAR *dest;

     int len;

 

     if (s==-1) {

          if (dwFormat != AE_FORMAT_WIN) {

              len=ConvertFormat(AE_FORMAT_WIN,dwFormat,buf,dest);

              memcpy(TextBuf,dest,min(len,BufSize));

              TextBuf[len]=0;

              TextBuf[len+1]=0;

              free(dest);

          } else {

              lstrcpyn(TextBuf,buf,BufSize);

          }

     } else {

          lstrcpyn(TextBuf,buf+s,min(BufSize,e-s+1));

     }

}

 

int CApiEdit::GetTextLength()

{

     TCHAR *dest;

     int len;

 

     if (dwFormat != AE_FORMAT_WIN) {

          len=ConvertFormat(AE_FORMAT_WIN,dwFormat,buf,dest);

          free(dest);

     } else {

          len=doclen;

     }

     return len;

}

 

dwFormat이 윈도우즈 포맷이 아니라면 이 포맷대로 문자열을 변환한 후 TextBuf에 복사하도록 했다. dwFormat이 내부 포맷이 아닌 경우는 두 가지가 있는데 애초에 파일을 읽을 때 내부 포맷이 아니었거나 아니면 사용자에 의해 다른 포맷으로 변경된 경우이다. 두 경우 모두 dwFormat대로 변환하기만 하면 된다.

문서의 길이를 조사하는 GetTextLength 함수도 조금 복잡해졌다. 편집중인 파일의 내부 포맷이 윈도우즈 포맷이 아니라면 실제로 파일을 변환해 봐야 정확한 크기를 알 수 있다. 파일의 길이를 아는 과정이 이렇게 복잡해졌으므로 상태란의 텍스트 출력루틴도 약간 수정되어야 한다.

 

void SetStatusText(int mask,LPCTSTR Mes/*=NULL*/)

{

     ....

     if (mask & 4) {

          if (pSi->Ae.GetFormat() == AE_FORMAT_WIN) {

              byte=pSi->Ae.GetTextLength();

              if (byte < 10240) {

                   wsprintf(Text, " %d %d 바이트",pSi->Ae.GetDocInfo(0)+1,byte);

              } else {

                   wsprintf(Text, " %d %d K바이트",pSi->Ae.GetDocInfo(0)+1,byte/1024);

              }

          } else {

              wsprintf(Text, " %d",pSi->Ae.GetDocInfo(0)+1);

          }

          SendMessage(hStatus, SB_SETTEXT, 2, (LPARAM)Text);

     }

 

상태란에 총 바이트수를 출력하기 위해 매번 텍스트를 변환해 볼 수는 없는 일이다. 그래서 윈도우즈 포맷일 때만 총 바이트 수를 보여주도록 했으며 나머지 포맷일 때는 바이트 수를 생략한다. 글자 하나를 입력할 때마다 상태란이 갱신되는데 그때마다 텍스트를 변환해야 한다면 끔찍한 일이 아닐 수 없다.