4 * Manipulate headers and Unicode tables for psf fonts
6 * Copyright (C) 1999 Andries E. Brouwer
7 * derived from sources that were
8 * Copyright (C) 1994 H. Peter Anvin
10 * This program may be freely copied under the terms of the GNU
11 * General Public License (GPL), version 2, or at your option
24 #include "psffontop.h"
27 * call: psfxtable -i infont -o outfont -it intable -ot outtable
28 * psfaddtable infont intable [outfont]
29 * psfgettable infont [outtable]
30 * psfstriptable infont [outfont]
32 * When outfont is requested it will get psf1 header when
33 * infont had psf1 header and intable does not have sequences
34 * and psf2 header otherwise.
38 * Parse humanly readable unicode table.
40 * <fontposition><tab><uc_defs>
42 * <fontrange><tab><uc_defs>
44 * <fontrange><tab><uc_range>
46 * <uc_defs> :: <empty> | <uc_def><space><uc_defs>
47 * <uc_def> :: <uc> | <uc>,<uc_def>
48 * <uc> :: U+<h><h><h><h>
49 * <h> :: <hexadecimal digit>
50 * <range> :: <value>-<value>
51 * Blank lines and lines starting with # are ignored.
53 struct unicode_list *uclistheads;
56 addpair(int fontpos, unsigned int uc) {
57 struct unicode_list *ul;
58 struct unicode_seq *us;
60 ul = xmalloc(sizeof(struct unicode_list));
61 us = xmalloc(sizeof(struct unicode_seq));
66 ul->prev = uclistheads[fontpos].prev;
69 uclistheads[fontpos].prev = ul;
73 addseq(int fontpos, unsigned int uc) {
74 struct unicode_list *ul;
75 struct unicode_seq *us;
77 ul = uclistheads[fontpos].prev;
78 us = xmalloc(sizeof(struct unicode_seq));
80 us->prev = ul->seq->prev;
87 getunicode(char **p0) {
90 while (*p == ' ' || *p == '\t')
92 if (*p != 'U' || p[1] != '+' ||
93 !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
94 !isxdigit(p[5]) || isxdigit(p[6]))
97 return strtol(p+2,0,16);
101 parse_itab_line(char *buf, int fontlen){
104 long fp0, fp1, un0, un1;
106 if ((p = strchr(buf, '\n')) != NULL)
109 char *u = _("%s: Warning: line too long\n");
110 fprintf(stderr, u, progname);
116 while (*p == ' ' || *p == '\t')
118 if (!*p || *p == '#')
121 fp0 = strtol(p, &p1, 0);
123 char *u = _("%s: Bad input line: %s\n");
124 fprintf(stderr, u, progname, buf);
131 fp1 = strtol(p, &p1, 0);
133 char *u = _("%s: Bad input line: %s\n");
134 fprintf(stderr, u, progname, buf);
141 if (fp0 < 0 || fp0 >= fontlen) {
142 char *u = _("%s: Glyph number (0x%lx) past end of font\n");
143 fprintf(stderr, u, progname, fp0);
146 if (fp1 && (fp1 < fp0 || fp1 >= fontlen)) {
147 char *u = _("%s: Bad end of range (0x%lx)\n");
148 fprintf(stderr, u, progname, fp1);
153 /* we have a range; expect the word "idem"
154 or a Unicode range of the same length */
155 while (*p == ' ' || *p == '\t')
157 if (!strncmp(p, "idem", 4)) {
158 for (i = fp0; i <= fp1; i++)
162 un0 = getunicode(&p);
163 while (*p == ' ' || *p == '\t')
166 char *u = _("%s: Corresponding to a range of "
167 "font positions, there should be "
168 "a Unicode range\n");
169 fprintf(stderr, u, progname);
173 un1 = getunicode(&p);
174 if (un0 < 0 || un1 < 0) {
175 char *u = _("%s: Bad Unicode range "
176 "corresponding to font position "
177 "range 0x%x-0x%x\n");
178 fprintf(stderr, u, progname, fp0, fp1);
181 if (un1 - un0 != fp1 - fp0) {
182 char *u = _("%s: Unicode range U+%x-U+%x not "
183 "of the same length as font "
184 "position range 0x%x-0x%x\n");
185 fprintf(stderr, u, progname,
189 for (i = fp0; i <= fp1; i++)
190 addpair(i, un0-fp0+i);
192 } else { /* no range */
193 while ((un0 = getunicode(&p)) >= 0) {
195 while (*p++ == ',' && (un1 = getunicode(&p)) >= 0) {
200 while (*p == ' ' || *p == '\t')
202 if (*p && *p != '#') {
203 char *u = _("%s: trailing junk (%s) ignored\n");
204 fprintf(stderr, u, progname, p);
210 read_itable(FILE *itab, int fontlen, struct unicode_list **uclistheadsp) {
215 *uclistheadsp = xrealloc(*uclistheadsp,
216 fontlen*sizeof(struct unicode_list));
217 for (i=0; i<fontlen; i++) {
218 struct unicode_list *up = &((*uclistheadsp)[i]);
223 while (fgets(buf, sizeof(buf), itab) != NULL)
224 parse_itab_line(buf, fontlen);
231 main(int argc, char **argv) {
232 char *ifname, *ofname, *itname, *otname;
233 FILE *ifil, *ofil, *itab, *otab;
234 int psftype, fontlen, charsize, hastable, notable;
236 int width = 8, bytewidth, height;
237 char *inbuf, *fontbuf;
238 int inbuflth, fontbuflth;
240 set_progname(argv[0]);
242 setlocale(LC_ALL, "");
243 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
244 textdomain(PACKAGE_NAME);
246 if (argc == 2 && !strcmp(argv[1], "-V"))
247 print_version_and_exit();
249 ifil = ofil = itab = otab = NULL;
250 ifname = ofname = itname = otname = NULL;
254 if (!strcmp(progname, "psfaddtable")) {
255 /* Do not send binary data to stdout without explicit "-" */
257 char *u = _("Usage:\n\t%s infont intable outfont\n");
258 fprintf(stderr, u, progname);
264 } else if (!strcmp(progname, "psfgettable")) {
265 if (argc < 2 || argc > 3) {
266 char *u = _("Usage:\n\t%s infont [outtable]\n");
267 fprintf(stderr, u, progname);
271 otname = (argc == 3) ? argv[2] : "-";
272 } else if (!strcmp(progname, "psfstriptable")) {
273 /* Do not send binary data to stdout without explicit "-" */
275 char *u = _("Usage:\n\t%s infont outfont\n");
276 fprintf(stderr, u, progname);
283 for (i = 1; i < argc; i ++) {
284 if ((!strcmp(argv[i], "-i") || !strcmp(argv[i], "-if"))
287 else if((!strcmp(argv[i],"-o")||!strcmp(argv[i],"-of"))
290 else if(!strcmp(argv[i], "-it") && i < argc-1)
292 else if(!strcmp(argv[i], "-ot") && i < argc-1)
294 else if(!strcmp(argv[i], "-nt"))
299 if (i < argc || argc <= 1) {
300 char *u = _("Usage:\n\t%s [-i infont] [-o outfont] "
301 "[-it intable] [-ot outtable] [-nt]\n");
302 fprintf(stderr, u, progname);
309 if (!strcmp(ifname, "-"))
312 ifil = fopen(ifname, "r");
321 else if (!strcmp(itname, "-"))
324 itab = fopen(itname, "r");
331 /* Refuse ifil == itab == stdin ? Perhaps not. */
335 else if (!strcmp(ofname, "-"))
338 ofil = fopen(ofname, "w");
347 else if (!strcmp(otname, "-"))
350 otab = fopen(otname, "w");
357 if (readpsffont(ifil, &inbuf, &inbuflth, &fontbuf, &fontbuflth,
359 itab ? NULL : &uclistheads) == -1) {
360 char *u = _("%s: Bad magic number on %s\n");
361 fprintf(stderr, u, progname, ifname);
366 charsize = fontbuflth/fontlen;
367 bytewidth = (width + 7)/8;
370 height = charsize / bytewidth;
372 hastable = (uclistheads != NULL);
374 if (PSF1_MAGIC_OK((unsigned char *)inbuf)) {
376 } else if (PSF2_MAGIC_OK((unsigned char *)inbuf)) {
379 char *u = _("%s: psf file with unknown magic\n");
380 fprintf(stderr, u, progname);
385 read_itable(itab, fontlen, &uclistheads);
390 struct unicode_list *ul;
391 struct unicode_seq *us;
395 char *u = _("%s: input font does not have an index\n");
396 fprintf(stderr, u, progname);
400 "#\n# Character table extracted from font %s\n#\n",
402 for (i=0; i<fontlen; i++) {
403 fprintf(otab, "0x%03x\t", i);
405 ul = uclistheads[i].next;
409 fprintf(otab, "%sU+%04x", sep, us->uc);
422 writepsffont(ofil, fontbuf, width, height, fontlen, psftype,
423 notable ? NULL : uclistheads);