post: drawing commands
[neatpost.git] / post.c
blob7c71e9d2d8f9b10c1f94a98e66ae1c99db5df97b
1 /*
2 * neatpost troff postscript postprocessor
4 * Copyright (C) 2013 Ali Gholami Rudi <ali at rudi dot ir>
6 * This program is released under the Modified BSD license.
7 */
8 #include <stdio.h>
9 #include <ctype.h>
10 #include "post.h"
12 static int o_pg;
14 static int next(void)
16 return getc(stdin);
19 static void back(int c)
21 ungetc(c, stdin);
24 static int utf8len(int c)
26 if (c <= 0x7f)
27 return 1;
28 if (c >= 0xfc)
29 return 6;
30 if (c >= 0xf8)
31 return 5;
32 if (c >= 0xf0)
33 return 4;
34 if (c >= 0xe0)
35 return 3;
36 if (c >= 0xc0)
37 return 2;
38 return 1;
41 static int nextutf8(char *s)
43 int c = next();
44 int l = utf8len(c);
45 int i;
46 if (c < 0)
47 return 0;
48 s[0] = c;
49 for (i = 1; i < l; i++)
50 s[i] = next();
51 s[l] = '\0';
52 return l;
55 /* skip blanks */
56 static void nextskip(void)
58 int c;
59 do {
60 c = next();
61 } while (isspace(c));
62 back(c);
65 static int nextnum(void)
67 int c;
68 int n = 0;
69 int neg = 0;
70 nextskip();
71 while (1) {
72 c = next();
73 if (!n && c == '-') {
74 neg = 1;
75 continue;
77 if (!isdigit(c))
78 back(c);
79 if (c < 0 || !isdigit(c))
80 break;
81 n = n * 10 + c - '0';
83 return neg ? -n : n;
86 static int iseol(void)
88 int c;
89 do {
90 c = next();
91 } while (c == ' ');
92 if (c != '\n')
93 back(c);
94 return c == '\n';
97 /* skip until the end of line */
98 static void nexteol(void)
100 int c;
101 do {
102 c = next();
103 } while (c >= 0 && c != '\n');
106 static void nextword(char *s)
108 int c;
109 nextskip();
110 c = next();
111 while (c >= 0 && !isspace(c)) {
112 *s++ = c;
113 c = next();
115 if (c >= 0)
116 back(c);
117 *s = '\0';
120 static void postspline(int h1, int v1)
122 int h2, v2;
123 while (!iseol()) {
124 h2 = nextnum();
125 v2 = nextnum();
126 draws(h1, v1, h2, v2);
127 h1 = h2;
128 v1 = v2;
130 draws(h1, v1, 0, 0);
133 static void postdraw(void)
135 int h1, h2, v1, v2;
136 int c = next();
137 drawbeg();
138 switch (c) {
139 case 'l':
140 h1 = nextnum();
141 v1 = nextnum();
142 drawl(h1, v1);
143 break;
144 case 'c':
145 drawc(nextnum());
146 break;
147 case 'e':
148 h1 = nextnum();
149 v1 = nextnum();
150 drawe(h1, v1);
151 break;
152 case 'a':
153 h1 = nextnum();
154 v1 = nextnum();
155 h2 = nextnum();
156 v2 = nextnum();
157 drawa(h1, v1, h2, v2);
158 break;
159 case '~':
160 h1 = nextnum();
161 v1 = nextnum();
162 if (iseol())
163 drawl(h1, v1);
164 else
165 postspline(h1, v1);
166 break;
168 drawend();
169 nexteol();
172 static char devpath[PATHLEN] = "devutf";
174 static void postx(void)
176 char cmd[128];
177 char dev[128];
178 int pos;
179 nextword(cmd);
180 switch (cmd[0]) {
181 case 'f':
182 pos = nextnum();
183 nextword(dev);
184 dev_mnt(pos, dev, dev);
185 break;
186 case 'i':
187 dev_open(devpath);
188 break;
189 case 'T':
190 nextword(dev);
191 sprintf(devpath, "%s/font/dev%s", TROFFROOT, dev);
192 break;
193 case 's':
194 break;
195 case 'X':
196 break;
198 nexteol();
201 static void postcmd(int c)
203 char cs[GNLEN];
204 if (isdigit(c)) {
205 outrel((c - '0') * 10 + next() - '0', 0);
206 nextutf8(cs);
207 outc(cs);
208 return;
210 switch (c) {
211 case 's':
212 outsize(nextnum());
213 break;
214 case 'f':
215 outfont(nextnum());
216 break;
217 case 'H':
218 outh(nextnum());
219 break;
220 case 'V':
221 outv(nextnum());
222 break;
223 case 'h':
224 outrel(nextnum(), 0);
225 break;
226 case 'v':
227 outrel(0, nextnum());
228 break;
229 case 'c':
230 nextutf8(cs);
231 outc(cs);
232 break;
233 case 'N':
234 nextnum();
235 break;
236 case 'C':
237 nextword(cs);
238 outc(cs);
239 break;
240 case 'p':
241 if (o_pg)
242 ps_pageend(o_pg);
243 o_pg = nextnum();
244 ps_pagebeg(o_pg);
245 outpage();
246 break;
247 case 'w':
248 break;
249 case 'n':
250 nextnum();
251 nextnum();
252 break;
253 case 'D':
254 postdraw();
255 break;
256 case 'x':
257 postx();
258 break;
259 case '#':
260 nexteol();
261 break;
262 default:
263 fprintf(stderr, "unknown command: %c\n", c);
267 static void post(void)
269 int c;
270 while ((c = next()) >= 0)
271 if (!isspace(c))
272 postcmd(c);
273 if (o_pg)
274 ps_pageend(o_pg);
277 int main(void)
279 ps_header();
280 post();
281 ps_trailer(o_pg, o_fonts);
282 return 0;