font: leave room of the terminating new line in fscanf()
[neatroff.git] / dev.c
blob9ac5385bf254c6678fbbeba344644e41ae574599
1 /* output device */
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "roff.h"
8 static char dev_dir[PATHLEN]; /* device directory */
9 static char dev_dev[PATHLEN]; /* output device name */
10 int dev_res; /* device resolution */
11 int dev_uwid; /* device unitwidth */
12 int dev_hor; /* minimum horizontal movement */
13 int dev_ver; /* minimum vertical movement */
15 /* mounted fonts */
16 static char fn_name[NFONTS][FNLEN]; /* font names */
17 static struct font *fn_font[NFONTS]; /* font structs */
18 static int fn_n; /* number of device fonts */
20 /* .fspecial request */
21 static char fspecial_fn[NFONTS][FNLEN]; /* .fspecial first arguments */
22 static char fspecial_sp[NFONTS][FNLEN]; /* .fspecial special fonts */
23 static int fspecial_n; /* number of fonts in fspecial_sp[] */
25 static void skipline(FILE* filp)
27 int c;
28 do {
29 c = getc(filp);
30 } while (c != '\n' && c != EOF);
33 static void dev_prologue(void)
35 out("x T %s\n", dev_dev);
36 out("x res %d %d %d\n", dev_res, dev_hor, dev_ver);
37 out("x init\n");
40 /* find a position for the given font */
41 static int dev_position(char *id)
43 int i;
44 for (i = 1; i < NFONTS; i++) /* already mounted */
45 if (!strcmp(fn_name[i], id))
46 return i;
47 for (i = 1; i < NFONTS; i++) /* the first empty position */
48 if (!fn_font[i])
49 return i;
50 return 0; /* no room left */
53 int dev_mnt(int pos, char *id, char *name)
55 char path[PATHLEN];
56 struct font *fn;
57 if (pos >= NFONTS)
58 return -1;
59 if (strchr(name, '/'))
60 snprintf(path, sizeof(path), "%s", name);
61 else
62 snprintf(path, sizeof(path), "%s/dev%s/%s", dev_dir, dev_dev, name);
63 fn = font_open(path);
64 if (!fn)
65 return -1;
66 if (pos < 0)
67 pos = dev_position(id);
68 if (fn_font[pos])
69 font_close(fn_font[pos]);
70 if (fn_name[pos] != name) /* ignore if fn_name[pos] is passed */
71 snprintf(fn_name[pos], sizeof(fn_name[pos]), "%s", id);
72 fn_font[pos] = fn;
73 out("x font %d %s\n", pos, name);
74 return pos;
77 int dev_open(char *dir, char *dev)
79 char path[PATHLEN];
80 char tok[128];
81 int i;
82 FILE *desc;
83 snprintf(dev_dir, sizeof(dev_dir), "%s", dir);
84 snprintf(dev_dev, sizeof(dev_dev), "%s", dev);
85 snprintf(path, sizeof(path), "%s/dev%s/DESC", dir, dev);
86 desc = fopen(path, "r");
87 if (!desc)
88 return 1;
89 while (fscanf(desc, "%127s", tok) == 1) {
90 if (tok[0] == '#') {
91 skipline(desc);
92 continue;
94 if (!strcmp("fonts", tok)) {
95 fscanf(desc, "%d", &fn_n);
96 for (i = 0; i < fn_n; i++)
97 fscanf(desc, "%s", fn_name[i + 1]);
98 fn_n++;
99 continue;
101 if (!strcmp("sizes", tok)) {
102 while (fscanf(desc, "%128s", tok) == 1)
103 if (!strcmp("0", tok))
104 break;
105 continue;
107 if (!strcmp("res", tok)) {
108 fscanf(desc, "%d", &dev_res);
109 continue;
111 if (!strcmp("unitwidth", tok)) {
112 fscanf(desc, "%d", &dev_uwid);
113 continue;
115 if (!strcmp("hor", tok)) {
116 fscanf(desc, "%d", &dev_hor);
117 continue;
119 if (!strcmp("ver", tok)) {
120 fscanf(desc, "%d", &dev_ver);
121 continue;
123 if (!strcmp("charset", tok))
124 break;
125 skipline(desc);
127 fclose(desc);
128 dev_prologue();
129 for (i = 0; i < fn_n; i++) {
130 if (*fn_name[i] && dev_mnt(i, fn_name[i], fn_name[i]) < 0) {
131 errmsg("neatroff: font %s is missing\n", fn_name[i]);
132 return 1;
135 return 0;
138 static void dev_epilogue(void)
140 out("x trailer\n");
141 out("x stop\n");
144 void dev_close(void)
146 int i;
147 dev_epilogue();
148 for (i = 0; i < NFONTS; i++) {
149 if (fn_font[i])
150 font_close(fn_font[i]);
151 fn_font[i] = NULL;
155 /* glyph handling functions */
157 static struct glyph *dev_find(char *c, int fn, int byid)
159 struct glyph *(*find)(struct font *fn, char *name);
160 struct glyph *g;
161 int i;
162 find = byid ? font_glyph : font_find;
163 if ((g = find(fn_font[fn], c)))
164 return g;
165 for (i = 0; i < fspecial_n; i++)
166 if (dev_pos(fspecial_fn[i]) == fn && dev_pos(fspecial_sp[i]) >= 0)
167 if ((g = find(dev_font(dev_pos(fspecial_sp[i])), c)))
168 return g;
169 for (i = 0; i < NFONTS; i++)
170 if (fn_font[i] && font_special(fn_font[i]))
171 if ((g = find(fn_font[i], c)))
172 return g;
173 return NULL;
176 struct glyph *dev_glyph(char *c, int fn)
178 if ((c[0] == c_ec || c[0] == c_ni) && c[1] == c_ec)
179 c++;
180 if (c[0] == c_ec && c[1] == '(')
181 c += 2;
182 c = cmap_map(c);
183 if (!strncmp("GID=", c, 4))
184 return dev_find(c + 4, fn, 1);
185 return dev_find(c, fn, 0);
188 /* return the mounted position of a font */
189 int dev_pos(char *id)
191 int i;
192 if (isdigit(id[0])) {
193 int num = atoi(id);
194 if (num < 0 || num >= NFONTS || !fn_font[num]) {
195 errmsg("neatroff: bad font position %s\n", id);
196 return -1;
198 return num;
200 for (i = 1; i < NFONTS; i++)
201 if (!strcmp(fn_name[i], id))
202 return i;
203 if (!strcmp(fn_name[0], id))
204 return 0;
205 return dev_mnt(0, id, id);
208 /* return the mounted position of a font struct */
209 int dev_fontpos(struct font *fn)
211 int i;
212 for (i = 0; i < NFONTS; i++)
213 if (fn_font[i] == fn)
214 return i;
215 return 0;
218 /* return the font struct at pos */
219 struct font *dev_font(int pos)
221 return pos >= 0 && pos < NFONTS ? fn_font[pos] : NULL;
224 void tr_fspecial(char **args)
226 char *fn = args[1];
227 int i;
228 if (!fn) {
229 fspecial_n = 0;
230 return;
232 for (i = 2; i < NARGS; i++) {
233 if (args[i] && fspecial_n < LEN(fspecial_fn)) {
234 snprintf(fspecial_fn[fspecial_n],
235 sizeof(fspecial_fn[fspecial_n]), "%s", fn);
236 snprintf(fspecial_sp[fspecial_n],
237 sizeof(fspecial_sp[fspecial_n]), "%s", args[i]);
238 fspecial_n++;