. 인쇄 정보

텍스트 편집기에서 인쇄 기능은 필수 기능이기는 하지만 그다지 상세하게 작성할 필요는 없다고 생각된다. 문서를 편집하는 프로그램이라면 인쇄가 필요하지만 요즘은 인쇄 전용 툴도 많이 보급되어 있기 때문에 편집기로 직접 인쇄를 하는 경우는 그다지 많지 않다. 게다가 텍스트는 서식이 없기 때문에 파일의 내용만 출력할 수 있을 뿐 보기 좋게 문서를 꾸민다거나 장식을 다는 것이 불가능하다. 텍스트를 출력할 필요가 있으면 워드프로세서를 대신 사용하는 것이 더 좋으며 그래서 당근은 기본적인 인쇄 기능만 작성할 것이다.

텍스트를 인쇄하는 것 정도는 사실 무척 쉽다. 프린터로 텍스트를 계속 보내기만 하면 나머지는 프린터가 알아서 할 것이다. 프린터는 내장된 글꼴을 가지고 있으며 행 끝에서 개행이나 용지끝에서 용지 넘김도 자동으로 처리할 수 있다. 도스 환경에서 copy 문서 prn이라는 명령을 내리면 문서가 자동으로 인쇄되는 것처럼 말이다.

그러나 이런 식의 텍스트 인쇄는 텍스트를 종이에 그대로 옮기는 것에 불과하며 텍스트 외의 어떤 것도 출력할 수 없다. 당근은 문법 분석기를 내장하고 있으므로 컬러 인쇄가 가능하고 줄간, 글꼴, 탭 등에 대한 옵션 조정 기능을 가지고 있으므로 이런 기능을 인쇄에도 적용할 수 있다. 또한 아무리 형식이 없다고 하나 머리말, 꼬리말, 페이지 번호 정도는 출력할 수 있어야 하며 페이지 여백도 조정할 수 있도록 하자. 이렇게 하자면 결국 프린터에게 맡길 수 없으며 당근이 직접 인쇄를 해야 하고 텍스트 모드의 인쇄가 아닌 그래픽 모드의 인쇄가 된다.

이렇게 인쇄하고자 할 때 가장 큰 문제점은 텍스트 파일은 위지윅이 아니기 때문에 화면에서와 용지에서의 문서 모양이 달라진다는 점이다. 화면에서는 창의 오른쪽 경계에 맞추어지지만 인쇄할 때는 용지의 폭에 맞추어야 하므로 정렬을 다시 해야 한다. 정렬 상태가 바뀌므로 문법 분석도 다시 해야 하며 줄간, 글꼴의 크기, 탭 크기도 화면에서와는 달라진다. 이런 차이가 발생하는 근본적인 이유는 화면과 프린터의 해상도에 현격한 차이가 있기 때문이다.

머리말이나 꼬리말은 원래 텍스트 파일에 있는 정보가 아니라 사용자에 의해 인위적으로 만들어지는 정보이다. 또한 본문과 머리, 꼬리말의 구분을 위한 구분선이 필요하며 여백에 대한 정보도 필요하다. , 인쇄를 위한 여분의 정보들이 더 많이 필요하다는 얘기다.

인쇄는 호스트와 컨트롤 양쪽이 협동적으로 수행해야 할 작업이다. 텍스트 본문은 컨트롤이 가지고 있으므로 컨트롤이 인쇄하는 것이 효율적이고 머리말, 꼬리말은 문서에 있는 정보가 아니므로 호스트가 직접 인쇄해야 한다. 호스트는 또한 인쇄할 프린터를 선택하고 특성을 조사하며 여백, 글꼴 등의 정보를 사용자로부터 입력받아 컨트롤에게 전달한다. 그래서 호스트와 컨트롤간의 인쇄 작업을 위한 통신 정보가 필요하다. 다음 구조체를 ApiEdit.h에 선언한다.

 

