xref: /netbsd-src/external/gpl2/groff/dist/src/libs/libdriver/printer.cpp (revision 89a07cf815a29524268025a1139fac4c5190f765)
1*89a07cf8Schristos /*	$NetBSD: printer.cpp,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $	*/
2*89a07cf8Schristos 
3*89a07cf8Schristos // -*- C++ -*-
4*89a07cf8Schristos 
5*89a07cf8Schristos // <groff_src_dir>/src/libs/libdriver/printer.cpp
6*89a07cf8Schristos 
7*89a07cf8Schristos /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003, 2004, 2005
8*89a07cf8Schristos    Free Software Foundation, Inc.
9*89a07cf8Schristos    Written by James Clark (jjc@jclark.com)
10*89a07cf8Schristos 
11*89a07cf8Schristos    Last update: 02 Mar 2005
12*89a07cf8Schristos 
13*89a07cf8Schristos    This file is part of groff.
14*89a07cf8Schristos 
15*89a07cf8Schristos    groff is free software; you can redistribute it and/or modify it
16*89a07cf8Schristos    under the terms of the GNU General Public License as published by
17*89a07cf8Schristos    the Free Software Foundation; either version 2, or (at your option)
18*89a07cf8Schristos    any later version.
19*89a07cf8Schristos 
20*89a07cf8Schristos    groff is distributed in the hope that it will be useful, but
21*89a07cf8Schristos    WITHOUT ANY WARRANTY; without even the implied warranty of
22*89a07cf8Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*89a07cf8Schristos    General Public License for more details.
24*89a07cf8Schristos 
25*89a07cf8Schristos    You should have received a copy of the GNU General Public License
26*89a07cf8Schristos    along with groff; see the file COPYING.  If not, write to the Free
27*89a07cf8Schristos    Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
28*89a07cf8Schristos    02110-1301, USA.
29*89a07cf8Schristos */
30*89a07cf8Schristos 
31*89a07cf8Schristos #include "driver.h"
32*89a07cf8Schristos 
33*89a07cf8Schristos /* If we are sending output to an onscreen pager (as is the normal case
34*89a07cf8Schristos    when reading man pages), then we may get an error state on the output
35*89a07cf8Schristos    stream, if the user does not read all the way to the end.
36*89a07cf8Schristos 
37*89a07cf8Schristos    We normally expect to catch this, and clean up the error context, when
38*89a07cf8Schristos    the pager exits, because we should get, and handle, a SIGPIPE.
39*89a07cf8Schristos 
40*89a07cf8Schristos    However ...
41*89a07cf8Schristos */
42*89a07cf8Schristos 
43*89a07cf8Schristos #if (defined(_MSC_VER) || defined(_WIN32)) \
44*89a07cf8Schristos     && !defined(__CYGWIN__) && !defined(_UWIN)
45*89a07cf8Schristos 
46*89a07cf8Schristos   /* Native MS-Windows doesn't know about SIGPIPE, so we cannot detect the
47*89a07cf8Schristos      early exit from the pager, and therefore, cannot clean up the error
48*89a07cf8Schristos      context; thus we use the following static function to identify this
49*89a07cf8Schristos      particular error context, and so suppress unwanted diagnostics.
50*89a07cf8Schristos   */
51*89a07cf8Schristos 
52*89a07cf8Schristos   static int
check_for_output_error(FILE * stream)53*89a07cf8Schristos   check_for_output_error (FILE* stream)
54*89a07cf8Schristos   {
55*89a07cf8Schristos     /* First, clean up any prior error context on the output stream */
56*89a07cf8Schristos     if (ferror (stream))
57*89a07cf8Schristos       clearerr (stream);
58*89a07cf8Schristos     /* Clear errno, in case clearerr() and fflush() don't */
59*89a07cf8Schristos     errno = 0;
60*89a07cf8Schristos     /* Flush the output stream, so we can capture any error context, other
61*89a07cf8Schristos        than the specific case we wish to suppress.
62*89a07cf8Schristos 
63*89a07cf8Schristos        Microsoft doesn't document it, but the error code for the specific
64*89a07cf8Schristos        context we are trying to suppress seems to be EINVAL -- a strange
65*89a07cf8Schristos        choice, since it is not normally associated with fflush(); of course,
66*89a07cf8Schristos        it *should* be EPIPE, but this *definitely* is not used, and *is* so
67*89a07cf8Schristos        documented.
68*89a07cf8Schristos     */
69*89a07cf8Schristos     return ((fflush(stream) < 0) && (errno != EINVAL));
70*89a07cf8Schristos   }
71*89a07cf8Schristos 
72*89a07cf8Schristos #else
73*89a07cf8Schristos 
74*89a07cf8Schristos   /* For other systems, we simply assume that *any* output error context
75*89a07cf8Schristos      is to be reported.
76*89a07cf8Schristos   */
77*89a07cf8Schristos # define check_for_output_error(stream) ferror(stream) || fflush(stream) < 0
78*89a07cf8Schristos 
79*89a07cf8Schristos #endif
80*89a07cf8Schristos 
81*89a07cf8Schristos 
font_pointer_list(font * f,font_pointer_list * fp)82*89a07cf8Schristos font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
83*89a07cf8Schristos : p(f), next(fp)
84*89a07cf8Schristos {
85*89a07cf8Schristos }
86*89a07cf8Schristos 
printer()87*89a07cf8Schristos printer::printer()
88*89a07cf8Schristos : font_list(0), font_table(0), nfonts(0)
89*89a07cf8Schristos {
90*89a07cf8Schristos }
91*89a07cf8Schristos 
~printer()92*89a07cf8Schristos printer::~printer()
93*89a07cf8Schristos {
94*89a07cf8Schristos   a_delete font_table;
95*89a07cf8Schristos   while (font_list) {
96*89a07cf8Schristos     font_pointer_list *tem = font_list;
97*89a07cf8Schristos     font_list = font_list->next;
98*89a07cf8Schristos     delete tem->p;
99*89a07cf8Schristos     delete tem;
100*89a07cf8Schristos   }
101*89a07cf8Schristos   if (check_for_output_error(stdout))
102*89a07cf8Schristos     fatal("output error");
103*89a07cf8Schristos }
104*89a07cf8Schristos 
load_font(int n,const char * nm)105*89a07cf8Schristos void printer::load_font(int n, const char *nm)
106*89a07cf8Schristos {
107*89a07cf8Schristos   assert(n >= 0);
108*89a07cf8Schristos   if (n >= nfonts) {
109*89a07cf8Schristos     if (nfonts == 0) {
110*89a07cf8Schristos       nfonts = 10;
111*89a07cf8Schristos       if (nfonts <= n)
112*89a07cf8Schristos 	nfonts = n + 1;
113*89a07cf8Schristos       font_table = new font *[nfonts];
114*89a07cf8Schristos       for (int i = 0; i < nfonts; i++)
115*89a07cf8Schristos 	font_table[i] = 0;
116*89a07cf8Schristos     }
117*89a07cf8Schristos     else {
118*89a07cf8Schristos       font **old_font_table = font_table;
119*89a07cf8Schristos       int old_nfonts = nfonts;
120*89a07cf8Schristos       nfonts *= 2;
121*89a07cf8Schristos       if (n >= nfonts)
122*89a07cf8Schristos 	nfonts = n + 1;
123*89a07cf8Schristos       font_table = new font *[nfonts];
124*89a07cf8Schristos       int i;
125*89a07cf8Schristos       for (i = 0; i < old_nfonts; i++)
126*89a07cf8Schristos 	font_table[i] = old_font_table[i];
127*89a07cf8Schristos       for (i = old_nfonts; i < nfonts; i++)
128*89a07cf8Schristos 	font_table[i] = 0;
129*89a07cf8Schristos       a_delete old_font_table;
130*89a07cf8Schristos     }
131*89a07cf8Schristos   }
132*89a07cf8Schristos   font *f = find_font(nm);
133*89a07cf8Schristos   font_table[n] = f;
134*89a07cf8Schristos }
135*89a07cf8Schristos 
find_font(const char * nm)136*89a07cf8Schristos font *printer::find_font(const char *nm)
137*89a07cf8Schristos {
138*89a07cf8Schristos   for (font_pointer_list *p = font_list; p; p = p->next)
139*89a07cf8Schristos     if (strcmp(p->p->get_name(), nm) == 0)
140*89a07cf8Schristos       return p->p;
141*89a07cf8Schristos   font *f = make_font(nm);
142*89a07cf8Schristos   if (!f)
143*89a07cf8Schristos     fatal("sorry, I can't continue");
144*89a07cf8Schristos   font_list = new font_pointer_list(f, font_list);
145*89a07cf8Schristos   return f;
146*89a07cf8Schristos }
147*89a07cf8Schristos 
make_font(const char * nm)148*89a07cf8Schristos font *printer::make_font(const char *nm)
149*89a07cf8Schristos {
150*89a07cf8Schristos   return font::load_font(nm);
151*89a07cf8Schristos }
152*89a07cf8Schristos 
end_of_line()153*89a07cf8Schristos void printer::end_of_line()
154*89a07cf8Schristos {
155*89a07cf8Schristos }
156*89a07cf8Schristos 
special(char *,const environment *,char)157*89a07cf8Schristos void printer::special(char *, const environment *, char)
158*89a07cf8Schristos {
159*89a07cf8Schristos }
160*89a07cf8Schristos 
devtag(char *,const environment *,char)161*89a07cf8Schristos void printer::devtag(char *, const environment *, char)
162*89a07cf8Schristos {
163*89a07cf8Schristos }
164*89a07cf8Schristos 
draw(int,int *,int,const environment *)165*89a07cf8Schristos void printer::draw(int, int *, int, const environment *)
166*89a07cf8Schristos {
167*89a07cf8Schristos }
168*89a07cf8Schristos 
change_color(const environment * const)169*89a07cf8Schristos void printer::change_color(const environment * const)
170*89a07cf8Schristos {
171*89a07cf8Schristos }
172*89a07cf8Schristos 
change_fill_color(const environment * const)173*89a07cf8Schristos void printer::change_fill_color(const environment * const)
174*89a07cf8Schristos {
175*89a07cf8Schristos }
176*89a07cf8Schristos 
set_ascii_char(unsigned char c,const environment * env,int * widthp)177*89a07cf8Schristos void printer::set_ascii_char(unsigned char c, const environment *env,
178*89a07cf8Schristos 			     int *widthp)
179*89a07cf8Schristos {
180*89a07cf8Schristos   char  buf[2];
181*89a07cf8Schristos   int   w;
182*89a07cf8Schristos   font *f;
183*89a07cf8Schristos 
184*89a07cf8Schristos   buf[0] = c;
185*89a07cf8Schristos   buf[1] = '\0';
186*89a07cf8Schristos 
187*89a07cf8Schristos   int i = set_char_and_width(buf, env, &w, &f);
188*89a07cf8Schristos   set_char(i, f, env, w, 0);
189*89a07cf8Schristos   if (widthp) {
190*89a07cf8Schristos     *widthp = w;
191*89a07cf8Schristos   }
192*89a07cf8Schristos }
193*89a07cf8Schristos 
set_special_char(const char * nm,const environment * env,int * widthp)194*89a07cf8Schristos void printer::set_special_char(const char *nm, const environment *env,
195*89a07cf8Schristos 			       int *widthp)
196*89a07cf8Schristos {
197*89a07cf8Schristos   font *f;
198*89a07cf8Schristos   int w;
199*89a07cf8Schristos   int i = set_char_and_width(nm, env, &w, &f);
200*89a07cf8Schristos   if (i != -1) {
201*89a07cf8Schristos     set_char(i, f, env, w, nm);
202*89a07cf8Schristos     if (widthp)
203*89a07cf8Schristos       *widthp = w;
204*89a07cf8Schristos   }
205*89a07cf8Schristos }
206*89a07cf8Schristos 
set_char_and_width(const char * nm,const environment * env,int * widthp,font ** f)207*89a07cf8Schristos int printer::set_char_and_width(const char *nm, const environment *env,
208*89a07cf8Schristos 				int *widthp, font **f)
209*89a07cf8Schristos {
210*89a07cf8Schristos   int i = font::name_to_index(nm);
211*89a07cf8Schristos   int fn = env->fontno;
212*89a07cf8Schristos   if (fn < 0 || fn >= nfonts) {
213*89a07cf8Schristos     error("bad font position `%1'", fn);
214*89a07cf8Schristos     return(-1);
215*89a07cf8Schristos   }
216*89a07cf8Schristos   *f = font_table[fn];
217*89a07cf8Schristos   if (*f == 0) {
218*89a07cf8Schristos     error("no font mounted at `%1'", fn);
219*89a07cf8Schristos     return(-1);
220*89a07cf8Schristos   }
221*89a07cf8Schristos   if (!(*f)->contains(i)) {
222*89a07cf8Schristos     if (nm[0] != '\0' && nm[1] == '\0')
223*89a07cf8Schristos       error("font `%1' does not contain ascii character `%2'",
224*89a07cf8Schristos 	    (*f)->get_name(),
225*89a07cf8Schristos 	    nm[0]);
226*89a07cf8Schristos     else
227*89a07cf8Schristos       error("font `%1' does not contain special character `%2'",
228*89a07cf8Schristos 	    (*f)->get_name(),
229*89a07cf8Schristos 	    nm);
230*89a07cf8Schristos     return(-1);
231*89a07cf8Schristos   }
232*89a07cf8Schristos   int w = (*f)->get_width(i, env->size);
233*89a07cf8Schristos   if (widthp)
234*89a07cf8Schristos     *widthp = w;
235*89a07cf8Schristos   return( i );
236*89a07cf8Schristos }
237*89a07cf8Schristos 
set_numbered_char(int num,const environment * env,int * widthp)238*89a07cf8Schristos void printer::set_numbered_char(int num, const environment *env, int *widthp)
239*89a07cf8Schristos {
240*89a07cf8Schristos   int i = font::number_to_index(num);
241*89a07cf8Schristos   int fn = env->fontno;
242*89a07cf8Schristos   if (fn < 0 || fn >= nfonts) {
243*89a07cf8Schristos     error("bad font position `%1'", fn);
244*89a07cf8Schristos     return;
245*89a07cf8Schristos   }
246*89a07cf8Schristos   font *f = font_table[fn];
247*89a07cf8Schristos   if (f == 0) {
248*89a07cf8Schristos     error("no font mounted at `%1'", fn);
249*89a07cf8Schristos     return;
250*89a07cf8Schristos   }
251*89a07cf8Schristos   if (!f->contains(i)) {
252*89a07cf8Schristos     error("font `%1' does not contain numbered character %2",
253*89a07cf8Schristos 	  f->get_name(),
254*89a07cf8Schristos 	  num);
255*89a07cf8Schristos     return;
256*89a07cf8Schristos   }
257*89a07cf8Schristos   int w = f->get_width(i, env->size);
258*89a07cf8Schristos   if (widthp)
259*89a07cf8Schristos     *widthp = w;
260*89a07cf8Schristos   set_char(i, f, env, w, 0);
261*89a07cf8Schristos }
262*89a07cf8Schristos 
get_font_from_index(int fontno)263*89a07cf8Schristos font *printer::get_font_from_index(int fontno)
264*89a07cf8Schristos {
265*89a07cf8Schristos   if ((fontno >= 0) && (fontno < nfonts))
266*89a07cf8Schristos     return(font_table[fontno]);
267*89a07cf8Schristos   else
268*89a07cf8Schristos     return(0);
269*89a07cf8Schristos }
270