2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 1989 - 1992, 2001 - 2006
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with groff; see the file COPYING. If not, write to the Free
20 * Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
28 /* If we are sending output to an onscreen pager (as is the normal case
29 when reading man pages), then we may get an error state on the output
30 stream, if the user does not read all the way to the end.
32 We normally expect to catch this, and clean up the error context, when
33 the pager exits, because we should get, and handle, a SIGPIPE.
38 #if (defined(_MSC_VER) || defined(_WIN32)) \
39 && !defined(__CYGWIN__) && !defined(_UWIN)
41 /* Native MS-Windows doesn't know about SIGPIPE, so we cannot detect the
42 early exit from the pager, and therefore, cannot clean up the error
43 context; thus we use the following static function to identify this
44 particular error context, and so suppress unwanted diagnostics.
48 check_for_output_error (FILE* stream
) /* FIXME in lib-roff, then?? */
50 /* First, clean up any prior error context on the output stream */
53 /* Clear errno, in case clearerr() and fflush() don't */
55 /* Flush the output stream, so we can capture any error context, other
56 than the specific case we wish to suppress.
58 Microsoft doesn't document it, but the error code for the specific
59 context we are trying to suppress seems to be EINVAL -- a strange
60 choice, since it is not normally associated with fflush(); of course,
61 it *should* be EPIPE, but this *definitely* is not used, and *is* so
64 return ((fflush(stream
) < 0) && (errno
!= EINVAL
));
69 /* For other systems, we simply assume that *any* output error context
72 # define check_for_output_error(stream) ferror(stream) || fflush(stream) < 0
77 font_pointer_list::font_pointer_list(font
*f
, font_pointer_list
*fp
)
83 : font_list(0), font_table(0), nfonts(0)
91 font_pointer_list
*tem
= font_list
;
92 font_list
= font_list
->next
;
96 if (check_for_output_error(stdout
))
97 fatal("output error");
100 void printer::load_font(int n
, const char *nm
)
108 font_table
= new font
*[nfonts
];
109 for (int i
= 0; i
< nfonts
; i
++)
113 font
**old_font_table
= font_table
;
114 int old_nfonts
= nfonts
;
118 font_table
= new font
*[nfonts
];
120 for (i
= 0; i
< old_nfonts
; i
++)
121 font_table
[i
] = old_font_table
[i
];
122 for (i
= old_nfonts
; i
< nfonts
; i
++)
124 a_delete old_font_table
;
127 font
*f
= find_font(nm
);
131 font
*printer::find_font(const char *nm
)
133 for (font_pointer_list
*p
= font_list
; p
; p
= p
->next
)
134 if (strcmp(p
->p
->get_name(), nm
) == 0)
136 font
*f
= make_font(nm
);
138 fatal("sorry, I can't continue");
139 font_list
= new font_pointer_list(f
, font_list
);
143 font
*printer::make_font(const char *nm
)
145 return font::load_font(nm
);
148 void printer::end_of_line()
152 void printer::special(char *, const environment
*, char)
156 void printer::devtag(char *, const environment
*, char)
160 void printer::draw(int, int *, int, const environment
*)
164 void printer::change_color(const environment
* const)
168 void printer::change_fill_color(const environment
* const)
172 void printer::set_ascii_char(unsigned char c
, const environment
*env
,
182 glyph
*g
= set_char_and_width(buf
, env
, &w
, &f
);
183 set_char(g
, f
, env
, w
, 0);
189 void printer::set_special_char(const char *nm
, const environment
*env
,
194 glyph
*g
= set_char_and_width(nm
, env
, &w
, &f
);
195 if (g
!= UNDEFINED_GLYPH
) {
196 set_char(g
, f
, env
, w
, nm
);
202 glyph
*printer::set_char_and_width(const char *nm
, const environment
*env
,
203 int *widthp
, font
**f
)
205 glyph
*g
= name_to_glyph(nm
);
206 int fn
= env
->fontno
;
207 if (fn
< 0 || fn
>= nfonts
) {
208 error("bad font position `%1'", fn
);
209 return UNDEFINED_GLYPH
;
213 error("no font mounted at `%1'", fn
);
214 return UNDEFINED_GLYPH
;
216 if (!(*f
)->contains(g
)) {
217 if (nm
[0] != '\0' && nm
[1] == '\0')
218 error("font `%1' does not contain ascii character `%2'",
222 error("font `%1' does not contain special character `%2'",
225 return UNDEFINED_GLYPH
;
227 int w
= (*f
)->get_width(g
, env
->size
);
233 void printer::set_numbered_char(int num
, const environment
*env
, int *widthp
)
235 glyph
*g
= number_to_glyph(num
);
236 int fn
= env
->fontno
;
237 if (fn
< 0 || fn
>= nfonts
) {
238 error("bad font position `%1'", fn
);
241 font
*f
= font_table
[fn
];
243 error("no font mounted at `%1'", fn
);
246 if (!f
->contains(g
)) {
247 error("font `%1' does not contain numbered character %2",
252 int w
= f
->get_width(g
, env
->size
);
255 set_char(g
, f
, env
, w
, 0);
258 font
*printer::get_font_from_index(int fontno
)
260 if ((fontno
>= 0) && (fontno
< nfonts
))
261 return(font_table
[fontno
]);