]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/textcommon.c
Copyright update...
[thirdparty/cups.git] / filter / textcommon.c
CommitLineData
2d35d8ee 1/*
efb2f309 2 * "$Id: textcommon.c,v 1.19 2002/01/02 17:59:01 mike Exp $"
2d35d8ee 3 *
4 * Common text filter routines for the Common UNIX Printing System (CUPS).
5 *
efb2f309 6 * Copyright 1997-2002 by Easy Software Products.
2d35d8ee 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * TextMain() - Standard main entry for text filters.
27 * compare_keywords() - Compare two C/C++ keywords.
28 * getutf8() - Get a UTF-8 encoded wide character...
29 */
30
31/*
32 * Include necessary headers...
33 */
34
35#include "textcommon.h"
36
37
38/*
39 * Globals...
40 */
41
75a4ca02 42int WrapLines = 1, /* Wrap text in lines */
2d35d8ee 43 SizeLines = 60, /* Number of lines on a page */
44 SizeColumns = 80, /* Number of columns on a line */
45 PageColumns = 1, /* Number of columns on a page */
46 ColumnGutter = 0, /* Number of characters between text columns */
47 ColumnWidth = 80, /* Width of each column */
b1ac64aa 48 PrettyPrint = 0, /* Do pretty code formatting */
49 Copies = 1; /* Number of copies */
2d35d8ee 50lchar_t **Page = NULL; /* Page characters */
51int NumPages = 0; /* Number of pages in document */
52int CharsPerInch = 10; /* Number of character columns per inch */
53int LinesPerInch = 6; /* Number of lines per inch */
54int UTF8 = 0; /* Use UTF-8 encoding? */
e2a4ce3e 55int NumKeywords = 0; /* Number of known keywords */
56char **Keywords = NULL; /* List of known keywords */
57
58
59/*
60 * Local globals...
61 */
62
63static char *code_keywords[] = /* List of known C/C++ keywords... */
2d35d8ee 64 {
c33207d6 65 "and",
66 "and_eq",
67 "asm",
2d35d8ee 68 "auto",
c33207d6 69 "bitand",
70 "bitor",
71 "bool",
2d35d8ee 72 "break",
73 "case",
c33207d6 74 "catch",
2d35d8ee 75 "char",
76 "class",
c33207d6 77 "compl",
2d35d8ee 78 "const",
79 "continue",
80 "default",
81 "delete",
2d35d8ee 82 "do",
c33207d6 83 "double",
2d35d8ee 84 "else",
85 "enum",
c33207d6 86 "explicit",
2d35d8ee 87 "extern",
c33207d6 88 "false",
2d35d8ee 89 "float",
90 "for",
91 "friend",
92 "goto",
93 "if",
c33207d6 94 "inline",
2d35d8ee 95 "int",
96 "long",
c33207d6 97 "mutable",
98 "namespace",
2d35d8ee 99 "new",
c33207d6 100 "not",
101 "not_eq",
102 "operator",
103 "or",
104 "or_eq",
2d35d8ee 105 "private",
106 "protected",
107 "public",
108 "register",
109 "return",
110 "short",
111 "signed",
112 "sizeof",
113 "static",
114 "struct",
115 "switch",
c33207d6 116 "template",
117 "this",
118 "throw",
119 "true",
120 "try",
2d35d8ee 121 "typedef",
c33207d6 122 "typename",
2d35d8ee 123 "union",
124 "unsigned",
c33207d6 125 "virtual",
2d35d8ee 126 "void",
127 "volatile",
c33207d6 128 "while",
129 "xor",
130 "xor_eq"
e2a4ce3e 131 },
132 *sh_keywords[] = /* List of known Boure/Korn/zsh/bash keywords... */
133 {
134 "alias",
135 "bg",
136 "break",
137 "case",
138 "cd",
139 "command",
140 "continue",
141 "do",
142 "done",
143 "echo",
144 "elif",
145 "else",
146 "esac",
147 "eval",
148 "exec",
149 "exit",
150 "export",
151 "fc",
152 "fg",
153 "fi",
154 "for",
155 "function",
156 "getopts",
157 "if",
158 "in",
159 "jobs",
160 "kill",
161 "let",
162 "limit",
163 "newgrp",
164 "print",
165 "pwd",
166 "read",
167 "readonly",
168 "return",
169 "select",
170 "set",
171 "shift",
172 "test",
173 "then",
174 "time",
175 "times",
176 "trap",
177 "typeset",
178 "ulimit",
179 "umask",
180 "unalias",
181 "unlimit",
182 "unset",
183 "until",
184 "wait",
185 "whence"
186 "while",
187 },
188 *csh_keywords[] = /* List of known csh/tcsh keywords... */
189 {
190 "alias",
191 "aliases",
192 "bg",
193 "bindkey",
194 "break",
195 "breaksw",
196 "builtins",
197 "case",
198 "cd",
199 "chdir",
200 "complete",
201 "continue",
202 "default",
203 "dirs",
204 "echo",
205 "echotc",
206 "else",
207 "end",
208 "endif",
209 "eval",
210 "exec",
211 "exit",
212 "fg",
213 "foreach",
214 "glob",
215 "goto",
216 "history",
217 "if",
218 "jobs",
219 "kill",
220 "limit",
221 "login",
222 "logout",
223 "ls",
224 "nice",
225 "nohup",
226 "notify",
227 "onintr",
228 "popd",
229 "pushd",
230 "pwd",
231 "rehash",
232 "repeat",
233 "set",
234 "setenv",
235 "settc",
236 "shift",
237 "source",
238 "stop",
239 "suspend",
240 "switch",
241 "telltc",
242 "then",
243 "time",
244 "umask",
245 "unalias",
246 "unbindkey",
247 "unhash",
248 "unlimit",
249 "unset",
250 "unsetenv",
251 "wait",
252 "where",
253 "which",
254 "while"
255 },
256 *perl_keywords[] = /* List of known perl keywords... */
257 {
258 "abs",
259 "accept",
260 "alarm",
261 "and",
262 "atan2",
263 "bind",
264 "binmode",
265 "bless",
266 "caller",
267 "chdir",
268 "chmod",
269 "chomp",
270 "chop",
271 "chown",
272 "chr",
273 "chroot",
274 "closdir",
275 "close",
276 "connect",
277 "continue",
278 "cos",
279 "crypt",
280 "dbmclose",
281 "dbmopen",
282 "defined",
283 "delete",
284 "die",
285 "do",
286 "dump",
287 "each",
288 "else",
289 "elsif",
290 "endgrent",
291 "endhostent",
292 "endnetent",
293 "endprotoent",
294 "endpwent",
295 "endservent",
296 "eof",
297 "eval",
298 "exec",
299 "exists",
300 "exit",
301 "exp",
302 "fcntl",
303 "fileno",
304 "flock",
305 "for",
306 "foreach",
307 "fork",
308 "format",
309 "formline",
310 "getc",
311 "getgrent",
312 "getgrgid",
313 "getgrnam",
314 "gethostbyaddr",
315 "gethostbyname",
316 "gethostent",
317 "getlogin",
318 "getnetbyaddr",
319 "getnetbyname",
320 "getnetent",
321 "getpeername",
322 "getpgrp",
323 "getppid",
324 "getpriority",
325 "getprotobyname",
326 "getprotobynumber",
327 "getprotoent",
328 "getpwent",
329 "getpwnam",
330 "getpwuid",
331 "getservbyname",
332 "getservbyport",
333 "getservent",
334 "getsockname",
335 "getsockopt",
336 "glob",
337 "gmtime",
338 "goto",
339 "grep",
340 "hex",
341 "if",
342 "import",
343 "index",
344 "int",
345 "ioctl",
346 "join",
347 "keys",
348 "kill",
349 "last",
350 "lc",
351 "lcfirst",
352 "length",
353 "link",
354 "listen",
355 "local",
356 "localtime",
357 "log",
358 "lstat",
359 "map",
360 "mkdir",
361 "msgctl",
362 "msgget",
363 "msgrcv",
364 "msgsend",
365 "my",
366 "next",
367 "no",
368 "not",
369 "oct",
370 "open",
371 "opendir",
372 "or",
373 "ord",
374 "pack",
375 "package",
376 "pipe",
377 "pop",
378 "pos",
379 "print",
380 "printf",
381 "push",
382 "quotemeta",
383 "rand",
384 "read",
385 "readdir",
386 "readlink",
387 "recv",
388 "redo",
389 "ref",
390 "rename",
391 "require",
392 "reset",
393 "return",
394 "reverse",
395 "rewinddir",
396 "rindex",
397 "rmdir",
398 "scalar",
399 "seek",
400 "seekdir",
401 "select",
402 "semctl",
403 "semget",
404 "semop",
405 "send",
406 "setgrent",
407 "sethostent",
408 "setnetent",
409 "setpgrp",
410 "setpriority",
411 "setprotoent",
412 "setpwent",
413 "setservent",
414 "setsockopt",
415 "shift",
416 "shmctl",
417 "shmget",
418 "shmread",
419 "shmwrite",
420 "shutdown",
421 "sin",
422 "sleep",
423 "socket",
424 "socketpair",
425 "sort",
426 "splice",
427 "split",
428 "sprintf",
429 "sqrt",
430 "srand",
431 "stat",
432 "study",
433 "sub",
434 "substr",
435 "symlink",
436 "syscall",
437 "sysread",
438 "sysseek",
439 "system",
440 "syswrite",
441 "tell",
442 "telldir",
443 "tie",
444 "tied",
445 "time",
446 "times"
447 "times",
448 "truncate",
449 "uc",
450 "ucfirst",
451 "umask",
452 "undef",
453 "unless",
454 "unlink",
455 "unpack",
456 "unshift",
457 "untie",
458 "until",
459 "use",
460 "utime",
461 "values",
462 "vec",
463 "wait",
464 "waitpid",
465 "wantarray",
466 "warn",
467 "while",
468 "write"
2d35d8ee 469 };
470
471
472/*
473 * Local functions...
474 */
475
476static int compare_keywords(const void *, const void *);
477static int getutf8(FILE *fp);
478
479
480/*
481 * 'TextMain()' - Standard main entry for text filters.
482 */
483
484int /* O - Exit status */
f6d46ae7 485TextMain(const char *name, /* I - Name of filter */
486 int argc, /* I - Number of command-line arguments */
487 char *argv[]) /* I - Command-line arguments */
2d35d8ee 488{
489 FILE *fp; /* Print file */
ed19bd98 490 ppd_file_t *ppd; /* PPD file */
2d35d8ee 491 int i, /* Looping var */
492 ch, /* Current char from file */
493 lastch, /* Previous char from file */
494 attr, /* Current attribute */
495 line, /* Current line */
496 column, /* Current column */
497 page_column; /* Current page column */
498 int num_options; /* Number of print options */
499 cups_option_t *options; /* Print options */
568d2c2f 500 const char *val; /* Option value */
2d35d8ee 501 char keyword[64], /* Keyword string */
502 *keyptr; /* Pointer into string */
503 int keycol; /* Column where keyword starts */
504 int ccomment; /* Inside a C-style comment? */
505 int cstring; /* Inside a C string */
506
507
cc787dc1 508 /*
509 * Make sure status messages are not buffered...
510 */
511
512 setbuf(stderr, NULL);
513
514 /*
515 * Check command-line...
516 */
517
2d35d8ee 518 if (argc < 6 || argc > 7)
519 {
520 fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n",
521 name);
522 return (1);
523 }
524
525 /*
526 * If we have 7 arguments, print the file named on the command-line.
527 * Otherwise, send stdin instead...
528 */
529
530 if (argc == 6)
531 fp = stdin;
532 else
533 {
534 /*
535 * Try to open the print file...
536 */
537
538 if ((fp = fopen(argv[6], "rb")) == NULL)
539 {
540 perror("ERROR: unable to open print file - ");
541 return (1);
542 }
543 }
544
545 /*
546 * Process command-line options and write the prolog...
547 */
548
549 options = NULL;
550 num_options = cupsParseOptions(argv[5], 0, &options);
551
75a4ca02 552 if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL)
553 {
75a4ca02 554 PageLeft = 72.0f;
555 PageRight = PageWidth - 36.0f;
556 PageBottom = PageBottom > 36.0f ? PageBottom : 36.0f;
5d4b6bc1 557 PageTop = PageLength - 36.0f;
75a4ca02 558 CharsPerInch = 12;
559 LinesPerInch = 8;
e2a4ce3e 560
561 if ((val = getenv("CONTENT_TYPE")) == NULL)
562 {
563 PrettyPrint = PRETTY_CODE;
564 NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
565 Keywords = code_keywords;
566 }
567 else if (strcasecmp(val, "application/x-cshell") == 0)
568 {
569 PrettyPrint = PRETTY_SHELL;
570 NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]);
571 Keywords = csh_keywords;
572 }
573 else if (strcasecmp(val, "application/x-perl") == 0)
574 {
575 PrettyPrint = PRETTY_PERL;
576 NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]);
577 Keywords = perl_keywords;
578 }
579 else if (strcasecmp(val, "application/x-shell") == 0)
580 {
581 PrettyPrint = PRETTY_SHELL;
582 NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]);
583 Keywords = sh_keywords;
584 }
585 else
586 {
587 PrettyPrint = PRETTY_CODE;
588 NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
589 Keywords = code_keywords;
590 }
75a4ca02 591 }
592
85569ef7 593 ppd = SetCommonOptions(num_options, options, 1);
5d4b6bc1 594
595 WrapLines = cupsGetOption("nowrap", num_options, options) == NULL;
596
597 if ((val = cupsGetOption("columns", num_options, options)) != NULL)
598 PageColumns = atoi(val);
599
2d35d8ee 600 if ((val = cupsGetOption("cpi", num_options, options)) != NULL)
601 CharsPerInch = atoi(val);
602
603 if ((val = cupsGetOption("lpi", num_options, options)) != NULL)
604 LinesPerInch = atoi(val);
605
5d4b6bc1 606 if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL)
607 PageTop -= 216.0f / LinesPerInch;
608
b1ac64aa 609 Copies = atoi(argv[4]);
610
f6d46ae7 611 WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
612 cupsGetOption("page-label", num_options, options), ppd);
2d35d8ee 613
614 /*
615 * Read text from the specified source and print it...
616 */
617
d21a7597 618 lastch = 0;
2d35d8ee 619 column = 0;
620 line = 0;
621 page_column = 0;
622 attr = 0;
623 keyptr = keyword;
624 keycol = 0;
625 ccomment = 0;
626 cstring = 0;
627
628 while ((ch = getutf8(fp)) >= 0)
629 {
630 /*
631 * Control codes:
632 *
633 * BS Backspace (0x08)
634 * HT Horizontal tab; next 8th column (0x09)
635 * LF Line feed; forward full line (0x0a)
636 * VT Vertical tab; reverse full line (0x0b)
637 * FF Form feed (0x0c)
638 * CR Carriage return (0x0d)
639 * ESC 7 Reverse full line (0x1b 0x37)
640 * ESC 8 Reverse half line (0x1b 0x38)
641 * ESC 9 Forward half line (0x1b 0x39)
642 */
643
644 switch (ch)
645 {
646 case 0x08 : /* BS - backspace for boldface & underline */
647 if (column > 0)
648 column --;
649
650 keyptr = keyword;
651 keycol = column;
652 break;
653
654 case 0x09 : /* HT - tab to next 8th column */
655 if (PrettyPrint && keyptr > keyword)
656 {
657 *keyptr = '\0';
658 keyptr = keyword;
659
e2a4ce3e 660 if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
661 compare_keywords))
2d35d8ee 662 {
663 /*
664 * Put keywords in boldface...
665 */
666
667 i = page_column * (ColumnWidth + ColumnGutter);
668
669 while (keycol < column)
670 {
671 Page[line][keycol + i].attr |= ATTR_BOLD;
672 keycol ++;
673 }
674 }
675 }
676
677 column = (column + 8) & ~7;
678
679 if (column >= ColumnWidth && WrapLines)
680 { /* Wrap text to margins */
681 line ++;
682 column = 0;
683
684 if (line >= SizeLines)
685 {
686 page_column ++;
687 line = 0;
688
689 if (page_column >= PageColumns)
690 {
691 WritePage();
692 page_column = 0;
693 }
694 }
695 }
696
697 keycol = column;
698 break;
699
700 case 0x0a : /* LF - output current line */
701 if (PrettyPrint && keyptr > keyword)
702 {
703 *keyptr = '\0';
704 keyptr = keyword;
705
e2a4ce3e 706 if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
707 compare_keywords))
2d35d8ee 708 {
709 /*
710 * Put keywords in boldface...
711 */
712
713 i = page_column * (ColumnWidth + ColumnGutter);
714
715 while (keycol < column)
716 {
717 Page[line][keycol + i].attr |= ATTR_BOLD;
718 keycol ++;
719 }
720 }
721 }
722
723 line ++;
724 column = 0;
725 keycol = 0;
726
727 if (!ccomment && !cstring)
728 attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
729
730 if (line >= SizeLines)
731 {
732 page_column ++;
733 line = 0;
734
735 if (page_column >= PageColumns)
736 {
737 WritePage();
738 page_column = 0;
739 }
740 }
741 break;
742
743 case 0x0b : /* VT - move up 1 line */
744 if (line > 0)
745 line --;
746
747 keyptr = keyword;
748 keycol = column;
749
750 if (!ccomment && !cstring)
751 attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
752 break;
753
754 case 0x0c : /* FF - eject current page... */
755 if (PrettyPrint && keyptr > keyword)
756 {
757 *keyptr = '\0';
758 keyptr = keyword;
759
e2a4ce3e 760 if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
761 compare_keywords))
2d35d8ee 762 {
763 /*
764 * Put keywords in boldface...
765 */
766
767 i = page_column * (ColumnWidth + ColumnGutter);
768
769 while (keycol < column)
770 {
771 Page[line][keycol + i].attr |= ATTR_BOLD;
772 keycol ++;
773 }
774 }
775 }
776
777 page_column ++;
778 column = 0;
779 keycol = 0;
780 line = 0;
781
782 if (!ccomment && !cstring)
783 attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
784
785 if (page_column >= PageColumns)
786 {
787 WritePage();
788 page_column = 0;
789 }
790 break;
791
792 case 0x0d : /* CR */
793 column = 0;
794 break;
795
796 case 0x1b : /* Escape sequence */
797 ch = getutf8(fp);
798 if (ch == '7')
799 {
800 /*
801 * ESC 7 Reverse full line (0x1b 0x37)
802 */
803
804 if (line > 0)
805 line --;
806 }
807 else if (ch == '8')
808 {
809 /*
810 * ESC 8 Reverse half line (0x1b 0x38)
811 */
812
813 if ((attr & ATTR_RAISED) && line > 0)
814 {
815 attr &= ~ATTR_RAISED;
816 line --;
817 }
818 else if (attr & ATTR_LOWERED)
819 attr &= ~ATTR_LOWERED;
820 else
821 attr |= ATTR_RAISED;
822 }
823 else if (ch == '9')
824 {
825 /*
826 * ESC 9 Forward half line (0x1b 0x39)
827 */
828
829 if ((attr & ATTR_LOWERED) && line < (SizeLines - 1))
830 {
831 attr &= ~ATTR_LOWERED;
832 line ++;
833 }
834 else if (attr & ATTR_RAISED)
835 attr &= ~ATTR_RAISED;
836 else
837 attr |= ATTR_LOWERED;
838 }
839 break;
840
841 default : /* All others... */
842 if (ch < ' ')
843 break; /* Ignore other control chars */
844
845 if (PrettyPrint)
846 {
847 /*
848 * Do highlighting of C/C++ keywords, preprocessor commands,
849 * and comments...
850 */
851
852 if ((ch == ' ' || ch == '\t') && (attr & ATTR_BOLD))
853 {
854 /*
855 * Stop bolding preprocessor command...
856 */
857
858 attr &= ~ATTR_BOLD;
859 }
c7fa9d06 860 else if (!(isalnum(ch) || ch == '_') && keyptr > keyword)
2d35d8ee 861 {
862 /*
863 * Look for a keyword...
864 */
865
866 *keyptr = '\0';
867 keyptr = keyword;
868
f5cc3283 869 if (!(attr & ATTR_ITALIC) &&
e2a4ce3e 870 bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
871 compare_keywords))
2d35d8ee 872 {
873 /*
874 * Put keywords in boldface...
875 */
876
877 i = page_column * (ColumnWidth + ColumnGutter);
878
879 while (keycol < column)
880 {
881 Page[line][keycol + i].attr |= ATTR_BOLD;
882 keycol ++;
883 }
884 }
885 }
c7fa9d06 886 else if ((isalnum(ch) || ch == '_') && !ccomment && !cstring)
2d35d8ee 887 {
888 /*
889 * Add characters to the current keyword (if they'll fit).
890 */
891
892 if (keyptr == keyword)
893 keycol = column;
894
895 if (keyptr < (keyword + sizeof(keyword) - 1))
896 *keyptr++ = ch;
897 }
898 else if (ch == '\"' && lastch != '\\' && !ccomment && !cstring)
899 {
900 /*
901 * Start a C string constant...
902 */
903
904 cstring = -1;
905 attr |= ATTR_BLUE;
906 }
e2a4ce3e 907 else if (ch == '*' && lastch == '/' && !cstring &&
908 PrettyPrint != PRETTY_SHELL)
2d35d8ee 909 {
910 /*
911 * Start a C-style comment...
912 */
913
914 ccomment = 1;
915 attr |= ATTR_ITALIC | ATTR_GREEN;
916 }
e2a4ce3e 917 else if (ch == '/' && lastch == '/' && !cstring &&
918 PrettyPrint == PRETTY_CODE)
2d35d8ee 919 {
920 /*
921 * Start a C++-style comment...
922 */
923
924 attr |= ATTR_ITALIC | ATTR_GREEN;
925 }
e2a4ce3e 926 else if (ch == '#' && !cstring && PrettyPrint != PRETTY_CODE)
927 {
928 /*
929 * Start a shell-style comment...
930 */
931
932 attr |= ATTR_ITALIC | ATTR_GREEN;
933 }
934 else if (ch == '#' && column == 0 && !ccomment && !cstring &&
935 PrettyPrint == PRETTY_CODE)
2d35d8ee 936 {
937 /*
938 * Start a preprocessor command...
939 */
940
941 attr |= ATTR_BOLD | ATTR_RED;
942 }
943 }
944
945 if (column >= ColumnWidth && WrapLines)
946 { /* Wrap text to margins */
947 column = 0;
948 line ++;
949
950 if (line >= SizeLines)
951 {
952 page_column ++;
953 line = 0;
954
955 if (page_column >= PageColumns)
956 {
957 WritePage();
958 page_column = 0;
959 }
960 }
961 }
962
963 /*
964 * Add text to the current column & line...
965 */
966
967 if (column < ColumnWidth)
968 {
969 i = column + page_column * (ColumnWidth + ColumnGutter);
970
971 if (PrettyPrint)
972 Page[line][i].attr = attr;
d5de5bef 973 else if (ch == ' ' && Page[line][i].ch)
974 ch = Page[line][i].ch;
2d35d8ee 975 else if (ch == Page[line][i].ch)
976 Page[line][i].attr |= ATTR_BOLD;
977 else if (Page[line][i].ch == '_')
978 Page[line][i].attr |= ATTR_UNDERLINE;
d5de5bef 979 else if (ch == '_')
980 {
981 Page[line][i].attr |= ATTR_UNDERLINE;
982
983 if (Page[line][i].ch)
984 ch = Page[line][i].ch;
985 }
2d35d8ee 986 else
987 Page[line][i].attr = attr;
988
989 Page[line][i].ch = ch;
990 }
991
992 if (PrettyPrint)
993 {
994 if ((ch == '{' || ch == '}') && !ccomment && !cstring &&
995 column < ColumnWidth)
996 {
997 /*
998 * Highlight curley braces...
999 */
1000
d21a7597 1001 Page[line][column].attr |= ATTR_BOLD;
2d35d8ee 1002 }
1003 else if ((ch == '/' || ch == '*') && lastch == '/' &&
e2a4ce3e 1004 column < ColumnWidth && PrettyPrint != PRETTY_SHELL)
2d35d8ee 1005 {
1006 /*
1007 * Highlight first comment character...
1008 */
1009
d21a7597 1010 Page[line][column - 1].attr = attr;
2d35d8ee 1011 }
1012 else if (ch == '\"' && lastch != '\\' && !ccomment && cstring > 0)
1013 {
1014 /*
1015 * End a C string constant...
1016 */
1017
1018 cstring = 0;
1019 attr &= ~ATTR_BLUE;
1020 }
1021 else if (ch == '/' && lastch == '*' && ccomment)
1022 {
1023 /*
1024 * End a C-style comment...
1025 */
1026
1027 ccomment = 0;
1028 attr &= ~(ATTR_ITALIC | ATTR_GREEN);
1029 }
1030
1031 if (cstring < 0)
1032 cstring = 1;
1033 }
1034
1035 column ++;
1036 break;
1037 }
1038
1039 /*
1040 * Save this character for the next cycle.
1041 */
1042
1043 lastch = ch;
1044 }
1045
1046 /*
1047 * Write any remaining page data...
1048 */
1049
1050 if (line > 0 || page_column > 0 || column > 0)
1051 WritePage();
1052
1053 /*
1054 * Write the epilog and return...
1055 */
1056
1057 WriteEpilogue();
1058
85569ef7 1059 if (ppd != NULL)
1060 ppdClose(ppd);
1061
2d35d8ee 1062 return (0);
1063}
1064
1065
1066/*
1067 * 'compare_keywords()' - Compare two C/C++ keywords.
1068 */
1069
1070static int /* O - Result of strcmp */
1071compare_keywords(const void *k1, /* I - First keyword */
1072 const void *k2) /* I - Second keyword */
1073{
1074 return (strcmp(*((const char **)k1), *((const char **)k2)));
1075}
1076
1077
1078/*
1079 * 'getutf8()' - Get a UTF-8 encoded wide character...
1080 */
1081
1082static int /* O - Character or -1 on error */
1083getutf8(FILE *fp) /* I - File to read from */
1084{
1085 int ch; /* Current character value */
1086 int next; /* Next character from file */
1087
1088
1089 /*
1090 * Read the first character and process things accordingly...
1091 *
1092 * UTF-8 maps 16-bit characters to:
1093 *
1094 * 0 to 127 = 0xxxxxxx
1095 * 128 to 2047 = 110xxxxx 10yyyyyy (xxxxxyyyyyy)
1096 * 2048 to 65535 = 1110xxxx 10yyyyyy 10zzzzzz (xxxxyyyyyyzzzzzz)
1097 *
1098 * We also accept:
1099 *
1100 * 128 to 191 = 10xxxxxx
1101 *
1102 * since this range of values is otherwise undefined unless you are
1103 * in the middle of a multi-byte character...
1104 *
1105 * This code currently does not support anything beyond 16-bit
1106 * characters, in part because PostScript doesn't support more than
1107 * 16-bit characters...
1108 */
1109
1110 if ((ch = getc(fp)) == EOF)
1111 return (EOF);
1112
1113 if (ch < 0xc0 || !UTF8) /* One byte character? */
1114 return (ch);
1115 else if ((ch & 0xe0) == 0xc0)
1116 {
1117 /*
1118 * Two byte character...
1119 */
1120
1121 if ((next = getc(fp)) == EOF)
1122 return (EOF);
1123 else
1124 return (((ch & 0x1f) << 6) | (next & 0x3f));
1125 }
1126 else if ((ch & 0xf0) == 0xe0)
1127 {
1128 /*
1129 * Three byte character...
1130 */
1131
1132 if ((next = getc(fp)) == EOF)
1133 return (EOF);
1134
1135 ch = ((ch & 0x0f) << 6) | (next & 0x3f);
1136
1137 if ((next = getc(fp)) == EOF)
1138 return (EOF);
1139 else
1140 return ((ch << 6) | (next & 0x3f));
1141 }
1142 else
1143 {
1144 /*
1145 * More than three bytes... We don't support that...
1146 */
1147
1148 return (EOF);
1149 }
1150}
1151
1152
1153/*
efb2f309 1154 * End of "$Id: textcommon.c,v 1.19 2002/01/02 17:59:01 mike Exp $".
2d35d8ee 1155 */