1 /* converting scales */
2 #define SC_IN (dev_res) /* inch in units */
3 #define SC_PT (SC_IN / 72) /* point in units */
4 #define SC_EM (n_s * SC_IN / 72)
5 #define SC_DW (SC_EM / 3) /* default width */
6 #define SC_HT (n_s * SC_PT) /* character height */
8 /* predefined array limits */
9 #define PATHLEN 1024 /* path length */
10 #define NFILES 16 /* number of input files */
11 #define NFONTS 32 /* number of fonts */
12 #define NGLYPHS 1024 /* glyphs in fonts */
13 #define NLIGS 32 /* number of font ligatures */
14 #define NKERNS 512 /* number of font pairwise kerning pairs */
15 #define FNLEN 32 /* font name length */
16 #define NMLEN 32 /* macro/register/environment/glyph name length */
17 #define GNLEN NMLEN /* glyph name length */
18 #define RNLEN NMLEN /* register/macro name */
19 #define ILNLEN 1000 /* line limit of input files */
20 #define LNLEN 4000 /* line buffer length (ren.c/out.c) */
21 #define NWORDS 256 /* number of words in line buffer */
22 #define NARGS 16 /* number of macro arguments */
23 #define NPREV 16 /* environment stack depth */
24 #define NTRAPS 1024 /* number of traps per page */
25 #define NIES 128 /* number of nested .ie commands */
26 #define NTABS 16 /* number of tab stops */
27 #define NTR 512 /* number of character translations (.tr) */
28 #define NSSTR 32 /* number of nested sstr_push() calls */
29 #define NFIELDS 32 /* number of fields */
30 #define MAXFRAC 100000 /* maximum value of the fractional part */
31 #define LIGLEN 4 /* length of ligatures */
33 /* escape sequences */
34 #define ESC_Q "bCDhHlLNoSvwxX" /* \X'ccc' quoted escape sequences */
35 #define ESC_P "*fgkmns" /* \Xc \X(cc \X[ccc] escape sequences */
37 #define MIN(a, b) ((a) < (b) ? (a) : (b))
38 #define MAX(a, b) ((a) < (b) ? (b) : (a))
39 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
41 /* special characters */
42 extern int c_ec
; /* escape character (\) */
43 extern int c_cc
; /* basic control character (.) */
44 extern int c_c2
; /* no-break control character (') */
45 #define c_ni 4 /* non-interpreted copy mode escape */
46 #define c_hc env_hc()/* hyphenation character */
47 #define c_mc env_mc()/* margin character (.mc) */
51 /* number registers */
52 int num_get(int id
, int inc
);
53 void num_set(int id
, int val
);
54 void num_inc(int id
, int val
);
56 char *num_str(int id
);
57 char *num_getfmt(int id
);
58 void num_setfmt(int id
, char *fmt
);
60 int eval(char *s
, int unit
);
61 int eval_up(char **s
, int unit
);
62 int eval_re(char *s
, int orig
, int unit
);
64 /* string registers */
65 void str_set(int id
, char *s
);
66 void str_dset(int id
, void *d
);
67 char *str_get(int id
);
68 void *str_dget(int id
);
70 void str_rn(int src
, int dst
);
72 /* saving and restoring registers before and after printing diverted lines */
79 struct adj
*env_adj(void);
84 int tab_next(int pos
);
85 int tab_type(int pos
);
87 /* device related variables */
94 char name
[GNLEN
]; /* name of the glyph */
95 char id
[GNLEN
]; /* device-dependent glyph identifier */
96 struct font
*font
; /* glyph font */
97 int wid
; /* character width */
98 int type
; /* character type; ascender/descender */
103 char fontname
[FNLEN
];
104 struct glyph glyphs
[NGLYPHS
];
108 int cs
, bd
; /* for .cs and .bd requests */
109 char c
[NGLYPHS
][GNLEN
]; /* character names in charset */
110 struct glyph
*g
[NGLYPHS
]; /* character glyphs in charset */
111 int n
; /* number of characters in charset */
113 char lig
[NLIGS
][LIGLEN
* GNLEN
];
115 /* glyph list based on the first character of glyph names */
116 int head
[256]; /* glyph list head */
117 int next
[NGLYPHS
]; /* next item in glyph list */
118 /* kerning pair list per glyph */
119 int knhead
[NGLYPHS
]; /* kerning pairs of glyphs[] */
120 int knnext
[NKERNS
]; /* next item in knhead[] list */
121 int knpair
[NKERNS
]; /* kerning pair 2nd glyphs */
122 int knval
[NKERNS
]; /* font pairwise kerning value */
123 int knn
; /* number of kerning pairs */
126 /* output device functions */
127 int dev_open(char *path
);
128 void dev_close(void);
129 int dev_mnt(int pos
, char *id
, char *name
);
130 int dev_pos(char *id
);
131 struct font
*dev_font(int pos
);
132 void dev_setcs(int fn
, int cs
);
133 int dev_getcs(int fn
);
134 void dev_setbd(int fn
, int bd
);
135 int dev_getbd(int fn
);
137 /* font-related functions */
138 struct font
*font_open(char *path
);
139 void font_close(struct font
*fn
);
140 struct glyph
*font_glyph(struct font
*fn
, char *id
);
141 struct glyph
*font_find(struct font
*fn
, char *name
);
142 int font_lig(struct font
*fn
, char **c
, int n
);
143 int font_kern(struct font
*fn
, char *c1
, char *c2
);
145 /* glyph handling functions */
146 struct glyph
*dev_glyph(char *c
, int fn
);
147 struct glyph
*dev_glyph_byid(char *id
, int fn
);
148 int charwid(int fn
, int sz
, int wid
);
149 int spacewid(int fn
, int sz
);
150 int charwid_base(int fn
, int sz
, int wid
);
152 /* different layers of neatroff */
153 int in_next(void); /* input layer */
154 int cp_next(void); /* copy-mode layer */
155 int tr_next(void); /* troff layer */
157 void in_push(char *s
, char **args
);
158 void in_pushnl(char *s
, char **args
);
159 void in_so(char *path
); /* .so request */
160 void in_nx(char *path
); /* .nx request */
161 void in_ex(void); /* .nx request */
162 void in_lf(char *path
, int ln
); /* .lf request */
163 void in_queue(char *path
); /* .ex request */
164 char *in_arg(int i
); /* look up argument */
165 int in_nargs(void); /* number of arguments */
166 void in_back(int c
); /* push back input character */
167 int in_top(void); /* the first pushed-back character */
168 char *in_filename(void); /* current filename */
169 int in_lnum(void); /* current line number */
171 void cp_blk(int skip
); /* skip or read the next line or block */
172 void cp_wid(int enable
); /* control inlining \w requests */
173 #define cp_back in_back /* cp.c is stateless */
174 void tr_first(void); /* read until the first non-command line */
176 /* character translation (.tr) */
177 void tr_add(char *c1
, char *c2
);
178 char *tr_map(char *c
);
180 /* variable length string buffer */
182 char *s
; /* allocated buffer */
183 int sz
; /* buffer size */
184 int n
; /* length of the string stored in s */
187 void sbuf_init(struct sbuf
*sbuf
);
188 void sbuf_done(struct sbuf
*sbuf
);
189 char *sbuf_buf(struct sbuf
*sbuf
);
190 void sbuf_add(struct sbuf
*sbuf
, int c
);
191 void sbuf_append(struct sbuf
*sbuf
, char *s
);
192 void sbuf_printf(struct sbuf
*sbuf
, char *s
, ...);
193 void sbuf_putnl(struct sbuf
*sbuf
);
194 void sbuf_cut(struct sbuf
*sbuf
, int n
);
195 int sbuf_len(struct sbuf
*sbuf
);
196 int sbuf_empty(struct sbuf
*sbuf
);
201 int f
, s
, m
; /* the last output font and size */
202 int r_f
, r_s
, r_m
; /* current font and size; use n_f and n_s if -1 */
203 int part
; /* partial input (\c) */
204 int els_neg
, els_pos
; /* extra line spacing */
205 int h
, v
; /* buffer vertical and horizontal positions */
206 int ct
, sb
, st
; /* \w registers */
207 /* saving previous characters added via wb_put() */
208 char prev_c
[LIGLEN
][GNLEN
];
209 int prev_l
[LIGLEN
]; /* sbuf_len(&wb->sbuf) before wb_put() calls */
210 int prev_h
[LIGLEN
]; /* wb->h before wb_put() calls */
211 int prev_n
; /* number of characters in prev_c[] */
212 int prev_ll
; /* sbuf_len(&wb->sbuf) after the last wb_put() */
215 void wb_init(struct wb
*wb
);
216 void wb_done(struct wb
*wb
);
217 void wb_hmov(struct wb
*wb
, int n
);
218 void wb_vmov(struct wb
*wb
, int n
);
219 void wb_els(struct wb
*wb
, int els
);
220 void wb_etc(struct wb
*wb
, char *x
);
221 void wb_put(struct wb
*wb
, char *c
);
222 int wb_part(struct wb
*wb
);
223 void wb_setpart(struct wb
*wb
);
224 void wb_drawl(struct wb
*wb
, int h
, int v
);
225 void wb_drawc(struct wb
*wb
, int r
);
226 void wb_drawe(struct wb
*wb
, int h
, int v
);
227 void wb_drawa(struct wb
*wb
, int h1
, int v1
, int h2
, int v2
);
228 void wb_drawxbeg(struct wb
*wb
, int c
);
229 void wb_drawxdot(struct wb
*wb
, int h
, int v
);
230 void wb_drawxend(struct wb
*wb
);
231 void wb_cat(struct wb
*wb
, struct wb
*src
);
232 int wb_hyph(struct wb
*wb
, int w
, struct wb
*w1
, struct wb
*w2
, int flg
);
233 int wb_wid(struct wb
*wb
);
234 int wb_empty(struct wb
*wb
);
235 int wb_eos(struct wb
*wb
);
236 void wb_wconf(struct wb
*wb
, int *ct
, int *st
, int *sb
);
237 int wb_lig(struct wb
*wb
, char *c
);
238 int wb_kern(struct wb
*wb
, char *c
);
240 /* hyphenation flags */
241 #define HY_MASK 0x0f /* enable hyphenation */
242 #define HY_LAST 0x02 /* do not hyphenate last lines */
243 #define HY_FINAL 0x04 /* do not hyphenate the final character */
244 #define HY_FIRSTTWO 0x08 /* do not hyphenate the first two characters */
245 #define HY_ANY 0x10 /* break at any possible position */
247 void hyphenate(char *hyphs
, char *word
);
255 struct adj
*adj_alloc(void);
256 void adj_free(struct adj
*adj
);
257 int adj_fill(struct adj
*adj
, int ad_b
, int fill
, int hyph
, struct sbuf
*dst
,
258 int *ll
, int *in
, int *ti
, int *els_neg
, int *els_pos
);
259 int adj_full(struct adj
*adj
, int fill
);
260 int adj_empty(struct adj
*adj
, int fill
);
261 int adj_wid(struct adj
*adj
);
262 void adj_swid(struct adj
*adj
, int swid
);
263 void adj_ll(struct adj
*adj
, int ll
);
264 void adj_in(struct adj
*adj
, int in
);
265 void adj_ti(struct adj
*adj
, int ti
);
266 void adj_wb(struct adj
*adj
, struct wb
*wb
);
267 void adj_nl(struct adj
*adj
);
268 void adj_sp(struct adj
*adj
);
269 void adj_nonl(struct adj
*adj
);
272 int render(void); /* the main loop */
273 int ren_char(struct wb
*wb
, int (*next
)(void), void (*back
)(int));
274 int ren_wid(int (*next
)(void), void (*back
)(int));
275 void ren_tl(int (*next
)(void), void (*back
)(int));
276 void ren_hline(struct wb
*wb
, int l
, char *c
); /* horizontal line */
277 void ren_hlcmd(struct wb
*wb
, char *arg
); /* \l */
278 void ren_vlcmd(struct wb
*wb
, char *arg
); /* \L */
279 void ren_bcmd(struct wb
*wb
, char *arg
); /* \b */
280 void ren_ocmd(struct wb
*wb
, char *arg
); /* \o */
281 void ren_dcmd(struct wb
*wb
, char *arg
); /* \D */
284 void out_line(char *s
); /* output rendered line */
285 void out(char *s
, ...); /* output troff cmd */
288 void tr_ab(char **args
);
289 void tr_bp(char **args
);
290 void tr_br(char **args
);
291 void tr_ce(char **args
);
292 void tr_ch(char **args
);
293 void tr_di(char **args
);
294 void tr_divbeg(char **args
);
295 void tr_divend(char **args
);
296 void tr_dt(char **args
);
297 void tr_em(char **args
);
298 void tr_ev(char **args
);
299 void tr_fc(char **args
);
300 void tr_fi(char **args
);
301 void tr_fp(char **args
);
302 void tr_ft(char **args
);
303 void tr_hw(char **args
);
304 void tr_in(char **args
);
305 void tr_ll(char **args
);
306 void tr_mk(char **args
);
307 void tr_ne(char **args
);
308 void tr_nf(char **args
);
309 void tr_ns(char **args
);
310 void tr_os(char **args
);
311 void tr_pn(char **args
);
312 void tr_ps(char **args
);
313 void tr_rs(char **args
);
314 void tr_rt(char **args
);
315 void tr_sp(char **args
);
316 void tr_sv(char **args
);
317 void tr_ta(char **args
);
318 void tr_ti(char **args
);
319 void tr_wh(char **args
);
320 void tr_eject(char **args
);
325 void errmsg(char *msg
, ...);
327 int utf8next(char *s
, int (*next
)(void));
328 int utf8read(char **s
, char *d
);
329 int charnext(char *c
, int (*next
)(void), void (*back
)(int));
330 int charread(char **s
, char *c
);
331 int charnext_delim(char *c
, int (*next
)(void), void (*back
)(int), char *delim
);
332 void charnext_str(char *d
, char *c
);
333 void argnext(char *d
, int cmd
, int (*next
)(void), void (*back
)(int));
334 void argread(char **sp
, char *d
, int cmd
);
335 int escread(char **s
, char *d
);
336 /* string streams; nested next()/back() interface for string buffers */
337 void sstr_push(char *s
);
338 char *sstr_pop(void);
340 void sstr_back(int c
);
342 /* internal commands */
343 #define TR_DIVBEG "\07<" /* diversion begins */
344 #define TR_DIVEND "\07>" /* diversion ends */
345 #define TR_EJECT "\07P" /* page eject */
347 /* mapping register, macro and environment names to numbers */
348 #define NREGS (1 << 16)
349 #define NREGS2 (NREGS * 2)
350 #define REG(c1, c2) ((c1) * 256 + (c2))
353 char *map_name(int id
);
356 #define CLR_R(c) (((c) >> 16) & 0xff)
357 #define CLR_G(c) (((c) >> 8) & 0xff)
358 #define CLR_B(c) ((c) & 0xff)
359 #define CLR_RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
361 char *clr_str(int c
);
362 int clr_get(char *s
);
364 /* builtin number registers; n_X for .X register */
365 #define n_a (*nreg(REG('.', 'a')))
366 #define n_cp (*nreg(REG('.', 'C')))
367 #define n_d (*nreg(REG('.', 'd')))
368 #define n_f (*nreg(REG('.', 'f')))
369 #define n_h (*nreg(REG('.', 'h')))
370 #define n_i (*nreg(REG('.', 'i')))
371 #define n_it (*nreg(map(".it"))) /* .it trap macro */
372 #define n_itn (*nreg(map(".itn"))) /* .it lines left */
373 #define n_j (*nreg(REG('.', 'j')))
374 #define n_l (*nreg(REG('.', 'l')))
375 #define n_L (*nreg(REG('.', 'L')))
376 #define n_n (*nreg(REG('.', 'n')))
377 #define n_nI (*nreg(map(".nI"))) /* i for .nm */
378 #define n_nm (*nreg(map(".nm"))) /* .nm enabled */
379 #define n_nM (*nreg(map(".nM"))) /* m for .nm */
380 #define n_nn (*nreg(map(".nn"))) /* remaining .nn */
381 #define n_nS (*nreg(map(".nS"))) /* s for .nm */
382 #define n_m (*nreg(REG('.', 'm')))
383 #define n_mc (*nreg(map(".mc"))) /* .mc enabled */
384 #define n_mcn (*nreg(map(".mcn"))) /* .mc distance */
385 #define n_o (*nreg(REG('.', 'o')))
386 #define n_p (*nreg(REG('.', 'p')))
387 #define n_s (*nreg(REG('.', 's')))
388 #define n_u (*nreg(REG('.', 'u')))
389 #define n_v (*nreg(REG('.', 'v')))
390 #define n_ct (*nreg(REG('c', 't')))
391 #define n_dl (*nreg(REG('d', 'l')))
392 #define n_dn (*nreg(REG('d', 'n')))
393 #define n_ln (*nreg(REG('l', 'n')))
394 #define n_nl (*nreg(REG('n', 'l')))
395 #define n_sb (*nreg(REG('s', 'b')))
396 #define n_st (*nreg(REG('s', 't')))
397 #define n_pg (*nreg(REG('%', '\0'))) /* % */
398 #define n_lb (*nreg(REG(0, 'b'))) /* input line beg */
399 #define n_ce (*nreg(REG(0, 'c'))) /* .ce remaining */
400 #define n_f0 (*nreg(REG(0, 'f'))) /* last .f */
401 #define n_lg (*nreg(REG(0, 'g'))) /* .lg mode */
402 #define n_hy (*nreg(REG(0, 'h'))) /* .hy mode */
403 #define n_i0 (*nreg(REG(0, 'i'))) /* last .i */
404 #define n_kn (*nreg(REG(0, 'k'))) /* .kn mode */
405 #define n_l0 (*nreg(REG(0, 'l'))) /* last .l */
406 #define n_L0 (*nreg(REG(0, 'L'))) /* last .L */
407 #define n_m0 (*nreg(REG(0, 'm'))) /* last .m */
408 #define n_mk (*nreg(REG(0, 'M'))) /* .mk internal register */
409 #define n_na (*nreg(REG(0, 'n'))) /* .na mode */
410 #define n_ns (*nreg(REG(0, 'N'))) /* .ns mode */
411 #define n_o0 (*nreg(REG(0, 'o'))) /* last .o */
412 #define n_ss (*nreg(REG(0, 'p'))) /* .ss value */
413 #define n_s0 (*nreg(REG(0, 's'))) /* last .s */
414 #define n_sv (*nreg(REG(0, 'S'))) /* .sv value */
415 #define n_lt (*nreg(REG(0, 't'))) /* .lt value */
416 #define n_t0 (*nreg(REG(0, 'T'))) /* previous .lt value */
417 #define n_v0 (*nreg(REG(0, 'v'))) /* last .v */
419 /* functions for implementing read-only registers */
420 int f_nexttrap(void); /* .t */
421 int f_divreg(void); /* .z */
422 int f_hpos(void); /* .k */