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