hyph: do not read more than GNLEN characters in hy_cget()
[neatroff.git] / out.c
blobcdfec0d5bbb5d48ae6de36eea74a7a61de5a2e03
1 /* generating troff output */
2 #include <ctype.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "roff.h"
9 static int out_nl = 1;
11 /* output troff code; newlines may appear only at the end of s */
12 static void out_out(char *s, va_list ap)
14 out_nl = strchr(s, '\n') != NULL;
15 vfprintf(stdout, s, ap);
18 /* output troff code; no preceding newline is necessary */
19 static void outnn(char *s, ...)
21 va_list ap;
22 va_start(ap, s);
23 out_out(s, ap);
24 va_end(ap);
27 /* output troff cmd; should appear after a newline */
28 void out(char *s, ...)
30 va_list ap;
31 if (!out_nl)
32 outnn("\n");
33 va_start(ap, s);
34 out_out(s, ap);
35 va_end(ap);
38 static int o_s = 10;
39 static int o_f = 1;
40 static int o_m = 0;
42 static void out_ps(int n)
44 if (o_s != n) {
45 o_s = n;
46 out("s%d\n", o_s);
50 static void out_ft(int n)
52 if (n >= 0 && o_f != n) {
53 o_f = n;
54 out("f%d\n", o_f);
58 static void out_clr(int n)
60 if (n >= 0 && o_m != n) {
61 o_m = n;
62 out("m%s\n", clr_str(o_m));
66 static int tok_num(char **s, int scale)
68 char tok[ILNLEN];
69 char *d = tok;
70 while (isspace(**s))
71 (*s)++;
72 while (**s && !isspace(**s))
73 *d++ = *(*s)++;
74 *d = '\0';
75 return eval(tok, scale);
78 static void out_draw(char *s)
80 int c = *s++;
81 out("D%c", c);
82 switch (tolower(c)) {
83 case 'l':
84 outnn(" %d", tok_num(&s, 'm'));
85 outnn(" %d", tok_num(&s, 'v'));
86 outnn(" ."); /* dpost requires this */
87 break;
88 case 'c':
89 outnn(" %d", tok_num(&s, 'm'));
90 break;
91 case 'e':
92 outnn(" %d", tok_num(&s, 'm'));
93 outnn(" %d", tok_num(&s, 'v'));
94 break;
95 case 'a':
96 outnn(" %d", tok_num(&s, 'm'));
97 outnn(" %d", tok_num(&s, 'v'));
98 outnn(" %d", tok_num(&s, 'm'));
99 outnn(" %d", tok_num(&s, 'v'));
100 break;
101 case '~':
102 case 'p':
103 outnn(" %d", tok_num(&s, 'm'));
104 outnn(" %d", tok_num(&s, 'v'));
105 while (*s) {
106 outnn(" %d", tok_num(&s, 'm'));
107 outnn(" %d", tok_num(&s, 'v'));
109 break;
111 outnn("\n");
114 static void outg(char *c, int fn, int sz)
116 int ofn = o_f;
117 int osz = o_s;
118 out_ft(fn);
119 out_ps(sz);
120 if (utf8one(c))
121 outnn("c%s%s", c, c[1] ? "\n" : "");
122 else
123 out("C%s\n", c[0] == c_ec && c[1] == '(' ? c + 2 : c);
124 out_ft(ofn);
125 out_ps(osz);
128 static void outc(char *c)
130 struct glyph *g = dev_glyph(c, o_f);
131 struct font *fn = dev_font(o_f);
132 int cwid, bwid;
133 if (!g)
134 return;
135 cwid = font_gwid(g->font, dev_font(o_f), o_s, g->wid);
136 bwid = font_wid(g->font, o_s, g->wid);
137 if (font_mapped(g->font, c))
138 c = g->name;
139 if (font_getcs(fn))
140 outnn("h%d", (cwid - bwid) / 2);
141 outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
142 if (font_getbd(fn)) {
143 outnn("h%d", font_getbd(fn) - 1);
144 outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
145 outnn("h%d", -font_getbd(fn) + 1);
147 if (font_getcs(fn))
148 outnn("h%d", -(cwid - bwid) / 2);
149 outnn("h%d", cwid);
152 void out_line(char *s)
154 char c[ILNLEN + GNLEN * 4];
155 int t;
156 while ((t = escread(&s, c)) >= 0) {
157 if (!t) {
158 if (c[0] == c_ni || (c[0] == '\\' && c[1] == '\\')) {
159 c[0] = c[1];
160 c[1] = '\0';
162 if (c[0] == '\t' || c[0] == '\x01' || c_hymark(c))
163 continue;
164 outc(cmap_map(c));
165 continue;
167 switch (t) {
168 case 'D':
169 out_draw(c);
170 break;
171 case 'f':
172 out_ft(dev_pos(c));
173 break;
174 case 'h':
175 outnn("h%d", eval(c, 'm'));
176 break;
177 case 'm':
178 if (!n_cp)
179 out_clr(clr_get(c));
180 break;
181 case 's':
182 out_ps(eval(c, 0));
183 break;
184 case 'v':
185 outnn("v%d", eval(c, 'v'));
186 break;
187 case 'X':
188 out("x X %s\n", c);
189 break;