tr: add .fmap to map character names to glyphs
[neatroff.git] / out.c
blobf9b339ee2056dd556e83d93e59f74041d2647b80
1 #include <ctype.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "roff.h"
8 static int out_nl = 1;
10 /* output troff code; newlines may appear only at the end of s */
11 static void out_out(char *s, va_list ap)
13 out_nl = strchr(s, '\n') != NULL;
14 vfprintf(stdout, s, ap);
17 /* output troff code; no preceding newline is necessary */
18 static void outnn(char *s, ...)
20 va_list ap;
21 va_start(ap, s);
22 out_out(s, ap);
23 va_end(ap);
26 /* output troff cmd; should appear after a newline */
27 void out(char *s, ...)
29 va_list ap;
30 if (!out_nl)
31 outnn("\n");
32 va_start(ap, s);
33 out_out(s, ap);
34 va_end(ap);
37 static int o_s = 10;
38 static int o_f = 1;
39 static int o_m = 0;
41 static void out_ps(int n)
43 if (o_s != n) {
44 o_s = n;
45 out("s%d\n", o_s);
49 static void out_ft(int n)
51 if (n >= 0 && o_f != n) {
52 o_f = n;
53 out("f%d\n", o_f);
57 static void out_clr(int n)
59 if (n >= 0 && o_m != n) {
60 o_m = n;
61 out("m%s\n", clr_str(o_m));
65 static int tok_num(char **s, int scale)
67 char tok[ILNLEN];
68 char *d = tok;
69 while (isspace(**s))
70 (*s)++;
71 while (**s && !isspace(**s))
72 *d++ = *(*s)++;
73 *d = '\0';
74 return eval(tok, scale);
77 static void out_draw(char *s)
79 int c = *s++;
80 out("D%c", c);
81 switch (tolower(c)) {
82 case 'l':
83 outnn(" %d", tok_num(&s, 'm'));
84 outnn(" %d", tok_num(&s, 'v'));
85 outnn(" ."); /* dpost requires this */
86 break;
87 case 'c':
88 outnn(" %d", tok_num(&s, 'm'));
89 break;
90 case 'e':
91 outnn(" %d", tok_num(&s, 'm'));
92 outnn(" %d", tok_num(&s, 'v'));
93 break;
94 case 'a':
95 outnn(" %d", tok_num(&s, 'm'));
96 outnn(" %d", tok_num(&s, 'v'));
97 outnn(" %d", tok_num(&s, 'm'));
98 outnn(" %d", tok_num(&s, 'v'));
99 break;
100 case '~':
101 case 'p':
102 outnn(" %d", tok_num(&s, 'm'));
103 outnn(" %d", tok_num(&s, 'v'));
104 while (*s) {
105 outnn(" %d", tok_num(&s, 'm'));
106 outnn(" %d", tok_num(&s, 'v'));
108 break;
110 outnn("\n");
113 static void outg(char *c, int fn)
115 int ofn = o_f;
116 out_ft(fn);
117 if (utf8one(c))
118 outnn("c%s%s", c, c[1] ? "\n" : "");
119 else
120 out("C%s\n", c[0] == c_ec && c[1] == '(' ? c + 2 : c);
121 out_ft(ofn);
124 static void outc(char *c)
126 struct glyph *g = dev_glyph(c, o_f);
127 int cwid = charwid(o_f, o_s, g ? g->wid : SC_DW);
128 int bwid = charwid_base(o_f, o_s, g ? g->wid : SC_DW);
129 if (g && font_mapped(g->font, c))
130 c = g->name;
131 if (dev_getcs(o_f))
132 outnn("h%d", (cwid - bwid) / 2);
133 outg(c, g ? dev_fontpos(g->font) : o_f);
134 if (dev_getbd(o_f)) {
135 outnn("h%d", dev_getbd(o_f) - 1);
136 outg(c, g ? dev_fontpos(g->font) : o_f);
137 outnn("h%d", -dev_getbd(o_f) + 1);
139 if (dev_getcs(o_f))
140 outnn("h%d", -(cwid - bwid) / 2);
141 outnn("h%d", cwid);
144 void out_line(char *s)
146 char c[ILNLEN + GNLEN * 4];
147 int t;
148 while ((t = escread(&s, c)) >= 0) {
149 if (!t) {
150 if (c[0] == c_ni || (c[0] == '\\' && c[1] == '\\')) {
151 c[0] = c[1];
152 c[1] = '\0';
154 if (c[0] == '\t' || c[0] == '\x01' || !strcmp(c_hc, c))
155 continue;
156 outc(cmap_map(c));
157 continue;
159 switch (t) {
160 case 'D':
161 out_draw(c);
162 break;
163 case 'f':
164 out_ft(dev_pos(c));
165 break;
166 case 'h':
167 outnn("h%d", eval(c, 'm'));
168 break;
169 case 'm':
170 if (!n_cp)
171 out_clr(clr_get(c));
172 break;
173 case 's':
174 out_ps(eval_re(c, o_s, '\0'));
175 break;
176 case 'v':
177 outnn("v%d", eval(c, 'v'));
178 break;
179 case 'X':
180 out("x X %s\n", c);
181 break;