tr: resetting font script and language
[neatroff.git] / out.c
blob58ebbfab4b1eb20145f30037274f41daa4d8eed1
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 while (**s == ' ' || **s == '\t')
69 (*s)++;
70 return eval_up(s, scale);
73 static int tok_numpt(char **s, int scale, int *i)
75 char *o;
76 while (**s == ' ' || **s == '\t')
77 (*s)++;
78 o = *s;
79 *i = eval_up(s, scale);
80 return o == *s ? 1 : 0;
83 static void out_draw(char *s)
85 int c = *s++;
86 out("D%c", c);
87 switch (tolower(c)) {
88 case 'l':
89 outnn(" %d", tok_num(&s, 'm'));
90 outnn(" %d", tok_num(&s, 'v'));
91 outnn(" ."); /* dpost requires this */
92 break;
93 case 'c':
94 outnn(" %d", tok_num(&s, 'm'));
95 break;
96 case 'e':
97 outnn(" %d", tok_num(&s, 'm'));
98 outnn(" %d", tok_num(&s, 'v'));
99 break;
100 case 'a':
101 outnn(" %d", tok_num(&s, 'm'));
102 outnn(" %d", tok_num(&s, 'v'));
103 outnn(" %d", tok_num(&s, 'm'));
104 outnn(" %d", tok_num(&s, 'v'));
105 break;
106 case '~':
107 case 'p':
108 while (*s) {
109 int h, v;
110 if (tok_numpt(&s, 'm', &h) || tok_numpt(&s, 'v', &v)) {
111 outnn(" ");
112 while (*s && *s != ' ')
113 outnn("%c", *s++);
114 } else {
115 outnn(" %d", h);
116 outnn(" %d", v);
119 break;
121 outnn("\n");
124 static void outg(char *c, int fn, int sz)
126 int ofn = o_f;
127 int osz = o_s;
128 out_ft(fn);
129 out_ps(sz);
130 if (utf8one(c))
131 outnn("c%s%s", c, c[1] ? "\n" : "");
132 else
133 out("C%s\n", c[0] == c_ec && c[1] == '(' ? c + 2 : c);
134 out_ft(ofn);
135 out_ps(osz);
138 static void outc(char *c)
140 struct glyph *g = dev_glyph(c, o_f);
141 struct font *fn = dev_font(o_f);
142 int cwid, bwid;
143 if (!g)
144 return;
145 cwid = font_gwid(g->font, dev_font(o_f), o_s, g->wid);
146 bwid = font_wid(g->font, o_s, g->wid);
147 if (font_mapped(g->font, c))
148 c = g->name;
149 if (font_getcs(fn))
150 outnn("h%d", (cwid - bwid) / 2);
151 outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
152 if (font_getbd(fn)) {
153 outnn("h%d", font_getbd(fn) - 1);
154 outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
155 outnn("h%d", -font_getbd(fn) + 1);
157 if (font_getcs(fn))
158 outnn("h%d", -(cwid - bwid) / 2);
159 outnn("h%d", cwid);
162 void out_line(char *s)
164 char *c;
165 int t;
166 while ((t = escread(&s, &c)) >= 0) {
167 if (!t) {
168 if (c[0] == c_ni || (c[0] == '\\' && c[1] == '\\')) {
169 c[0] = c[1];
170 c[1] = '\0';
172 if (c[0] == '\t' || c[0] == '\x01' || c_hymark(c))
173 continue;
174 outc(cmap_map(c));
175 continue;
177 switch (t) {
178 case 'D':
179 out_draw(c);
180 break;
181 case 'f':
182 out_ft(dev_pos(c));
183 break;
184 case 'h':
185 outnn("h%d", eval(c, 'm'));
186 break;
187 case 'm':
188 if (!n_cp)
189 out_clr(clr_get(c));
190 break;
191 case 's':
192 out_ps(eval(c, 0));
193 break;
194 case 'v':
195 outnn("v%d", eval(c, 'v'));
196 break;
197 case 'X':
198 out("x X %s\n", c);
199 break;