3 // <groff_src_dir>/src/libs/libdriver/printer.cpp
5 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
6 Written by James Clark (jjc@jclark.com)
8 This file is part of groff.
10 groff is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 groff is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 /* If we are sending output to an onscreen pager (as is the normal case
27 when reading man pages), then we may get an error state on the output
28 stream, if the user does not read all the way to the end.
30 We normally expect to catch this, and clean up the error context, when
31 the pager exits, because we should get, and handle, a SIGPIPE.
36 #if (defined(_MSC_VER) || defined(_WIN32)) \
37 && !defined(__CYGWIN__) && !defined(_UWIN)
39 /* Native MS-Windows doesn't know about SIGPIPE, so we cannot detect the
40 early exit from the pager, and therefore, cannot clean up the error
41 context; thus we use the following static function to identify this
42 particular error context, and so suppress unwanted diagnostics.
46 check_for_output_error (FILE* stream)
48 /* First, clean up any prior error context on the output stream */
51 /* Clear errno, in case clearerr() and fflush() don't */
53 /* Flush the output stream, so we can capture any error context, other
54 than the specific case we wish to suppress.
56 Microsoft doesn't document it, but the error code for the specific
57 context we are trying to suppress seems to be EINVAL -- a strange
58 choice, since it is not normally associated with fflush(); of course,
59 it *should* be EPIPE, but this *definitely* is not used, and *is* so
62 return ((fflush(stream) < 0) && (errno != EINVAL));
67 /* For other systems, we simply assume that *any* output error context
70 # define check_for_output_error(stream) ferror(stream) || fflush(stream) < 0
75 font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
81 : font_list(0), font_table(0), nfonts(0)
89 font_pointer_list *tem = font_list;
90 font_list = font_list->next;
94 if (check_for_output_error(stdout))
95 fatal("output error");
98 void printer::load_font(int n, const char *nm)
106 font_table = new font *[nfonts];
107 for (int i = 0; i < nfonts; i++)
111 font **old_font_table = font_table;
112 int old_nfonts = nfonts;
116 font_table = new font *[nfonts];
118 for (i = 0; i < old_nfonts; i++)
119 font_table[i] = old_font_table[i];
120 for (i = old_nfonts; i < nfonts; i++)
122 a_delete old_font_table;
125 font *f = find_font(nm);
129 font *printer::find_font(const char *nm)
131 for (font_pointer_list *p = font_list; p; p = p->next)
132 if (strcmp(p->p->get_name(), nm) == 0)
134 font *f = make_font(nm);
136 fatal("sorry, I can't continue");
137 font_list = new font_pointer_list(f, font_list);
141 font *printer::make_font(const char *nm)
143 return font::load_font(nm);
146 void printer::end_of_line()
150 void printer::special(char *, const environment *, char)
154 void printer::devtag(char *, const environment *, char)
158 void printer::draw(int, int *, int, const environment *)
162 void printer::change_color(const environment * const)
166 void printer::change_fill_color(const environment * const)
170 void printer::set_ascii_char(unsigned char c, const environment *env,
180 glyph *g = set_char_and_width(buf, env, &w, &f);
181 set_char(g, f, env, w, 0);
187 void printer::set_special_char(const char *nm, const environment *env,
192 glyph *g = set_char_and_width(nm, env, &w, &f);
193 if (g != UNDEFINED_GLYPH) {
194 set_char(g, f, env, w, nm);
200 glyph *printer::set_char_and_width(const char *nm, const environment *env,
201 int *widthp, font **f)
203 glyph *g = name_to_glyph(nm);
204 int fn = env->fontno;
205 if (fn < 0 || fn >= nfonts) {
206 error("bad font position `%1'", fn);
207 return UNDEFINED_GLYPH;
211 error("no font mounted at `%1'", fn);
212 return UNDEFINED_GLYPH;
214 if (!(*f)->contains(g)) {
215 if (nm[0] != '\0' && nm[1] == '\0')
216 error("font `%1' does not contain ascii character `%2'",
220 error("font `%1' does not contain special character `%2'",
223 return UNDEFINED_GLYPH;
225 int w = (*f)->get_width(g, env->size);
231 void printer::set_numbered_char(int num, const environment *env, int *widthp)
233 glyph *g = number_to_glyph(num);
234 int fn = env->fontno;
235 if (fn < 0 || fn >= nfonts) {
236 error("bad font position `%1'", fn);
239 font *f = font_table[fn];
241 error("no font mounted at `%1'", fn);
244 if (!f->contains(g)) {
245 error("font `%1' does not contain numbered character %2",
250 int w = f->get_width(g, env->size);
253 set_char(g, f, env, w, 0);
256 font *printer::get_font_from_index(int fontno)
258 if ((fontno >= 0) && (fontno < nfonts))
259 return(font_table[fontno]);