4 * Add a Unicode character table to a PSF font
6 * Copyright (C) 1994 H. Peter Anvin
8 * This program may be freely copied under the terms of the GNU
9 * General Public License (GPL), version 2, or at your option
12 * Added input ranges, aeb.
23 typedef unsigned short unicode;
27 unicode uc; /* Unicode listed */
28 struct unicode_list *next;
31 void usage(char *argv0)
33 fprintf(stderr, _("Usage: \n"
34 " %s psffont chartable [outfile]\n"), argv0);
38 int getunicode(char **p0)
42 while (*p == ' ' || *p == '\t')
44 if (*p != 'U' || p[1] != '+' ||
45 !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
46 !isxdigit(p[5]) || isxdigit(p[6]))
49 return strtol(p+2,0,16);
52 struct unicode_list **hookptr[512];
54 void addpair(int fp, int un)
56 struct unicode_list *newmbr;
58 if ( un != PSF_SEPARATOR && un <= 0xFFFF )
60 /* Add to linked list IN ORDER READ */
62 newmbr = malloc(sizeof(struct unicode_list));
63 newmbr->uc = (unicode) un;
65 *(hookptr[fp]) = newmbr;
66 hookptr[fp] = &(newmbr->next);
68 /* otherwise: ignore */
71 int main(int argc, char *argv[])
73 FILE *in, *ctbl, *out;
74 char *inname, *tblname;
76 unsigned char unicodepair[2];
77 struct unicode_list *unilist[512];
78 struct unicode_list *newmbr, tmpmbr;
79 struct psf_header psfhdr;
82 int fp0, fp1, un0, un1;
85 setlocale(LC_ALL, "");
86 bindtextdomain(PACKAGE, LOCALEDIR);
89 if ( argc < 3 || argc > 4 )
92 if ( !strcmp(argv[1],"-") )
99 in = fopen(inname = argv[1], "r");
107 if ( !strcmp(argv[2],"-") && in != stdin )
114 ctbl = fopen(tblname = argv[2], "r");
122 if ( argc < 4 || !strcmp(argv[3],"-") )
126 out = fopen(argv[3], "w");
134 if ( fread(&psfhdr, sizeof(struct psf_header), 1, in) < 1 )
136 fprintf(stderr, _("%s: Cannot read psf header\n"), inname);
140 if (! PSF_MAGIC_OK(psfhdr) )
142 fprintf(stderr, _("%s: Bad magic number\n"), inname);
146 if ( psfhdr.mode > PSF_MAXMODE )
148 fprintf(stderr, _("%s: Unknown mode number (%d)\n"), inname, psfhdr.mode);
152 fontlen = ( psfhdr.mode & PSF_MODE512 ) ? 512 : 256;
155 if ( fread(buffer, psfhdr.charsize, fontlen, in) < fontlen )
160 fclose(in); /* Done with input */
162 /* Set has-table bit in mode field, and copy to output */
164 psfhdr.mode |= PSF_MODEHASTAB;
165 fwrite(&psfhdr, sizeof(struct psf_header), 1, out);
166 fwrite(buffer, psfhdr.charsize, fontlen, out);
168 /* Now we come to the tricky part. Parse the input table. */
170 for ( i = 0 ; i < 512 ; i++ ) /* Initialize unicode list */
173 for ( i = 0 ; i < 512 ; i++ ) /* Initialize hook pointer list */
174 hookptr[i] = &(unilist[i]);
176 while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
178 if ( (p = strchr(buffer, '\n')) != NULL )
181 fprintf(stderr, _("%s: Warning: line too long\n"), tblname);
187 * <fontpos> <unicode> <unicode> ...
189 * <range> <unicode range>
191 * where <range> ::= <fontpos>-<fontpos>
192 * and <unicode> ::= U+<h><h><h><h>
193 * and <h> ::= <hexadecimal digit>
196 while (*p == ' ' || *p == '\t')
198 if (!*p || *p == '#')
199 continue; /* skip comment or blank line */
201 fp0 = strtol(p, &p1, 0);
204 fprintf(stderr, _("Bad input line: %s\n"), buffer);
209 while (*p == ' ' || *p == '\t')
214 fp1 = strtol(p, &p1, 0);
217 fprintf(stderr, _("Bad input line: %s\n"), buffer);
225 if ( fp0 < 0 || fp0 >= fontlen )
228 _("%s: Glyph number (0x%x) larger than font length\n"),
232 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
235 _("%s: Bad end of range (0x%x)\n"),
242 /* we have a range; expect the word "idem" or a Unicode range of the
244 while (*p == ' ' || *p == '\t')
246 if (!strncmp(p, "idem", 4))
248 for (i=fp0; i<=fp1; i++)
254 un0 = getunicode(&p);
255 while (*p == ' ' || *p == '\t')
260 _("%s: Corresponding to a range of font positions, "
261 "there should be a Unicode range\n"),
266 un1 = getunicode(&p);
267 if (un0 < 0 || un1 < 0)
270 _("%s: Bad Unicode range corresponding to font "
271 "position range 0x%x-0x%x\n"),
275 if (un1 - un0 != fp1 - fp0)
278 _("%s: Unicode range U+%x-U+%x not of the same "
279 "length as font position range 0x%x-0x%x\n"),
280 tblname, un0, un1, fp0, fp1);
283 for (i=fp0; i<=fp1; i++)
284 addpair(i, un0-fp0+i);
289 /* no range; expect a list of unicode values for a single font position */
291 while ( (un0 = getunicode(&p)) >= 0 )
294 while (*p == ' ' || *p == '\t')
297 fprintf(stderr, _("%s: trailing junk (%s) ignored\n"), tblname, p);
300 /* Okay, we hit EOF, now glyph table should be read */
304 for ( i = 0 ; i < fontlen ; i++ )
306 for ( newmbr = unilist[i] ; newmbr ; newmbr = tmpmbr.next )
309 unicodepair[0] = (tmpmbr.uc & 0xff);
310 unicodepair[1] = ((tmpmbr.uc >> 8) & 0xff);
311 fwrite(unicodepair, sizeof(unicodepair), 1, out);
315 /* Write string terminator */
316 unicodepair[0] = (PSF_SEPARATOR & 0xff);
317 unicodepair[1] = ((PSF_SEPARATOR >> 8) & 0xff);
318 fwrite(unicodepair, sizeof(unicodepair), 1, out);