Make ps_glyph_to_unicode() take a glyph index instead of a glyph name.
[sgt/halibut] / in_pf.c
1 #include <stdio.h>
2 #include "halibut.h"
3 #include "paper.h"
4
5 static char *pf_read_token(FILE *fp);
6
7 void read_pfa_file(input *in) {
8 rdstringc rsc = { 0, 0, NULL };
9 char *p;
10 size_t len;
11 char *fontname;
12 font_info *fi;
13 FILE *fp = in->currfp;
14 int c;
15
16 in->pos.line = 0;
17 do {
18 c = fgetc(fp);
19 if (c == EOF) {
20 sfree(rsc.text);
21 error(err_pfeof, &in->pos);
22 return;
23 }
24 rdaddc(&rsc, c);
25 } while (c != 012 && c != 015);
26 p = rsc.text;
27 if ((p = strchr(p, ':')) == NULL) {
28 sfree(rsc.text);
29 error(err_pfhead, &in->pos);
30 return;
31 }
32 p++;
33 p += strspn(p, " \t");
34 len = strcspn(p, " \t");
35 fontname = snewn(len + 1, char);
36 memcpy(fontname, p, len);
37 fontname[len] = 0;
38 sfree(rsc.text);
39
40 for (fi = all_fonts; fi; fi = fi->next) {
41 if (strcmp(fi->name, fontname) == 0) {
42 fi->fp = in->currfp;
43 fi->pos = in->pos;
44 fi->length1 = fi->length2 = 0;
45 sfree(fontname);
46 return;
47 }
48 }
49 error(err_pfnoafm, &in->pos, fontname);
50 fclose(in->currfp);
51 sfree(fontname);
52 }
53
54 /*
55 * PostScript white space characters; PLRM3 table 3.1
56 */
57 static int pf_isspace(int c) {
58 return c == 000 || c == 011 || c == 012 || c == 014 || c == 015 ||
59 c == ' ';
60 }
61
62 /*
63 * PostScript special characters; PLRM3 page 27
64 */
65 static int pf_isspecial(int c) {
66 return c == '(' || c == ')' || c == '<' || c == '>' || c == '[' ||
67 c == ']' || c == '{' || c == '}' || c == '/' || c == '%';
68 }
69
70 static long pf_length1(font_info *fi) {
71 FILE *fp = fi->fp;
72 char *tok;
73
74 rewind(fp);
75 tok = pf_read_token(fp);
76 while (tok && strcmp(tok, "eexec") != 0) {
77 sfree(tok);
78 tok = pf_read_token(fp);
79 }
80 if (tok == NULL) {
81 error(err_pfeof, &fi->pos);
82 return 0;
83 }
84 return ftell(fp);
85 }
86
87 /*
88 * Return the initial, unencrypted, part of a font.
89 */
90 void pf_part1(font_info *fi, char **bufp, size_t *lenp) {
91 FILE *fp = fi->fp;
92
93 if (fi->length1 == 0)
94 fi->length1 = pf_length1(fi);
95 rewind(fp);
96 *bufp = snewn(fi->length1, char);
97 *lenp = fi->length1;
98 if (fread(*bufp, 1, fi->length1, fp) != (size_t)fi->length1) {
99 error(err_pfeof, &fi->pos);
100 *lenp = 0;
101 sfree(*bufp);
102 *bufp = NULL;
103 }
104 }
105
106 static int hexval(char c) {
107 if (c >= '0' && c <= '9') return c - '0';
108 if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
109 if (c >= 'a' && c <= 'f') return c - 'a' + 0xa;
110 return 0;
111 }
112
113 /*
114 * Return the middle, encrypted, part of a font.
115 */
116 void pf_part2(font_info *fi, char **bufp, size_t *lenp) {
117 FILE *fp = fi->fp;
118 rdstringc rsc = { 0, 0, NULL };
119 char *tok, *p;
120 unsigned char nybble;
121 int havenybble = 0;
122
123 if (fi->length1 == 0)
124 fi->length1 = pf_length1(fi);
125 fseek(fp, fi->length1, SEEK_SET);
126 tok = pf_read_token(fp);
127 while (tok && strcmp(tok, "cleartomark") != 0) {
128 for (p = tok; *p; p++) {
129 if (pf_isspace(*p)) continue;
130 if (!havenybble)
131 nybble = hexval(*p);
132 else
133 rdaddc(&rsc, (nybble << 4) | hexval(*p));
134 havenybble = !havenybble;
135 }
136 sfree(tok);
137 tok = pf_read_token(fp);
138 }
139 if (tok == NULL) {
140 error(err_pfeof, &fi->pos);
141 *bufp = NULL;
142 *lenp = 0;
143 }
144 *bufp = rsc.text;
145 /* Trim off the trailing zeroes */
146 if (rsc.pos >= 256)
147 *lenp = rsc.pos - 256;
148 else {
149 error(err_pfbad, &fi->pos);
150 *bufp = NULL;
151 *lenp = 0;
152 }
153 }
154
155 static char *pf_read_litstring(FILE *fp) {
156 rdstringc rsc = { 0, 0, NULL };
157 int depth = 1;
158 int c;
159
160 rdaddc(&rsc, '(');
161 do {
162 c = fgetc(fp);
163 switch (c) {
164 case '(':
165 depth++; break;
166 case ')':
167 depth--; break;
168 case '\\':
169 rdaddc(&rsc, '\\');
170 c = fgetc(fp);
171 break;
172 }
173 if (c != EOF) rdaddc(&rsc, c);
174 } while (depth > 0 && c != EOF);
175 return rsc.text;
176 }
177
178 static char *pf_read_hexstring(FILE *fp) {
179 rdstringc rsc = { 0, 0, NULL };
180 int c;
181
182 rdaddc(&rsc, '<');
183 do {
184 c = fgetc(fp);
185 if (c != EOF) rdaddc(&rsc, c);
186 } while (c != '>' && c != EOF);
187 return rsc.text;
188 }
189
190 static char *pf_read_word(FILE *fp, int c) {
191 rdstringc rsc = { 0, 0, NULL };
192
193 rdaddc(&rsc, c);
194 if (c == '{' || c == '}' || c == '[' || c == ']')
195 return rsc.text;
196 for (;;) {
197 c = fgetc(fp);
198 if (pf_isspecial(c) || pf_isspace(c) || c == EOF) break;
199 rdaddc(&rsc, c);
200 }
201 if (pf_isspecial(c)) ungetc(c, fp);
202 return rsc.text;
203 }
204
205 static char *pf_read_token(FILE *fp) {
206 int c;
207
208 do {
209 c = fgetc(fp);
210 } while (pf_isspace(c));
211 if (c == EOF) return NULL;
212 if (c == '%') {
213 do {
214 c = fgetc(fp);
215 } while (c != 012 && c != 015);
216 return pf_read_token(fp);
217 }
218 if (c == '(') return pf_read_litstring(fp);
219 if (c == '<') return pf_read_hexstring(fp);
220 return pf_read_word(fp, c);
221 }