3 // <groff_src_dir>/src/libs/libdriver/printer.cpp
5 /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003, 2004, 2005
6 Free Software Foundation, Inc.
7 Written by James Clark (jjc@jclark.com)
9 Last update: 02 Mar 2005
11 This file is part of groff.
13 groff is free software; you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
18 groff is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with groff; see the file COPYING. If not, write to the Free
25 Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
31 /* If we are sending output to an onscreen pager (as is the normal case
32 when reading man pages), then we may get an error state on the output
33 stream, if the user does not read all the way to the end.
35 We normally expect to catch this, and clean up the error context, when
36 the pager exits, because we should get, and handle, a SIGPIPE.
41 #if (defined(_MSC_VER) || defined(_WIN32)) \
42 && !defined(__CYGWIN__) && !defined(_UWIN)
44 /* Native MS-Windows doesn't know about SIGPIPE, so we cannot detect the
45 early exit from the pager, and therefore, cannot clean up the error
46 context; thus we use the following static function to identify this
47 particular error context, and so suppress unwanted diagnostics.
51 check_for_output_error (FILE* stream)
53 /* First, clean up any prior error context on the output stream */
56 /* Clear errno, in case clearerr() and fflush() don't */
58 /* Flush the output stream, so we can capture any error context, other
59 than the specific case we wish to suppress.
61 Microsoft doesn't document it, but the error code for the specific
62 context we are trying to suppress seems to be EINVAL -- a strange
63 choice, since it is not normally associated with fflush(); of course,
64 it *should* be EPIPE, but this *definitely* is not used, and *is* so
67 return ((fflush(stream) < 0) && (errno != EINVAL));
72 /* For other systems, we simply assume that *any* output error context
75 # define check_for_output_error(stream) ferror(stream) || fflush(stream) < 0
80 font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
86 : font_list(0), font_table(0), nfonts(0)
94 font_pointer_list *tem = font_list;
95 font_list = font_list->next;
99 if (check_for_output_error(stdout))
100 fatal("output error");
103 void printer::load_font(int n, const char *nm)
111 font_table = new font *[nfonts];
112 for (int i = 0; i < nfonts; i++)
116 font **old_font_table = font_table;
117 int old_nfonts = nfonts;
121 font_table = new font *[nfonts];
123 for (i = 0; i < old_nfonts; i++)
124 font_table[i] = old_font_table[i];
125 for (i = old_nfonts; i < nfonts; i++)
127 a_delete old_font_table;
130 font *f = find_font(nm);
134 font *printer::find_font(const char *nm)
136 for (font_pointer_list *p = font_list; p; p = p->next)
137 if (strcmp(p->p->get_name(), nm) == 0)
139 font *f = make_font(nm);
141 fatal("sorry, I can't continue");
142 font_list = new font_pointer_list(f, font_list);
146 font *printer::make_font(const char *nm)
148 return font::load_font(nm);
151 void printer::end_of_line()
155 void printer::special(char *, const environment *, char)
159 void printer::devtag(char *, const environment *, char)
163 void printer::draw(int, int *, int, const environment *)
167 void printer::change_color(const environment * const)
171 void printer::change_fill_color(const environment * const)
175 void printer::set_ascii_char(unsigned char c, const environment *env,
185 int i = set_char_and_width(buf, env, &w, &f);
186 set_char(i, f, env, w, 0);
192 void printer::set_special_char(const char *nm, const environment *env,
197 int i = set_char_and_width(nm, env, &w, &f);
199 set_char(i, f, env, w, nm);
205 int printer::set_char_and_width(const char *nm, const environment *env,
206 int *widthp, font **f)
208 int i = font::name_to_index(nm);
209 int fn = env->fontno;
210 if (fn < 0 || fn >= nfonts) {
211 error("bad font position `%1'", fn);
216 error("no font mounted at `%1'", fn);
219 if (!(*f)->contains(i)) {
220 if (nm[0] != '\0' && nm[1] == '\0')
221 error("font `%1' does not contain ascii character `%2'",
225 error("font `%1' does not contain special character `%2'",
230 int w = (*f)->get_width(i, env->size);
236 void printer::set_numbered_char(int num, const environment *env, int *widthp)
238 int i = font::number_to_index(num);
239 int fn = env->fontno;
240 if (fn < 0 || fn >= nfonts) {
241 error("bad font position `%1'", fn);
244 font *f = font_table[fn];
246 error("no font mounted at `%1'", fn);
249 if (!f->contains(i)) {
250 error("font `%1' does not contain numbered character %2",
255 int w = f->get_width(i, env->size);
258 set_char(i, f, env, w, 0);
261 font *printer::get_font_from_index(int fontno)
263 if ((fontno >= 0) && (fontno < nfonts))
264 return(font_table[fontno]);