This repository has been archived by the owner on Sep 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathu2ps_pswr.c
132 lines (107 loc) · 2.54 KB
/
u2ps_pswr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "config.h"
#include "warn.h"
/* PostScript writer.
The term code outputs utf-8 characters one by one, intermixed with
commands. To get valid postscript, the characters must be grouped
with "(" and ")u", and the commands must be properly spaced.
Output lines are wrapped if they become too long.
This is independent from logical lines in the text. */
#define PSLINE 100
extern FILE* output;
enum psmode { NOTHING = 0, COMMAND, UNISTRING, BADSTRING } state = NOTHING;
static int pscol = 0;
void pswrite(const char* string, int len)
{
pscol += fwrite(string, 1, len, output);
if(len && string[len-1] == '\n') pscol = 0;
}
void psputs(const char* string)
{
pswrite(string, strlen(string));
}
void psmode(enum psmode newstate)
{
if(newstate == state && newstate != COMMAND)
return;
switch(state) {
case UNISTRING: psputs(")u"); state = COMMAND; break;
case BADSTRING: psputs(")x"); state = COMMAND; break;
default: break;
};
/* possible pairs here:
NOTHING -> COMMAND
NOTHING -> *STRING
COMMAND -> *STRING
COMMAND -> NOTHING
COMMAND -> COMMAND */
if(state && newstate)
psputs(" ");
else if(!newstate)
psputs("\n");
if(newstate == UNISTRING || newstate == BADSTRING)
psputs("(");
state = newstate;
}
void psnl(int nl)
{
int i;
psmode(NOTHING);
for(i = 0; i < nl; i++) psputs("\n");
}
void psline(const char* fmt, ...)
{
va_list ap;
psmode(NOTHING);
va_start(ap, fmt);
vfprintf(output, fmt, ap);
va_end(ap);
}
void pscmd(const char* fmt, ...)
{
int nl = (*fmt == '!'); if(nl) fmt++;
if(!nl && pscol >= PSLINE) psnl(0);
va_list ap;
psmode(COMMAND);
va_start(ap, fmt);
pscol += vfprintf(output, fmt, ap);
va_end(ap);
if(nl) psnl(0);
}
/* Valid utf-8 is written as is, but invalid input gets converted
into ???? so that the ps part would not have to deal with
encoding errors. */
void psbad(int len)
{
static char badstring[] = "??????";
int max = sizeof(badstring);
psmode(BADSTRING);
pswrite(badstring, len < max ? len : max);
}
void psuni(char* ptr, int len)
{
psmode(UNISTRING);
if(*ptr == '(' || *ptr == ')' || *ptr == '\\')
psputs("\\");
pswrite(ptr, len);
}
/* This is only used for stuff like headings and line numbers,
not for the text. */
void psstr(const char* str)
{
const char* p = str;
const char* e;
psmode(COMMAND);
psputs("(");
while((e = strpbrk(p, "()\\"))) {
pswrite(p, e - p);
psputs("\\");
pswrite(e, 1);
p = e + 1;
} if(*p)
psputs(p);
psputs(")");
state = NOTHING;
}