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