Annotation of mandoc/term_ps.c, Revision 1.2
1.2 ! kristaps 1: /* $Id: term_ps.c,v 1.1 2010/06/08 13:22:37 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:
! 71: static void
! 72: ps_end(struct termp *p)
! 73: {
! 74:
! 75: printf("%s\n", "%%EOF");
! 76: }
! 77:
! 78:
! 79: static void
! 80: ps_begin(struct termp *p)
! 81: {
! 82:
! 83: /*
! 84: * Emit the standard PostScript prologue, set our initial page
! 85: * position, then run pageopen() on the initial page.
! 86: */
! 87:
! 88: printf("%s\n", "%!PS");
! 89: printf("%s\n", "/Courier");
! 90: printf("%s\n", "10 selectfont");
! 91:
! 92: p->engine.ps.pspage = 1;
! 93: p->engine.ps.psstate = 0;
! 94: ps_pageopen(p);
! 95: }
! 96:
! 97:
! 98: static void
! 99: ps_letter(struct termp *p, char c)
! 100: {
! 101:
! 102: if ( ! (PS_INLINE & p->engine.ps.psstate)) {
! 103: /*
! 104: * If we're not in a PostScript "word" context, then
! 105: * open one now at the current cursor.
! 106: */
! 107: printf("%zu %zu moveto\n",
! 108: p->engine.ps.pscol,
! 109: p->engine.ps.psrow);
! 110: putchar('(');
! 111: p->engine.ps.psstate |= PS_INLINE;
! 112: }
! 113:
! 114: /*
! 115: * We need to escape these characters as per the PostScript
! 116: * specification. We would also escape non-graphable characters
! 117: * (like tabs), but none of them would get to this point and
! 118: * it's superfluous to abort() on them.
! 119: */
! 120:
! 121: switch (c) {
! 122: case ('('):
! 123: /* FALLTHROUGH */
! 124: case (')'):
! 125: /* FALLTHROUGH */
! 126: case ('\\'):
! 127: putchar('\\');
! 128: break;
! 129: default:
! 130: break;
! 131: }
! 132:
! 133: /* Write the character and adjust where we are on the page. */
! 134: putchar(c);
! 135: p->engine.ps.pscol += PS_CHAR_WIDTH;
! 136: }
! 137:
! 138:
! 139: /*
! 140: * Open a page. This is only used for -Tps at the moment. It opens a
! 141: * page context, printing the header and the footer. THE OUTPUT BUFFER
! 142: * MUST BE EMPTY. If it is not, output will ghost on the next line and
! 143: * we'll be all gross and out of state.
! 144: */
! 145: static void
! 146: ps_pageopen(struct termp *p)
! 147: {
! 148:
! 149: assert(TERMTYPE_PS == p->type);
! 150: assert(0 == p->engine.ps.psstate);
! 151:
! 152: p->engine.ps.pscol = PS_CHAR_LEFT;
! 153: p->engine.ps.psrow = PS_CHAR_TOPMARG;
! 154: p->engine.ps.psstate |= PS_MARGINS;
! 155:
! 156: (*p->headf)(p, p->argf);
! 157: (*p->endline)(p);
! 158:
! 159: p->engine.ps.psstate &= ~PS_MARGINS;
! 160: assert(0 == p->engine.ps.psstate);
! 161:
! 162: p->engine.ps.pscol = PS_CHAR_LEFT;
! 163: p->engine.ps.psrow = PS_CHAR_BOTMARG;
! 164: p->engine.ps.psstate |= PS_MARGINS;
! 165:
! 166: (*p->footf)(p, p->argf);
! 167: (*p->endline)(p);
! 168:
! 169: p->engine.ps.psstate &= ~PS_MARGINS;
! 170: assert(0 == p->engine.ps.psstate);
! 171:
! 172: p->engine.ps.pscol = PS_CHAR_LEFT;
! 173: p->engine.ps.psrow = PS_CHAR_TOP;
! 174:
! 175: }
! 176:
! 177:
! 178: static void
! 179: ps_advance(struct termp *p, size_t len)
! 180: {
! 181:
! 182: if (PS_INLINE & p->engine.ps.psstate) {
! 183: /* Dump out any existing line scope. */
! 184: printf(") show\n");
! 185: p->engine.ps.psstate &= ~PS_INLINE;
! 186: }
! 187:
! 188: p->engine.ps.pscol += len ? len * PS_CHAR_WIDTH : 0;
! 189: }
! 190:
! 191:
! 192: static void
! 193: ps_endline(struct termp *p)
! 194: {
! 195:
! 196: if (PS_INLINE & p->engine.ps.psstate) {
! 197: printf(") show\n");
! 198: p->engine.ps.psstate &= ~PS_INLINE;
! 199: }
! 200:
! 201: if (PS_MARGINS & p->engine.ps.psstate)
! 202: return;
! 203:
! 204: p->engine.ps.pscol = PS_CHAR_LEFT;
! 205: if (p->engine.ps.psrow >= PS_CHAR_HEIGHT + PS_CHAR_BOT) {
! 206: p->engine.ps.psrow -= PS_CHAR_HEIGHT;
! 207: return;
! 208: }
! 209:
! 210: /*
! 211: * XXX: can't run pageopen() until we're certain a flushln() has
! 212: * occured, else the buf will reopen in an awkward state on the
! 213: * next line.
! 214: */
! 215: printf("showpage\n");
! 216: p->engine.ps.psrow = PS_CHAR_TOP;
1.1 kristaps 217: }
CVSweb