. 페이지 인쇄

BeginPrint 함수에 의해 인쇄에 필요한 모든 정보가 만들어졌다. 이제 pi->pLine에 작성된 정렬정보와 pi->Parser 분석기가 분석해놓은 결과를 프린터로 보내기만 하면 된다. 다음 함수는 pi 구조체의 정보를 참조하여 nPage를 인쇄한다. 인쇄 과정은 화면출력과 거의 유사하다. DrawLine DrawSegment를 합쳐 놓은 정도라고 생각하면 된다.

 

BOOL CApiEdit::PrintPage(Ae_PrintInfo *pi,int nPage)

{

     int l,Line;

     int len;

     int nowoff;

     int x;

     SIZE sz;

     int nUnit;

     int style;

     BOOL bFindUnit;

     COLORREF fore, back;

     TCHAR szLine[32];

     COLORREF OldTextColor, OldBkColor;

     int OldBkMode;

     BOOL bEnd=FALSE;

 

     OldTextColor=GetTextColor(pi->pdc);

     OldBkColor=GetBkColor(pi->pdc);

     OldBkMode=GetBkMode(pi->pdc);

     for (l=pi->LinePerPage*(nPage-1),Line=0;l<pi->LinePerPage*nPage;l++,Line++) {

          if (pi->pLine[l].Start == -1) {

              bEnd=TRUE;

              break;

          }

 

          x=pi->Origin;

          nowoff=pi->pLine[l].Start;

          for (;;) {

              for (len=0;;) {

                   if (buf[nowoff+len] == ‘\t’) {

                        if (len==0)

                            len=1;

                        break;

                   }

                   if (nowoff+len==pi->pLine[l].End) {

                        break;

                   }

 

                   if (pi->Parser) {

                        bFindUnit=FALSE;

                        for (nUnit=0;nUnit<pi->Parser->pInfo[l].UnitSize;nUnit++) {

                            if (pi->Parser->pInfo[l].pUnit[nUnit].pos == nowoff+len) {

                                 bFindUnit=TRUE;

                                 break;

                            }

                            if (pi->Parser->pInfo[l].pUnit[nUnit].pos == -1) {

                                 break;

                            }

                        }

 

                        if (bFindUnit && len!=0) {

                            break;

                        }

                   }

                   len++;

              }

 

              if (pi->Parser && len!=0) {

                   for (nUnit=0;nUnit<pi->Parser->pInfo[l].UnitSize;nUnit++) {

                        if (pi->Parser->pInfo[l].pUnit[nUnit].pos >= nowoff+len ||

                            pi->Parser->pInfo[l].pUnit[nUnit].pos == -1) {

                            break;

                        }

                   }

                   style=pi->Parser->pInfo[l].pUnit[nUnit-1].style;

                   pi->Parser->GetStyleColor(style,fore,back);

                   if (fore!=-1) {

                        SetTextColor(pi->pdc,fore);

                   } else {

                        SetTextColor(pi->pdc,RGB(0,0,0));

                   }

                   if (back!=-1) {

                        SetBkColor(pi->pdc,back);

                        SetBkMode(pi->pdc,OPAQUE);

                   } else {

                        SetBkMode(pi->pdc,TRANSPARENT);

                   }

              }else {

                   SetTextColor(pi->pdc,RGB(0,0,0));

                   SetBkMode(pi->pdc,TRANSPARENT);

              }

 

              if (buf[nowoff] == ‘\t’) {

                   x =((x-pi->Origin)/pi->TabSize+1)*pi->TabSize+pi->Origin;

              } else {

                   ExtTextOut(pi->pdc,x,pi->prt.top+Line*pi->LineHeight,

                        ETO_CLIPPED,&pi->prt,buf+nowoff,len,NULL);

                   GetTextExtentPoint32(pi->pdc,buf+nowoff,len,&sz);

                   x+=sz.cx;

              }

 

              nowoff+=len;

              if (nowoff==pi->pLine[l].End) {

                   break;

              }

          }

 

          if (pi->bLineNum) {

              if (pi->pLine[l].nLine==0) {

                   wsprintf(szLine,"%d",pi->pLine[l].nPara);

                   SetTextColor(pi->pdc,RGB(128,128,128));

                   TextOut(pi->pdc,pi->prt.left,pi->prt.top+Line*pi->LineHeight,

                        szLine,lstrlen(szLine));

              }

          }

     }

     SetTextColor(pi->pdc,OldTextColor);

     SetBkColor(pi->pdc,OldBkColor);

     SetBkMode(pi->pdc,OldBkMode);

 

     return bEnd;

}

 

조금 코드가 길기는 하지만 앞에서 다 실습해 왔던 코드라 더 이상 설명이 필요하지는 않을 것이다. 오히려 몇 가지 처리가 생략되어 화면출력 코드보다 더 간단하다. 프린터에서는 선택영역이라는 것이 없으므로 선택 블록을 그릴 필요가 없고 제어코드 보기나 북마크 표시, 현재행 표시 같은 것들도 없다.

이 함수는 nPage를 인쇄한 후 그 결과를 리턴하는데 페이지가 존재하지 않으면 TRUE를 리턴하고 그렇지 않으면 FALSE를 리턴한다. 호스트는 0번째 페이지부터 시작해서 이 함수가 TRUE를 리턴할 때까지 반복적으로 이 함수를 호출하면 된다. 모든 페이지가 다 인쇄되면 마지막 마무리를 한다.

 

void CApiEdit::EndPrint(Ae_PrintInfo *pi)

{

     free(pi->pLine);

     if (pi->Parser) {

          delete pi->Parser;

     }

}

 

이 함수는 BeginPrint와 반대되는 함수이며 BeginPrint가 애써 만들어 놓았던 정보를 삭제한다. 인쇄용 정렬정보를 위해 할당한 메모리를 삭제하고 분석기 객체는 제거한다. 컨트롤의 입장에서는 이 두 가지만 하면 인쇄에 대한 모든 처리를 완료한 것이다. 물론 호스트는 DC 해제, 글꼴 해제 등의 마무리를 더 해야 한다.

여기까지 ApiEdit의 인쇄 지원 코드는 모두 완성되었다. ApiEdit Ae_PrintInfo 구조체의 지시대로 인쇄 준비, 페이지 인쇄 기능을 제공할 뿐이므로 아직 인쇄는 되지 않는다. 호스트인 당근이 인쇄 옵션을 관리하고 인쇄 대화상자로부터 인쇄 정보를 조사해야만 ApiEdit가 인쇄를 할 수 있다. 만약 다른 프로젝트에서 ApiEdit를 사용한다면 당근이 하는 방식대로 ApiEdit와 통신하면서 협조적으로 인쇄해야 한다.