15 #include <sys/ioctl.h>
20 /* the three exported functions */
21 void saveunicodemap(int fd, char *oufil); /* save humanly readable */
22 void loadunicodemap(int fd, char *ufil);
23 void appendunicodemap(int fd, FILE *fp, int ct);/* append in psf style */
25 extern char *malloc(), *realloc();
26 extern char *progname;
27 extern int getfd(void);
30 static char *unidirpath[] = { "", DATADIR "/" TRANSDIR "/", 0 };
31 static char *unisuffixes[] = { "", ".uni", 0 };
39 main(int argc, char *argv[]) {
44 setlocale(LC_ALL, "");
45 bindtextdomain(PACKAGE, LOCALEDIR);
50 if (argc >= 3 && !strcmp(argv[1], "-o")) {
51 saveunicodemap(fd, argv[2]);
59 fprintf(stderr, _("usage: %s [-o map.orig] map-file\n"),
64 loadunicodemap(fd, (argc > 1) ? argv[1] : "def.uni");
70 * Skip spaces and read U+1234 or return -1 for error.
71 * Return first non-read position in *p0 (unchanged on error).
73 int getunicode(char **p0) {
76 while (*p == ' ' || *p == '\t')
78 if (*p != 'U' || p[1] != '+' || !isxdigit(p[2]) || !isxdigit(p[3]) ||
79 !isxdigit(p[4]) || !isxdigit(p[5]) || isxdigit(p[6]))
82 return strtol(p+2,0,16);
85 struct unimapinit advice;
87 struct unimapdesc descr;
89 struct unipair *list = 0;
95 advice.advised_hashsize = 0;
96 advice.advised_hashstep = 0;
97 advice.advised_hashlevel = 1;
99 if(ioctl(fd, PIO_UNIMAPCLR, &advice)) {
100 perror("PIO_UNIMAPCLR");
103 descr.entry_ct = listct;
104 descr.entries = list;
105 if(ioctl(fd, PIO_UNIMAP, &descr)) {
106 if (errno == ENOMEM && advice.advised_hashlevel < 100) {
107 advice.advised_hashlevel++;
109 printf(_("trying hashlevel %d\n"), advice.advised_hashlevel);
113 perror("PIO_UNIMAP");
119 void addpair(int fp, int un) {
120 if (listct == listsz) {
122 list = realloc((char *)list, listsz);
124 fprintf(stderr, _("%s: out of memory\n"), progname);
128 list[listct].fontpos = fp;
129 list[listct].unicode = un;
134 loadunicodemap(int fd, char *tblname) {
139 int fp0, fp1, un0, un1;
142 mapf = findfile(tblname, unidirpath, unisuffixes);
149 printf(_("Loading unicode map from file %s\n"), pathname);
151 while ( fgets(buffer, sizeof(buffer), mapf) != NULL ) {
152 if ( (p = strchr(buffer, '\n')) != NULL )
155 fprintf(stderr, _("%s: %s: Warning: line too long\n"), progname, tblname);
161 * <fontpos> <unicode> <unicode> ...
163 * <range> <unicode range>
165 * where <range> ::= <fontpos>-<fontpos>
166 * and <unicode> ::= U+<h><h><h><h>
167 * and <h> ::= <hexadecimal digit>
170 while (*p == ' ' || *p == '\t')
172 if (!*p || *p == '#')
173 continue; /* skip comment or blank line */
175 fp0 = strtol(p, &p1, 0);
177 fprintf(stderr, _("Bad input line: %s\n"), buffer);
182 while (*p == ' ' || *p == '\t')
186 fp1 = strtol(p, &p1, 0);
188 fprintf(stderr, _("Bad input line: %s\n"), buffer);
196 if ( fp0 < 0 || fp0 >= fontlen ) {
198 _("%s: Glyph number (0x%x) larger than font length\n"),
202 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) {
204 _("%s: Bad end of range (0x%x)\n"),
210 /* we have a range; expect the word "idem" or a Unicode range
211 of the same length */
212 while (*p == ' ' || *p == '\t')
214 if (!strncmp(p, "idem", 4)) {
215 for (i=fp0; i<=fp1; i++)
219 un0 = getunicode(&p);
220 while (*p == ' ' || *p == '\t')
224 _("%s: Corresponding to a range of font positions, "
225 "there should be a Unicode range\n"),
230 un1 = getunicode(&p);
231 if (un0 < 0 || un1 < 0) {
233 _("%s: Bad Unicode range corresponding to "
234 "font position range 0x%x-0x%x\n"),
238 if (un1 - un0 != fp1 - fp0) {
240 _("%s: Unicode range U+%x-U+%x not of the same"
241 " length as font position range 0x%x-0x%x\n"),
242 tblname, un0, un1, fp0, fp1);
245 for(i=fp0; i<=fp1; i++)
246 addpair(i,un0-fp0+i);
249 /* no range; expect a list of unicode values
250 for a single font position */
252 while ( (un0 = getunicode(&p)) >= 0 )
255 while (*p == ' ' || *p == '\t')
258 fprintf(stderr, _("%s: trailing junk (%s) ignored\n"), tblname, p);
263 if (listct == 0 && !force)
264 fprintf(stderr, _("%s: not loading empty unimap\n"
265 "(if you insist: use option -f to override)\n"),
271 static struct unimapdesc
272 getunicodemap(int fd) {
273 struct unimapdesc descr;
277 if(ioctl(fd, GIO_UNIMAP, (unsigned long) &descr)) {
278 if(errno != ENOMEM || descr.entry_ct == 0) {
279 perror("GIO_UNIMAP");
282 descr.entries = (struct unipair *)
283 malloc(descr.entry_ct * sizeof(struct unipair));
284 if (descr.entries == NULL) {
285 fprintf(stderr, _("%s: out of memory?\n"), progname);
288 if(ioctl(fd, GIO_UNIMAP, (unsigned long) &descr)) {
289 perror("GIO_UNIMAP(2)");
294 fprintf(stderr, "# %d %s\n", descr.entry_ct,
295 (descr.entry_ct == 1) ? _("entry") : _("entries"));
302 saveunicodemap(int fd, char *oufil) {
304 struct unimapdesc descr;
305 struct unipair *list;
308 if ((fpo = fopen(oufil, "w")) == NULL) {
313 descr = getunicodemap(fd);
314 list = descr.entries;
316 for(i=0; i<descr.entry_ct; i++)
317 fprintf(fpo, "0x%02x\tU+%04x\n", list[i].fontpos, list[i].unicode);
321 printf(_("Saved unicode map on `%s'\n"), oufil);
325 appendunsignedshort(FILE *fp, unsigned short u) {
326 unsigned char unicodepair[2];
328 unicodepair[0] = (u & 0xff);
329 unicodepair[1] = ((u >> 8) & 0xff);
330 if (fwrite(unicodepair, sizeof(unicodepair), 1, fp) != 1) {
331 perror("appendunimap");
337 appendunicodemap(int fd, FILE *fp, int fontsize) {
338 struct unimapdesc descr;
339 struct unipair *list;
342 descr = getunicodemap(fd);
343 list = descr.entries;
345 for(i=0; i<fontsize; i++) {
346 for(j=0; j<descr.entry_ct; j++)
347 if (list[j].fontpos == i)
348 appendunsignedshort(fp, list[j].unicode);
349 appendunsignedshort(fp, PSF_SEPARATOR);
353 printf(_("Appended Unicode map\n"));