Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtTerm / util / lineToData.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: lineToData.c /main/1 1996/04/21 19:20:58 drk $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
31  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
32  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
33  * (c) Copyright 1993, 1994 Novell, Inc.                                *
34  */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <string.h>
40
41 #include "TermPrimLineFontP.h"
42
43 int ParseChar(char **str);
44 int parseCoord(char **str, char *val, signed char *offset);
45 char * parseToken(char **str);
46 void displayErrorString(FILE *f, char *orig, char *remain);
47 static void DumpChar(FILE *f, int charNum, charType *charList, int charListMax,
48         rect *rectList, int rectListMax, line *lineList, int lineListMax,
49         line *stippleList, int stippleListMax);
50 static void DumpGlyphs(FILE *f, char *prefix,
51         GlyphInfo glyphList, int glyphListMax);
52 static int parseLine(char **bufPtr, line *line);
53 static int parseRectangle(char **bufPtr, rect *rectangle);
54 static void order(char *p1, char *p2, signed char *offset1, signed char *offset2);
55 static char *vis(char val);
56
57 int
58 main(argc, argv)
59 int argc;
60 char **argv;
61 {
62     int charNum = 0;
63     char buffer[BUFSIZ];
64     char *bufPtr;
65     char orig[BUFSIZ];
66     register int i;
67     register char *c;
68     FILE *f;
69     FILE *tmp;
70     extern int getopt();
71     extern int optind;
72     extern char *optarg;
73     extern int opterr;
74     int resolution = 75;                /* dots per inch                */
75     int points;
76     char *prefix = "_Term";
77
78     charType *charList = (charType *) 0;
79     int charListSize = 0;
80     int charListMax = 0;
81
82     rect *rectList = (rect *) 0;
83     int rectListSize = 0;
84     int rectListMax = 0;
85
86     line *stippleList = (line *) 0;
87     int stippleListSize = 0;
88     int stippleListMax = 0;
89
90     line *lineList = (line *) 0;
91     int lineListSize = 0;
92     int lineListMax = 0;
93
94     GlyphInfo glyphList = (GlyphInfo) 0;
95     int glyphListSize = 0;
96     int glyphListMax = 0;
97
98     int charCount = 0;                  /* total number of chars in font*/
99
100     char *datafilename = "linegen.data";
101     int dummyInt;
102     int error;
103
104     while (EOF != (i = getopt(argc, argv, "p:f:"))) {
105         switch (i) {
106         case 'f' :
107             datafilename = optarg;
108             break;
109
110         case 'p' :
111             prefix = optarg;
112             break;
113         }
114     }
115
116     if (NULL == (f = fopen(datafilename, "r"))) {
117         (void) perror(datafilename);
118         (void) exit(1);
119     }
120
121     /* read through the file and generate each character...
122      */
123     while (fgets(buffer, sizeof(buffer), f)) {
124         /* null out '\n'... */
125         buffer[strlen(buffer) - 1] = '\0';
126
127         /* if the line begins with '#', ignore it... */
128         if (*buffer == '#')
129             continue;
130
131         /* if the line begins with a '!', just print it out (with the
132          * '!' removed... */
133
134         if (*buffer == '!') {
135             (void) fputs(buffer + 1, stdout);
136             (void) putc('\n', stdout);
137             continue;
138         }
139
140         /* back up buffer... */
141         (void) strcpy(orig, buffer);
142
143         bufPtr = buffer;
144
145         /* pull off token... */
146         c = parseToken(&bufPtr);
147
148         /* ignore blank lines... */
149         if (!c || !*c)
150             continue;
151
152         /* process the token... */
153         if (!strcmp(c, "char")) {
154             /* dump the previous character... */
155             if (charListMax > 0) {
156                 (void) DumpChar(stdout, charCount++, charList, charListMax,
157                          rectList, rectListMax, lineList, lineListMax,
158                          stippleList, stippleListMax);
159                 lineListMax = 0;
160                 rectListMax = 0;
161                 stippleListMax = 0;
162             }
163
164             /* grow the glyph list if necessary... */
165             if (glyphListMax + 1 > glyphListSize) {
166                 glyphListSize += 10;
167                 glyphList = (GlyphInfo) realloc(glyphList,
168                         glyphListSize * sizeof(GlyphInfoRec));
169             }
170             /* bump count.  We need to remember that this is one high
171              * when we use it as an index...
172              */
173             glyphList[glyphListMax].numRects = 0;
174             glyphList[glyphListMax].numLines = 0;
175             glyphList[glyphListMax].numStipples = 0;
176             (void) glyphListMax++;
177
178             /* this is a list of characters... */
179             charListMax = 0;
180             charListSize = 10;
181             charList = (charType *)
182                     malloc((unsigned) (charListSize * sizeof(charType)));
183
184             while (*bufPtr) {
185                 /* extend the charList if we need to (the 2 is 1 for this
186                  * entry and 1 for the terminating 0...
187                  */
188                 if (charListMax + 2 > charListSize) {
189                     charListSize += 10;
190                     charList = (charType *) realloc(charList,
191                             charListSize * sizeof(charType));
192                 }
193
194                 if (0 == (charList[charListMax++] = ParseChar(&bufPtr))) {
195                     (void) fprintf(stderr, "invalid \"char\" specification:\n");
196                     (void) displayErrorString(stderr, orig, bufPtr);
197                     (void) exit(1);
198                 }
199
200                 if (bufPtr && *bufPtr) {
201                     if (*bufPtr == ',') {
202                         /* additional stuff... */
203                         (void) bufPtr++;
204                         /* skip whitespace... */
205                         while (*bufPtr && strchr(" \t", *bufPtr))
206                             (void) bufPtr++;
207                     } else {
208                         /* error -- invalid character... */
209                         (void) fprintf(stderr,
210                                 "invalid \"char\" specification:\n");
211                         (void) displayErrorString(stderr, orig, bufPtr);
212                         (void) exit(1);
213                     }
214                 }
215             }
216
217             /* null term the list... */
218             charList[charListMax] = 0;
219
220             /* save away the char list... */
221             glyphList[glyphListMax - 1].chars = charList;
222
223         } else if (!strcmp(c, "rect")) {
224             if (rectListMax + 1 > rectListSize) {
225                 rectListSize += 10;
226                 rectList = (rect *) realloc(rectList,
227                         rectListSize * sizeof(rect));
228             }
229                 
230             if (parseRectangle(&bufPtr, &rectList[rectListMax])) {
231                 (void) fprintf(stderr, "invalid \"rect\" specification:\n");
232                 (void) displayErrorString(stderr, orig, bufPtr);
233                 (void) exit(1);
234             }
235
236             /* increment line count... */
237             (void) rectListMax++;
238
239             /* save away the rect list... */
240             glyphList[glyphListMax - 1].rects = rectList;
241             glyphList[glyphListMax - 1].numRects = rectListMax;
242
243         } else if (!strcmp(c, "line")) {
244             if (lineListMax + 1 > lineListSize) {
245                 lineListSize += 10;
246                 lineList = (line *) realloc(lineList,
247                         lineListSize * sizeof(line));
248             }
249
250             /* did we error?... */
251             if (parseLine(&bufPtr, &lineList[lineListMax])) {
252                 (void) fprintf(stderr, "invalid \"line\" specification:\n");
253                 (void) displayErrorString(stderr, orig, bufPtr);
254                 (void) exit(1);
255             }
256
257             /* increment line count... */
258             (void) lineListMax++;
259
260             /* save away the line list... */
261             glyphList[glyphListMax - 1].lines = lineList;
262             glyphList[glyphListMax - 1].numLines = lineListMax;
263
264         } else if (!strcmp(c, "stipple")) {
265             if (stippleListMax + 1 > stippleListSize) {
266                 stippleListSize += 10;
267                 stippleList = (line *) realloc(stippleList,
268                         stippleListSize * sizeof(line));
269             }
270                 
271             if (parseLine(&bufPtr, &stippleList[stippleListMax])) {
272                 (void) fprintf(stderr, "invalid \"stipple\" specification:\n");
273                 (void) displayErrorString(stderr, orig, bufPtr);
274                 (void) exit(1);
275             }
276
277
278             /* increment line count... */
279             (void) stippleListMax++;
280
281             /* save away the line list... */
282             glyphList[glyphListMax - 1].stipples = stippleList;
283             glyphList[glyphListMax - 1].numStipples = stippleListMax;
284
285         } else {
286             /* unknown token... */
287             (void) fprintf(stderr, "invalid token:\n");
288             (void) displayErrorString(stderr, orig, orig);
289             (void) exit(1);
290         }
291     }
292
293     /* dump out the last character(s)... */
294     if (charListMax > 0) {
295         (void) DumpChar(stdout, charCount++, charList, charListMax,
296                  rectList, rectListMax, lineList, lineListMax,
297                  stippleList, stippleListMax);
298         lineListMax = 0;
299         rectListMax = 0;
300         stippleListMax = 0;
301         charListMax = 0;
302     }
303
304     /* build the final structure... */
305     (void) DumpGlyphs(stdout, prefix, glyphList, glyphListMax);
306
307     (void) exit(0);
308 }
309
310 int
311 ParseChar(char **str)
312 {
313     register char *c = *str;
314     char *ptr;
315     int ret = 0;
316
317     while (*c && strchr(" \t", *c))
318         c++;
319
320     if (*c == '\'') {
321         /* char format (i.e., 'c')...
322          */
323
324         /* skip over '\''... */
325         (void) c++;
326         if (*c == '\\') {
327             /* quoted character... */
328             /* skip over '\\'... */
329             (void) c++;
330             switch (*c++) {
331             case 'n' :
332                 ret = '\n';
333                 break;
334             case 'f' :
335                 ret = '\f';
336                 break;
337             case 'r' :
338                 ret = '\r';
339                 break;
340             case 'b' :
341                 ret = '\b';
342                 break;
343             case 't' :
344                 ret = '\t';
345                 break;
346             case '\'' :
347                 ret = '\'';
348                 break;
349             case '\\' :
350                 ret = '\\';
351                 break;
352             case '0':
353             case '1':
354             case '2':
355             case '3':
356             case '4':
357             case '5':
358             case '6':
359             case '7':
360                 /* backup... */
361                 (void) c--;
362                 ret = (int) strtol(c, &ptr, 8);
363                 c = ptr;
364                 break;
365             default :
366                 /* error... */
367                 *str = c - 1;
368                 return(0);
369                 break;
370             }
371         } else {
372             /* unquoted char... */
373             ret = *c++;
374         }
375
376         /* need to finish parsing the closing quote... */
377         if (*c++ != '\'') {
378             *str = c - 1;
379             return(0);
380         }
381     } else if ((*c >= '0') || (*c <= '9')) {
382         /* a number...
383          */
384         ret = (int) strtol(c, &ptr, 0);
385     }
386
387     /* skip over whitespace... */
388     while (*c && strchr(" \t", *c))
389         c++;
390
391     /* update the pointer... */
392     *str = c;
393     return(ret);
394 }
395
396 int
397 parseCoord(char **str, char *val, signed char *offset)
398 {
399     register char *c = *str;
400     char *ptr;
401     int sign = 1;
402
403     /* skip over whitespace... */
404     while (*c && strchr(" \t", *c))
405         c++;
406
407     /* end of line?... */
408     if (!*c) {
409         *str = (char *) 0;
410         return(-1);
411     }
412
413     /* parse off number... */
414     *val = (char) strtol(c, &ptr, 0);
415     c = ptr;
416
417     /* skip over whitespace... */
418     while (c && *c && strchr(" \t", *c))
419         c++;
420
421     /* parse off offset... */
422     if (c && ((*c == '-') || (*c == '+'))) {
423         if (*c == '-')
424             sign = -1;
425         /* skip over sign... */
426         (void) c++;
427         /* skip over shitespace... */
428         while (*c && strchr(" \t", *c))
429             c++;
430
431         /* parse off offset... */
432         *offset = (char) strtol(c, &ptr, 0);
433         c = ptr;
434
435         /* set sign of offset... */
436         *offset *= sign;
437
438         /* skip over whitespace... */
439         while (c && *c && strchr(" \t", *c))
440             c++;
441     } else {
442         *offset = 0;
443     }
444
445     /* set up return ptr... */
446     *str = c;
447
448     return(0);
449 }
450
451 char *
452 parseToken(char **str)
453 {
454     register char *c = *str;
455     char *ret;
456
457     /* skip white space... */
458     while (*c && strchr(" \t", *c))
459         c++;
460
461     /* we hit start of token... */
462     ret = c;
463     while (*c && !strchr(" \t", *c))
464         c++;
465
466     /* null out the first whitespace... */
467     if (*c)
468         *c++ = '\0';
469
470     /* skip white space... */
471     while (*c && strchr(" \t", *c))
472         c++;
473
474     *str = c;
475     return(ret);
476 }
477
478 void
479 displayErrorString(FILE *f, char *orig, char *remain)
480 {
481     register int col;
482
483     (void) fprintf(f, "        %s\n", orig);
484     if (!remain || !*remain) {
485         col = strlen(orig);
486     } else {
487         col = strlen(orig) - strlen(remain);
488         if (col < 0)
489             /* this should not happen... */
490             col = 0;
491     }
492
493     /* add 8 for the indent... */
494     col += 8;
495
496     /* output space... */
497     while (col-- > 0)
498         (void) putc(' ', f);
499     /* output an '^'... */
500     (void) putc('^', f);
501     (void) putc('\n', f);
502 }
503
504 static int
505 parseLine(char **bufPtr, line *line)
506 {
507     signed char dummyChar;
508     int error = 0;
509
510     /* set the bits that correspond to this line... */
511     /* parse off x1... */
512     error = parseCoord(bufPtr, &(line->x1),
513             &(line->x1Offset));
514
515     /* parse off y1... */
516     if (!error)
517         error = parseCoord(bufPtr, &(line->y1),
518                 &(line->y1Offset));
519
520     /* parse off x2... */
521     if (!error)
522         error = parseCoord(bufPtr, &(line->x2),
523                 &(line->x2Offset));
524
525     /* parse off y2... */
526     if (!error)
527         error = parseCoord(bufPtr, &(line->y2),
528                 &(line->y2Offset));
529
530     /* parse off lineWidth... */
531     if (!error)
532         error = parseCoord(bufPtr, &(line->width),
533                 &dummyChar);
534
535     /* did we error?... */
536     if (error) {
537         return(1);
538     }
539
540     /* order x and y coords... */
541     (void) order(&(line->x1),
542             &(line->x2),
543             &(line->x1Offset),
544             &(line->x2Offset));
545     (void) order(&(line->y1),
546             &(line->y2),
547             &(line->y1Offset),
548             &(line->y2Offset));
549
550     return(0);
551 }
552
553 static int
554 parseRectangle(char **bufPtr, rect *rectangle)
555 {
556     int error = 0;
557
558     /* parse off x1... */
559     error = parseCoord(bufPtr, &(rectangle->x1),
560             &(rectangle->x1Offset));
561
562     /* parse off y1... */
563     if (!error)
564         error = parseCoord(bufPtr, &(rectangle->y1),
565                 &(rectangle->y1Offset));
566
567     /* parse off x2... */
568     if (!error)
569         error = parseCoord(bufPtr, &(rectangle->x2),
570                 &(rectangle->x2Offset));
571
572     /* parse off y2... */
573     if (!error)
574         error = parseCoord(bufPtr, &(rectangle->y2),
575                 &(rectangle->y2Offset));
576
577     /* did we error?... */
578     if (error) {
579         return(1);
580     }
581
582     /* order x and y coords... */
583     (void) order(&(rectangle->x1),
584             &(rectangle->x2),
585             &(rectangle->x1Offset),
586             &(rectangle->x2Offset));
587     (void) order(&(rectangle->y1),
588             &(rectangle->y2),
589             &(rectangle->y1Offset),
590             &(rectangle->y2Offset));
591
592     return(0);
593 }
594
595 static void
596 order(char *p1, char *p2, signed char *offset1, signed char *offset2)
597 {
598     char swap;
599
600     /* order coords... */
601     if (*p1 > *p2) {
602         /* swap p1 & p1 */
603         swap = *p1;
604         *p1 = *p2;
605         *p2 = swap;
606
607         swap = *offset1;
608         *offset1 = *offset2;
609         *offset2 = swap;
610     }
611 }
612
613 static void
614 DumpGlyphs(FILE *f, char *prefix, GlyphInfo glyphList, int glyphListMax)
615 {
616     int i1;
617     int i2;
618
619     /* print the full glyph array... */
620
621     (void) fprintf(f, "int %sNumGlyphs = %d;\n", prefix, glyphListMax);
622     (void) fprintf(f, "GlyphInfoRec %sGlyphs[] = {\n", prefix);
623     for (i1 = 0; i1 < glyphListMax; i1++) {
624         /* print the characters this is for... */
625         (void) fputs("    /* data for ", f);
626         for (i2 = 0; glyphList[i1].chars[i2] != 0; i2++) {
627             if (i2 > 0) {
628                 (void) putc(',', f);
629             }
630             (void) fputs(vis(glyphList[i1].chars[i2]), f);
631             (void) putc(' ', f);
632         }
633         (void) fputs("*/\n", f);
634         (void) fprintf(f, "    {\n");
635
636         (void) fprintf(f, "        chars%03d,           /* char list */\n",
637                 i1);
638
639         if (glyphList[i1].numRects > 0) {
640             (void) fprintf(f, "        rects%03d,    %2d,", i1,
641                     glyphList[i1].numRects);
642         } else {
643             (void) fprintf(f, "        (rect *) 0,   0,");
644         }
645         (void) fprintf(f, "    /* rectangle list */\n");
646
647         if (glyphList[i1].numLines > 0) {
648             (void) fprintf(f, "        lines%03d,    %2d,", i1,
649                     glyphList[i1].numLines);
650         } else {
651             (void) fprintf(f, "        (line *) 0,   0,");
652         }
653         (void) fprintf(f, "    /* line list */\n");
654
655         if (glyphList[i1].numStipples > 0) {
656             (void) fprintf(f, "        stipples%03d, %2d,", i1,
657                     glyphList[i1].numStipples);
658         } else {
659             (void) fprintf(f, "        (line *) 0,   0,");
660         }
661         (void) fprintf(f, "    /* stipple list */\n");
662         (void) printf("    },\n\n");
663     }
664     (void) printf("};\n");
665 }
666
667 static void
668 DumpChar(FILE *f, int charCount, charType *charList, int charListMax,
669         rect *rectList, int rectListMax, line *lineList, int lineListMax,
670         line *stippleList, int stippleListMax)
671 {
672     int i;
673
674     /* print the characters this is for... */
675     (void) fputs("/* data for ", f);
676     for (i = 0; i < charListMax; i++) {
677         if (i > 0) {
678             (void) putc(',', f);
679         }
680         (void) fputs(vis(charList[i]), f);
681         (void) putc(' ', f);
682     }
683     (void) fputs("*/\n", f);
684
685     (void) fprintf(f, "static charType chars%03d[] = {", charCount);
686     for (i = 0; i < charListMax; i++) {
687         (void) fprintf(f, "0%03o, ", (int) charList[i]);
688     }
689     (void) fprintf(f, "0};\n");
690
691     if (rectListMax > 0) {
692         (void) fprintf(f, "static rect rects%03d[] = {\n", charCount);
693         for (i = 0; i < rectListMax; i++) {
694             (void) fprintf(f, "    {%d, %d, %d, %d, %d, %d, %d, %d},\n",
695                     rectList[i].x1, rectList[i].x1Offset,
696                     rectList[i].y1, rectList[i].y1Offset,
697                     rectList[i].x2, rectList[i].x2Offset,
698                     rectList[i].y2, rectList[i].y2Offset);
699         }
700         (void) fprintf(f, "};\n");
701     }
702
703     if (lineListMax > 0) {
704         (void) fprintf(f, "static line lines%03d[] = {\n", charCount);
705         for (i = 0; i < lineListMax; i++) {
706             (void) fprintf(f, "    {%d, %d, %d, %d, %d, %d, %d, %d, %d},\n",
707                     lineList[i].x1, lineList[i].x1Offset,
708                     lineList[i].y1, lineList[i].y1Offset,
709                     lineList[i].x2, lineList[i].x2Offset,
710                     lineList[i].y2, lineList[i].y2Offset,
711                     lineList[i].width);
712         }
713         (void) fprintf(f, "};\n");
714     }
715
716     if (stippleListMax > 0) {
717         (void) fprintf(f, "static line stipples%03d[] = {\n", charCount);
718         for (i = 0; i < stippleListMax; i++) {
719             (void) fprintf(f, "    {%d, %d, %d, %d, %d, %d, %d, %d, %d},\n",
720                     stippleList[i].x1, stippleList[i].x1Offset,
721                     stippleList[i].y1, stippleList[i].y1Offset,
722                     stippleList[i].x2, stippleList[i].x2Offset,
723                     stippleList[i].y2, stippleList[i].y2Offset,
724                     stippleList[i].width);
725         }
726         (void) fprintf(f, "};\n");
727     }
728     (void) fprintf(f, "\n");
729 }
730
731 static char *
732 vis(char val)
733 {
734     char buffer[BUFSIZ];
735
736     if (isprint(val)) {
737         if (val == '^') {
738             (void) strcpy(buffer, "'^^'");
739         } else if (val == '\\') {
740             (void) strcpy(buffer, "'\\\\'");
741         } else if (val == '\'') {
742             (void) strcpy(buffer, "'\\\''");
743         } else {
744             (void) sprintf(buffer, "'%c'", val);
745         }
746     } else if (iscntrl(val)) {
747         (void) sprintf(buffer, "'^%c'", val);
748     } else {
749         (void) sprintf(buffer, "'\\%03o'", val);
750     }
751
752     return(strdup(buffer));
753 }