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)
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
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.
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.
53 check_for_output_error (FILE* stream
)
55 /* First, clean up any prior error context on the output stream */
58 /* Clear errno, in case clearerr() and fflush() don't */
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
69 return ((fflush(stream
) < 0) && (errno
!= EINVAL
));
74 /* For other systems, we simply assume that *any* output error context
77 # define check_for_output_error(stream) ferror(stream) || fflush(stream) < 0
82 font_pointer_list::font_pointer_list(font
*f
, font_pointer_list
*fp
)
88 : font_list(0), font_table(0), nfonts(0)
96 font_pointer_list
*tem
= font_list
;
97 font_list
= font_list
->next
;
101 if (check_for_output_error(stdout
))
102 fatal("output error");
105 void printer::load_font(int n
, const char *nm
)
113 font_table
= new font
*[nfonts
];
114 for (int i
= 0; i
< nfonts
; i
++)
118 font
**old_font_table
= font_table
;
119 int old_nfonts
= nfonts
;
123 font_table
= new font
*[nfonts
];
125 for (i
= 0; i
< old_nfonts
; i
++)
126 font_table
[i
] = old_font_table
[i
];
127 for (i
= old_nfonts
; i
< nfonts
; i
++)
129 a_delete old_font_table
;
132 font
*f
= find_font(nm
);
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)
141 font
*f
= make_font(nm
);
143 fatal("sorry, I can't continue");
144 font_list
= new font_pointer_list(f
, font_list
);
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
,
187 int i
= set_char_and_width(buf
, env
, &w
, &f
);
188 set_char(i
, f
, env
, w
, 0);
194 void printer::set_special_char(const char *nm
, const environment
*env
,
199 int i
= set_char_and_width(nm
, env
, &w
, &f
);
201 set_char(i
, f
, env
, w
, nm
);
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
);
218 error("no font mounted at `%1'", fn
);
221 if (!(*f
)->contains(i
)) {
222 if (nm
[0] != '\0' && nm
[1] == '\0')
223 error("font `%1' does not contain ascii character `%2'",
227 error("font `%1' does not contain special character `%2'",
232 int w
= (*f
)->get_width(i
, env
->size
);
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
);
246 font
*f
= font_table
[fn
];
248 error("no font mounted at `%1'", fn
);
251 if (!f
->contains(i
)) {
252 error("font `%1' does not contain numbered character %2",
257 int w
= f
->get_width(i
, env
->size
);
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
]);