Initial import from FreeBSD RELENG_4:
[games.git] / contrib / groff / src / libs / libdriver / printer.cc
1 // -*- C++ -*-
2
3 // <groff_src_dir>/src/libs/libdriver/printer.cc
4
5 /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
6    Free Software Foundation, Inc.
7    Written by James Clark (jjc@jclark.com)
8
9    Last update: 12 Apr 2002
10
11    This file is part of groff.
12
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)
16    any later version.
17
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.
22
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, 59 Temple Place - Suite 330, Boston, MA
26    02111-1307, USA.
27 */
28
29 #include "driver.h"
30
31 printer *pr = 0;
32
33 font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
34 : p(f), next(fp)
35 {
36 }
37
38 printer::printer()
39 : font_list(0), font_table(0), nfonts(0)
40 {
41 }
42
43 printer::~printer()
44 {
45   a_delete font_table;
46   while (font_list) {
47     font_pointer_list *tem = font_list;
48     font_list = font_list->next;
49     delete tem->p;
50     delete tem;
51   }
52   if (ferror(stdout) || fflush(stdout) < 0)
53     fatal("output error");
54 }
55
56 void printer::load_font(int n, const char *nm)
57 {
58   assert(n >= 0);
59   if (n >= nfonts) {
60     if (nfonts == 0) {
61       nfonts = 10;
62       if (nfonts <= n)
63         nfonts = n + 1;
64       font_table = new font *[nfonts];
65       for (int i = 0; i < nfonts; i++)
66         font_table[i] = 0;
67     }
68     else {
69       font **old_font_table = font_table;
70       int old_nfonts = nfonts;
71       nfonts *= 2;
72       if (n >= nfonts)
73         nfonts = n + 1;
74       font_table = new font *[nfonts];
75       int i;
76       for (i = 0; i < old_nfonts; i++)
77         font_table[i] = old_font_table[i];
78       for (i = old_nfonts; i < nfonts; i++)
79         font_table[i] = 0;
80       a_delete old_font_table;
81     }
82   }
83   font *f = find_font(nm);
84   font_table[n] = f;
85 }
86
87 font *printer::find_font(const char *nm)
88 {
89   for (font_pointer_list *p = font_list; p; p = p->next)
90     if (strcmp(p->p->get_name(), nm) == 0)
91       return p->p;
92   font *f = make_font(nm);
93   if (!f)
94     fatal("sorry, I can't continue");
95   font_list = new font_pointer_list(f, font_list);
96   return f;
97 }
98
99 font *printer::make_font(const char *nm)
100 {
101   return font::load_font(nm);
102 }
103
104 void printer::end_of_line()
105 {
106 }
107
108 void printer::special(char *, const environment *, char)
109 {
110 }
111
112 void printer::draw(int, int *, int, const environment *)
113 {
114 }
115
116 void printer::change_color(const environment *)
117 {
118 }
119
120 void printer::change_fill_color(const environment *)
121 {
122 }
123
124 void printer::set_ascii_char(unsigned char c, const environment *env, 
125                              int *widthp)
126 {
127   char  buf[2];
128   int   w;
129   font *f;
130
131   buf[0] = c;
132   buf[1] = '\0';
133
134   int i = set_char_and_width(buf, env, &w, &f);
135   set_char(i, f, env, w, 0);
136   if (widthp) {
137     *widthp = w;
138   }
139 }
140
141 void printer::set_special_char(const char *nm, const environment *env,
142                                int *widthp)
143 {
144   font *f;
145   int w;
146   int i = set_char_and_width(nm, env, &w, &f);
147   if (i != -1) {
148     set_char(i, f, env, w, nm);
149     if (widthp)
150       *widthp = w;
151   }
152 }
153
154 int printer::set_char_and_width(const char *nm, const environment *env,
155                                 int *widthp, font **f)
156 {
157   int i = font::name_to_index(nm);
158   int fn = env->fontno;
159   if (fn < 0 || fn >= nfonts) {
160     error("bad font position `%1'", fn);
161     return(-1);
162   }
163   *f = font_table[fn];
164   if (*f == 0) {
165     error("no font mounted at `%1'", fn);
166     return(-1);
167   }
168   if (!(*f)->contains(i)) {
169     if (nm[0] != '\0' && nm[1] == '\0')
170       error("font `%1' does not contain ascii character `%2'",
171             (*f)->get_name(),
172             nm[0]);
173     else
174       error("font `%1' does not contain special character `%2'",
175             (*f)->get_name(),
176             nm);
177     return(-1);
178   }
179   int w = (*f)->get_width(i, env->size);
180   if (widthp)
181     *widthp = w;
182   return( i );
183 }
184
185 void printer::set_numbered_char(int num, const environment *env, int *widthp)
186 {
187   int i = font::number_to_index(num);
188   int fn = env->fontno;
189   if (fn < 0 || fn >= nfonts) {
190     error("bad font position `%1'", fn);
191     return;
192   }
193   font *f = font_table[fn];
194   if (f == 0) {
195     error("no font mounted at `%1'", fn);
196     return;
197   }
198   if (!f->contains(i)) {
199     error("font `%1' does not contain numbered character %2",
200           f->get_name(),
201           num);
202     return;
203   }
204   int w = f->get_width(i, env->size);
205   if (widthp)
206     *widthp = w;
207   set_char(i, f, env, w, 0);
208 }
209
210 font *printer::get_font_from_index(int fontno)
211 {
212   if ((fontno >= 0) && (fontno < nfonts))
213     return(font_table[fontno]);
214   else
215     return(0);
216 }