15 #include <sys/ioctl.h>
22 #include "psffontop.h"
23 #include "loadunimap.h"
28 extern char *progname;
31 static const char *const unidirpath[] = { "", DATADIR "/" UNIMAPDIR "/", 0 };
32 static const char *const unisuffixes[] = { "", ".uni", ".sfm", 0 };
40 static void __attribute__ ((noreturn))
43 _("Usage:\n\t%s [-C console] [-o map.orig]\n"), progname);
48 main(int argc, char *argv[]) {
52 char *infnam = "def.uni";
54 set_progname(argv[0]);
56 setlocale(LC_ALL, "");
57 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
58 textdomain(PACKAGE_NAME);
61 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
62 print_version_and_exit();
64 while ((c = getopt(argc, argv, "C:o:")) != EOF) {
77 if (argc > optind+1 || (argc == optind && !outfnam))
83 saveunicodemap(fd, outfnam);
89 infnam = argv[optind];
90 loadunicodemap(fd, infnam);
96 * Skip spaces and read U+1234 or return -1 for error.
97 * Return first non-read position in *p0 (unchanged on error).
100 getunicode(char **p0) {
103 while (*p == ' ' || *p == '\t')
106 /* The code below also allows one to accept 'utf8' */
113 * Read a single complete utf-8 character, and
114 * expect it to be closed by a single quote.
116 u = from_utf8(&p1, 0, &err);
117 if (err || *p1 != '\'')
123 if (*p != 'U' || p[1] != '+' || !isxdigit(p[2]) || !isxdigit(p[3]) ||
124 !isxdigit(p[4]) || !isxdigit(p[5]) || isxdigit(p[6]))
127 return strtol(p+2,0,16);
130 static struct unimapdesc descr;
132 static struct unipair *list = 0;
133 static int listsz = 0;
134 static int listct = 0;
137 addpair(int fp, int un) {
138 if (listct == listsz) {
140 list = xrealloc((char *)list, listsz);
142 list[listct].fontpos = fp;
143 list[listct].unicode = un;
149 * <fontpos> <unicode> <unicode> ...
152 * <range> <unicode range>
154 * where <range> ::= <fontpos>-<fontpos>
155 * and <unicode> ::= U+<h><h><h><h>
156 * and <h> ::= <hexadecimal digit>
160 parseline(char *buffer, char *tblname) {
163 int fp0, fp1, un0, un1;
168 while (*p == ' ' || *p == '\t')
170 if (!*p || *p == '#')
171 return; /* skip comment or blank line */
173 fp0 = strtol(p, &p1, 0);
175 fprintf(stderr, _("Bad input line: %s\n"), buffer);
180 while (*p == ' ' || *p == '\t')
184 fp1 = strtol(p, &p1, 0);
186 fprintf(stderr, _("Bad input line: %s\n"), buffer);
193 if ( fp0 < 0 || fp0 >= fontlen ) {
195 _("%s: Glyph number (0x%x) larger than font length\n"),
199 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) {
201 _("%s: Bad end of range (0x%x)\n"),
207 /* we have a range; expect the word "idem" or a Unicode range
208 of the same length or a single Unicode value */
209 while (*p == ' ' || *p == '\t')
211 if (!strncmp(p, "idem", 4)) {
213 for (i=fp0; i<=fp1; i++)
218 un0 = getunicode(&p);
219 while (*p == ' ' || *p == '\t')
222 for (i=fp0; i<=fp1; i++)
228 un1 = getunicode(&p);
229 if (un0 < 0 || un1 < 0) {
231 _("%s: Bad Unicode range corresponding to "
232 "font position range 0x%x-0x%x\n"),
236 if (un1 - un0 != fp1 - fp0) {
238 _("%s: Unicode range U+%x-U+%x not of the same"
239 " length as font position range 0x%x-0x%x\n"),
240 tblname, un0, un1, fp0, fp1);
243 for(i=fp0; i<=fp1; i++)
244 addpair(i,un0-fp0+i);
247 /* no range; expect a list of unicode values
248 for a single font position */
250 while ( (un0 = getunicode(&p)) >= 0 )
254 while (*p == ' ' || *p == '\t')
257 fprintf(stderr, _("%s: trailing junk (%s) ignored\n"),
262 loadunicodemap(int fd, char *tblname) {
267 if (lk_findfile(tblname, unidirpath, unisuffixes, &fp)) {
273 printf(_("Loading unicode map from file %s\n"), fp.pathname);
275 while ( fgets(buffer, sizeof(buffer), fp.fd) != NULL ) {
276 if ( (p = strchr(buffer, '\n')) != NULL )
279 fprintf(stderr, _("%s: %s: Warning: line too long\n"),
282 parseline(buffer, tblname);
287 if (listct == 0 && !force) {
289 _("%s: not loading empty unimap\n"
290 "(if you insist: use option -f to override)\n"),
293 descr.entry_ct = listct;
294 descr.entries = list;
295 if (loadunimap (fd, NULL, &descr))
301 static struct unimapdesc
302 getunicodemap(int fd) {
303 struct unimapdesc unimap_descr;
305 if (getunimap(fd, &unimap_descr))
309 fprintf(stderr, "# %d %s\n", unimap_descr.entry_ct,
310 (unimap_descr.entry_ct == 1) ? _("entry") : _("entries"));
317 saveunicodemap(int fd, char *oufil) {
319 struct unimapdesc unimap_descr;
320 struct unipair *unilist;
323 if ((fpo = fopen(oufil, "w")) == NULL) {
328 unimap_descr = getunicodemap(fd);
329 unilist = unimap_descr.entries;
331 for(i=0; i<unimap_descr.entry_ct; i++)
332 fprintf(fpo, "0x%02x\tU+%04x\n", unilist[i].fontpos, unilist[i].unicode);
336 printf(_("Saved unicode map on `%s'\n"), oufil);
340 appendunicodemap(int fd, FILE *fp, int fontsize, int utf8) {
341 struct unimapdesc unimap_descr;
342 struct unipair *unilist;
345 unimap_descr = getunicodemap(fd);
346 unilist = unimap_descr.entries;
349 for(i=0; i<fontsize; i++) {
351 /* More than one mapping is not a sequence! */
353 for(j=0; j<unimap_descr.entry_ct; j++)
354 if (unilist[j].fontpos == i)
357 appendseparator(fp, 1, utf8);
359 if (debug) printf ("\nchar %03x: ", i);
360 for(j=0; j<unimap_descr.entry_ct; j++)
361 if (unilist[j].fontpos == i) {
363 printf ("%04x ", unilist[j].unicode);
364 appendunicode(fp, unilist[j].unicode, utf8);
366 appendseparator(fp, 0, utf8);
370 if (debug) printf ("\n");
372 printf(_("Appended Unicode map\n"));