Annotation of mandoc/term_ps.c, Revision 1.3
1.3 ! kristaps 1: /* $Id: term_ps.c,v 1.2 2010/06/08 15:00:17 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #ifdef HAVE_CONFIG_H
18: #include "config.h"
19: #endif
20:
1.2 kristaps 21: #include <assert.h>
22: #include <stdio.h>
1.1 kristaps 23: #include <stdlib.h>
24:
25: #include "out.h"
26: #include "main.h"
27: #include "term.h"
28:
1.2 kristaps 29: #define PS_CHAR_WIDTH 6
30: #define PS_CHAR_HEIGHT 12
31: #define PS_CHAR_TOPMARG (792 - 24)
32: #define PS_CHAR_TOP (PS_CHAR_TOPMARG - 36)
33: #define PS_CHAR_LEFT 36
34: #define PS_CHAR_BOTMARG 24
35: #define PS_CHAR_BOT (PS_CHAR_BOTMARG + 36)
36:
37: static void ps_letter(struct termp *, char);
38: static void ps_begin(struct termp *);
39: static void ps_end(struct termp *);
40: static void ps_pageopen(struct termp *);
41: static void ps_advance(struct termp *, size_t);
42: static void ps_endline(struct termp *);
43:
44:
1.1 kristaps 45: void *
46: ps_alloc(void)
47: {
48: struct termp *p;
49:
50: if (NULL == (p = term_alloc(TERMENC_ASCII)))
51: return(NULL);
52:
53: p->type = TERMTYPE_PS;
1.2 kristaps 54: p->letter = ps_letter;
55: p->begin = ps_begin;
56: p->end = ps_end;
57: p->advance = ps_advance;
58: p->endline = ps_endline;
1.1 kristaps 59: return(p);
60: }
61:
62:
63: void
64: ps_free(void *arg)
65: {
66:
67: term_free((struct termp *)arg);
1.2 kristaps 68: }
69:
70:
1.3 ! kristaps 71: /* ARGSUSED */
1.2 kristaps 72: static void
73: ps_end(struct termp *p)
74: {
75:
76: printf("%s\n", "%%EOF");
77: }
78:
79:
80: static void
81: ps_begin(struct termp *p)
82: {
83:
84: /*
85: * Emit the standard PostScript prologue, set our initial page
86: * position, then run pageopen() on the initial page.
87: */
88:
89: printf("%s\n", "%!PS");
90: printf("%s\n", "/Courier");
91: printf("%s\n", "10 selectfont");
92:
93: p->engine.ps.pspage = 1;
94: p->engine.ps.psstate = 0;
95: ps_pageopen(p);
96: }
97:
98:
99: static void
100: ps_letter(struct termp *p, char c)
101: {
102:
103: if ( ! (PS_INLINE & p->engine.ps.psstate)) {
104: /*
105: * If we're not in a PostScript "word" context, then
106: * open one now at the current cursor.
107: */
108: printf("%zu %zu moveto\n",
109: p->engine.ps.pscol,
110: p->engine.ps.psrow);
111: putchar('(');
112: p->engine.ps.psstate |= PS_INLINE;
113: }
114:
115: /*
116: * We need to escape these characters as per the PostScript
117: * specification. We would also escape non-graphable characters
118: * (like tabs), but none of them would get to this point and
119: * it's superfluous to abort() on them.
120: */
121:
122: switch (c) {
123: case ('('):
124: /* FALLTHROUGH */
125: case (')'):
126: /* FALLTHROUGH */
127: case ('\\'):
128: putchar('\\');
129: break;
130: default:
131: break;
132: }
133:
134: /* Write the character and adjust where we are on the page. */
135: putchar(c);
136: p->engine.ps.pscol += PS_CHAR_WIDTH;
137: }
138:
139:
140: /*
141: * Open a page. This is only used for -Tps at the moment. It opens a
142: * page context, printing the header and the footer. THE OUTPUT BUFFER
143: * MUST BE EMPTY. If it is not, output will ghost on the next line and
144: * we'll be all gross and out of state.
145: */
146: static void
147: ps_pageopen(struct termp *p)
148: {
149:
150: assert(TERMTYPE_PS == p->type);
151: assert(0 == p->engine.ps.psstate);
152:
153: p->engine.ps.pscol = PS_CHAR_LEFT;
154: p->engine.ps.psrow = PS_CHAR_TOPMARG;
155: p->engine.ps.psstate |= PS_MARGINS;
156:
157: (*p->headf)(p, p->argf);
158: (*p->endline)(p);
159:
160: p->engine.ps.psstate &= ~PS_MARGINS;
161: assert(0 == p->engine.ps.psstate);
162:
163: p->engine.ps.pscol = PS_CHAR_LEFT;
164: p->engine.ps.psrow = PS_CHAR_BOTMARG;
165: p->engine.ps.psstate |= PS_MARGINS;
166:
167: (*p->footf)(p, p->argf);
168: (*p->endline)(p);
169:
170: p->engine.ps.psstate &= ~PS_MARGINS;
171: assert(0 == p->engine.ps.psstate);
172:
173: p->engine.ps.pscol = PS_CHAR_LEFT;
174: p->engine.ps.psrow = PS_CHAR_TOP;
175:
176: }
177:
178:
179: static void
180: ps_advance(struct termp *p, size_t len)
181: {
182:
183: if (PS_INLINE & p->engine.ps.psstate) {
184: /* Dump out any existing line scope. */
185: printf(") show\n");
186: p->engine.ps.psstate &= ~PS_INLINE;
187: }
188:
189: p->engine.ps.pscol += len ? len * PS_CHAR_WIDTH : 0;
190: }
191:
192:
193: static void
194: ps_endline(struct termp *p)
195: {
196:
197: if (PS_INLINE & p->engine.ps.psstate) {
198: printf(") show\n");
199: p->engine.ps.psstate &= ~PS_INLINE;
200: }
201:
202: if (PS_MARGINS & p->engine.ps.psstate)
203: return;
204:
205: p->engine.ps.pscol = PS_CHAR_LEFT;
206: if (p->engine.ps.psrow >= PS_CHAR_HEIGHT + PS_CHAR_BOT) {
207: p->engine.ps.psrow -= PS_CHAR_HEIGHT;
208: return;
209: }
210:
211: /*
212: * XXX: can't run pageopen() until we're certain a flushln() has
213: * occured, else the buf will reopen in an awkward state on the
214: * next line.
215: */
216: printf("showpage\n");
217: p->engine.ps.psrow = PS_CHAR_TOP;
1.1 kristaps 218: }
CVSweb