struct Ae_PrintInfo

{

     HDC pdc;

     int dpiY;

     RECT prt;

     int ParseID;

     int nWrap;

     BOOL bLineNum;

 

     int Origin;

     int TabSize;

     int LineHeight;

     int LinePerPage;

     int TotalPage;

     tagLine *pLine;

     CParse *Parser;

};

 

#define Mili(n,r) int((n)*(r)/25.4)

 

Mili 매크로는 밀리미터 단위를 픽셀 단위로 바꾸어 준다. 당근은 인쇄시 모든 단위를 밀리미터로 계산하는데 인쇄 코드에서 직접 단위를 다루기는 번거로우므로 매크로를 선언해두었다. 매크로 내용은 아주 쉽다. 해상도 r은 인치당 픽셀이 몇 개인가에 대한 정보이고 1인치는 25.4밀리미터이므로 해상도를 곱하고 25.4로 나누면 n밀리미터가 몇 픽셀인지를 알 수 있다.

Ae_PrintInfo 구조체의 멤버는 두 개의 그룹으로 나뉜다. 앞쪽 그룹은 호스트가 컨트롤에게 전달하는 인쇄 정보이고 뒤쪽 그룹은 컨트롤이 인쇄중에 직접 정의하여 사용하는 임시정보이다. 각 멤버의 의미는 다음과 같다.

 

멤버

설명

pdc

인쇄에 사용할 프린터 DC이다.

dpiY

프린터의 수직 해상도이다.

prt

여백, 머리말 등을 제외하고 본문이 인쇄될 영역이다. 컨트롤은 영역에 본문을 정렬하여 인쇄한다.

ParseID

구문 분석에 사용할 분석기 ID이다. -1이면 컨트롤이 가지고 있는 분석기로 분석하고 0이면 구문 분석을 하지 않는다.

nWrap

인쇄시의 정렬 방식을 지정한다.

bLineNum

TRUE이면 본문의 왼쪽에 문단번호를 출력한다.

Origin

줄번호 영역을 제외하고 본문 인쇄를 시작할 수평좌표이다.

TabSize

크기이다.

LineHeight

줄간이다.

LinePerPage

페이지에 들어가는

pLine

인쇄를 위한 임시 정렬 정보 배열

Parser

인쇄를 위한 구문 분석기 객체이며 호스트가 전달해 ParseID값대로 분석기를 선택한다.

 

인쇄중에 참고할만한 여러 가지 정보들이 포함되어 있는데 호스트는 인쇄 대화상자에서 사용자가 선택한 옵션과 설정정보에 미리 선택되어 있는 값을 이 구조체에 대입하여 컨트롤에게 전달하고 컨트롤은 이 구조체의 지시대로 인쇄한다. 인쇄 글꼴에 대한 설정은 포함되어 있지 않은데 글꼴은 호스트가 pdc에 선택한다. 따라서 컨트롤은 별다른 폰트 선택없이 pdc에 설정된 글꼴로 인쇄하면 된다.

ApiEdit는 인쇄 기능 지원을 위해 4개의 함수를 제공한다. 다음 4개의 멤버함수들을 CApiEdit 클래스의 멤버로 추가하자.

 

class CApiEdit

{

     ....

     void BeginPrint(Ae_PrintInfo *pi);

     BOOL PrintPage(Ae_PrintInfo *pi,int nPage);

     void EndPrint(Ae_PrintInfo *pi);

     void GetLine(int Line, int &s, int &e,Ae_PrintInfo *pi);

 

각각 인쇄 준비, 한 페이지 인쇄, 인쇄 종료 함수들이며 이 함수들은 호스트에 의해 적당한 때에 호출된다. 다음절에서 당근의 인쇄 코드를 작성할 때 이 함수들을 호출하게 될 것이다. GetLine 함수는 인쇄를 위해 문서를 다시 정렬하는데 BeginPrint 함수에 의해 호출된다.