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