home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / cawf407.zip / src / device.c < prev    next >
C/C++ Source or Header  |  1993-12-28  |  9KB  |  420 lines

  1. /*
  2.  *    device.c -- cawf(1) output device support functions
  3.  */
  4.  
  5. /*
  6.  *    Copyright (c) 1991 Purdue University Research Foundation,
  7.  *    West Lafayette, Indiana 47907.  All rights reserved.
  8.  *
  9.  *    Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  10.  *    University Computing Center.  Not derived from licensed software;
  11.  *    derived from awf(1) by Henry Spencer of the University of Toronto.
  12.  *
  13.  *    Permission is granted to anyone to use this software for any
  14.  *    purpose on any computer system, and to alter it and redistribute
  15.  *    it freely, subject to the following restrictions:
  16.  *
  17.  *    1. The author is not responsible for any consequences of use of
  18.  *       this software, even if they arise from flaws in it.
  19.  *
  20.  *    2. The origin of this software must not be misrepresented, either
  21.  *       by explicit claim or by omission.  Credits must appear in the
  22.  *       documentation.
  23.  *
  24.  *    3. Altered versions must be plainly marked as such, and must not
  25.  *       be misrepresented as being the original software.  Credits must
  26.  *       appear in the documentation.
  27.  *
  28.  *    4. This notice may not be removed or altered.
  29.  */
  30.  
  31. #include "cawf.h"
  32. #include <ctype.h>
  33.  
  34. _PROTOTYPE(static unsigned char *Convstr,(char *s, int *len));
  35. _PROTOTYPE(static int Convfont,(char *nm, char *s, char **fn,
  36.     unsigned char **fi));
  37.  
  38. #ifdef    __EMX__
  39. #define    strcasecmp    stricmp
  40. #else    /* not __EMX__ */
  41. # ifndef    UNIX
  42. #define    strcasecmp    strcmpi
  43. # endif    /* not UNIX */
  44. #endif    /* __EMX__ */
  45.  
  46.  
  47.  
  48. /*
  49.  * Convstr(s, len) - convert a string
  50.  */
  51.  
  52. static unsigned char *
  53. Convstr(s, len)
  54.     char *s;            /* input string */
  55.     int *len;            /* length of result */
  56. {
  57.     int c;                /* character assembly */
  58.     unsigned char *cp;        /* temporary character pointer */
  59.     char *em;            /* error message */
  60.     int i;                /* temporary index */
  61.     int l;                /* length */
  62.     unsigned char *r;        /* result string */
  63. /*
  64.  * Make space for the result.
  65.  */
  66.     if ((r = (unsigned char *)malloc(strlen((char *)s) + 1)) == NULL) {
  67.         (void) fprintf(stderr, "%s: out of string space at %s\n",
  68.             Pname, s);
  69.         return(NULL);
  70.     }
  71. /*
  72.  * Copy the input string to the result, processing '\\' escapes.
  73.  */
  74.     for (cp = r, l = 0; *s;) {
  75.         switch (*s) {
  76.  
  77.         case '\\':
  78.             s++;
  79.             if (*s >= '0' && *s <= '7') {
  80.         /*
  81.          * '\xxx' -- octal form
  82.          */
  83.                 for (c = i = 0; i < 3; i++, s++) {
  84.                     if (*s < '0' || *s > '7') {
  85.                         em = "non-octal char";
  86. bad_string:
  87.                         (void) fprintf(stderr,
  88.                             "%s: %s : %s\n",
  89.                             Pname, em, (char *)r);
  90.                         return(NULL);
  91.                     }
  92.                     c = (c << 3) + *s - '0';
  93.                 }
  94.                 if (c > 0377) {
  95.                     em = "octal char > 0377";
  96.                     goto bad_string;
  97.                 }
  98.                 *cp++ = c;
  99.                 l++;
  100.             } else if (*s == 'x') {
  101.         /*
  102.          * '\xyy' -- hexadecimal form
  103.          */
  104.                 s++;
  105.                 for (c = i = 0; i < 2; i++, s++) {
  106. #if    defined(__STDC__)
  107.                     if ( ! isalpha(*s) && ! isdigit(*s))
  108. #else
  109.                     if ( ! isascii(*s) && ! isalpha(*s)
  110.                     &&   ! isdigit(*s))
  111. #endif
  112.                     {
  113. non_hex_char:
  114.                         em = "non-hex char";
  115.                         goto bad_string;
  116.                     }
  117.                     c = c << 4;
  118.                     if (*s >= '0' && *s <= '9')
  119.                         c += *s - '0';
  120.                     else if ((*s >= 'a' && *s <= 'f')
  121.                          ||  (*s >= 'A' && *s <= 'F'))
  122.                         c += *s + 10 -
  123.                              (isupper(*s) ? 'A' : 'a');
  124.                     else
  125.                         goto non_hex_char;
  126.                 }
  127.                 *cp++ = (unsigned char)c;
  128.                 l++;
  129.             } else if (*s == 'E' || *s == 'e') {
  130.         /*
  131.          * '\E' or '\e' -- ESCape
  132.          */
  133.                 *cp++ = ESC;
  134.                 l++;
  135.                 s++;
  136.             } else if (*s == '\0') {
  137.                 em = "no char after \\";
  138.                 goto bad_string;
  139.             } else {
  140.         /*
  141.          * escaped character (for some reason)
  142.          */
  143.                 *cp++ = *s++;
  144.                 l++;
  145.             }
  146.             break;
  147.     /*
  148.      * Copy a "normal" character.
  149.      */
  150.         default:
  151.             *cp++ = *s++;
  152.             l++;
  153.         }
  154.     }
  155.     *cp = '\0';
  156.     *len = l;
  157.     return(r);
  158. }
  159.  
  160.  
  161. /*
  162.  * Convfont(nm, s, fn, fi) - convert a font for a device
  163.  */
  164.  
  165. static int
  166. Convfont(nm, s, fn, fi)
  167.     char *nm;            /* output device name */
  168.     char *s;            /* font definition string */
  169.     char **fn;            /* font name address */
  170.     unsigned char **fi;        /* initialization string address */
  171. {
  172.     char *cp;            /* temporary character pointer */
  173.     int len;            /* length */
  174. /*
  175.  * Get the font name, allocate space for it and allocate space for
  176.  * a font structure.
  177.  */
  178.     if ((cp = strchr(s, '=')) == NULL) {
  179.         (void) fprintf(stderr, "%s: bad %s font line format: %s\n",
  180.             Pname, nm, s);
  181.         return(0);
  182.     }
  183.     if ((*fn = (char *)malloc(cp - s + 1)) == NULL) {
  184.         (void) fprintf(stderr, "%s: no space for %s font name %s\n",
  185.             Pname, nm, s);
  186.         return(0);
  187.     }
  188.     (void) strncpy(*fn, s, cp - s);
  189.     (*fn)[cp - s] = '\0';
  190. /*
  191.  * Assmble the font initialization string.
  192.  */
  193.     if ((*fi = Convstr(cp + 1, &len)) == NULL)
  194.         return(0);
  195.     return(len);
  196. }
  197.  
  198.  
  199. /*
  200.  * Defdev() - define the output device
  201.  */
  202.  
  203. int
  204. Defdev()
  205. {
  206.     unsigned char *fi = NULL;    /* last font initialization string */
  207.     char *fn = NULL;        /* font name */
  208.     int fd = 0;            /* found-device flag */
  209.     FILE *fs;            /* file stream */
  210.     int err = 0;            /* errror count */
  211.     int i;                /* temporary index */
  212.     int len;            /* length */
  213.     char line[MAXLINE];        /* line buffer */
  214.     char *p;            /* output device configuration file */
  215.     char *s;            /* temporary string pointer */
  216. /*
  217.  * Check for the built-in devices, ANSI, NONE or NORMAL (default).
  218.  */
  219.     Fstr.b = Fstr.i = Fstr.it = Fstr.r = NULL;
  220.     Fstr.bl = Fstr.il = Fstr.itl = Fstr.rl = 0;
  221.     if (Device == NULL || strcasecmp(Device, "normal") == 0) {
  222.         Fontctl = 0;
  223. check_font:
  224.         if (Devfont) {
  225.             (void) fprintf(stderr,
  226.                 "%s: font %s for device %s illegal\n",
  227.                 Pname, Devfont, Device ? Device : "NORMAL");
  228.             return(1);
  229.         }
  230.         return(0);
  231.     }
  232.     Fontctl = 1;
  233.     if (strcasecmp(Device, "ansi") == 0) {
  234.         Fstr.b = Newstr((unsigned char *)"x[7m");
  235.         Fstr.it = Newstr((unsigned char *)"x[4m");
  236.         Fstr.r = Newstr((unsigned char *)"x[0m");
  237.         Fstr.b[0] = Fstr.it[0] = Fstr.r[0] = ESC;
  238.         Fstr.bl = Fstr.itl = Fstr.rl = 4;
  239.         goto check_font;
  240.     }
  241.     if (strcasecmp(Device, "none") == 0)
  242.         goto check_font;
  243. /*
  244.  * If a device configuration file path is supplied, use it.
  245.  */
  246.     if (Devconf)
  247.         p = Devconf;
  248.     else {
  249.  
  250.     /*
  251.      * Use the CAWFLIB environment if it is defined.
  252.      */
  253.         if ((p = getenv("CAWFLIB")) == NULL)    
  254.             p = CAWFLIB;
  255.         len = strlen(p) + 1 + strlen(DEVCONFIG) + 1;
  256.         if ((s = (char *)malloc(len)) == NULL) {
  257.             (void) fprintf(stderr, "%s: no space for %s name\n",
  258.                 Pname, DEVCONFIG);
  259.             return(1);
  260.         }
  261.         (void) sprintf(s, "%s/%s", p, DEVCONFIG);
  262.         p = s;
  263.     }
  264. /*
  265.  * Open the configuration file.
  266.  */
  267. #ifdef    UNIX
  268.     if ((fs = fopen(p, "r")) == NULL)
  269. #else
  270.     if ((fs = fopen(p, "rt")) == NULL)
  271. #endif
  272.     {
  273.         (void) fprintf(stderr, "%s: can't open config file: %s\n",
  274.             Pname, p);
  275.         return(1);
  276.     }
  277.     *line = ' ';
  278. /*
  279.  * Look for a device definition line -- a line that begins with a name.
  280.  */
  281.     while ( ! feof(fs)) {
  282.         if (*line == '\t' || *line == '#' || *line == ' ') {
  283.             (void) fgets(line, MAXLINE, fs);
  284.             continue;
  285.         }
  286.         if ((s = strrchr(line, '\n')) != NULL)
  287.             *s = '\0';
  288.         else
  289.             line[MAXLINE-1] = '\0';
  290.     /*
  291.      * Match device name.
  292.      */
  293.         if (strcmp(Device, line) != 0) {
  294.             (void) fgets(line, MAXLINE, fs);
  295.             continue;
  296.         }
  297.         fd = 1;
  298.     /*
  299.      * Read the parameter lines for the device.
  300.      */
  301.         while (fgets(line, MAXLINE, fs) != NULL) {
  302.             if (*line == ' ') {
  303.                 for (i = 1; line[i] == ' '; i++)
  304.                     ;
  305.             } else if (*line == '\t')
  306.                 i = 1;
  307.             else
  308.                 break;
  309. #if    defined(__STDC__)
  310.             if ( ! isalpha(line[i])
  311. #else
  312.             if ( ! isascii(line[i]) || ! isalpha(line[i])
  313. #endif
  314.             ||   line[i+1] != '=')
  315.                 break;
  316.             if ((s = strrchr(line, '\n')) != NULL)
  317.                 *s = '\0';
  318.             else
  319.                 line[MAXLINE-1] = '\0';
  320.             switch (line[i]) {
  321.         /*
  322.          * \tb=<bolding_string>
  323.          */
  324.             case 'b':
  325.                 if (Fstr.b != NULL) {
  326.                     (void) fprintf(stderr,
  327.                     "%s: dup bold for %s in %s: %s\n",
  328.                     Pname, Device, p, line);
  329.                     (void) free(Fstr.b);
  330.                     Fstr.b = NULL;
  331.                 }
  332.                 if ((Fstr.b = Convstr(&line[i+2], &Fstr.bl))
  333.                 == NULL)
  334.                     err++;
  335.                 break;
  336.         /*
  337.          * \ti=<italicization_string>
  338.          */
  339.             case 'i':
  340.                 if (Fstr.it != NULL) {
  341.                     (void) fprintf(stderr,
  342.                     "%s: dup italic for %s in %s: %s\n",
  343.                     Pname, Device, p, line);
  344.                     (void) free(Fstr.it);
  345.                     Fstr.it = NULL;
  346.                 }
  347.                 if ((Fstr.it = Convstr(&line[i+2], &Fstr.itl))
  348.                 == NULL)
  349.                     err++;
  350.                 break;
  351.         /*
  352.          * \tr=<return_to_Roman_string>
  353.          */
  354.             case 'r':
  355.                 if (Fstr.r != NULL) {
  356.                     (void) fprintf(stderr,
  357.                     "%s: dup roman for %s in %s: %s\n",
  358.                     Pname, Device, p, line);
  359.                     (void) free(Fstr.r);
  360.                     Fstr.r = NULL;
  361.                 }
  362.                 if ((Fstr.r = Convstr(&line[i+2], &Fstr.rl))
  363.                 == NULL)
  364.                     err++;
  365.                 break;
  366.         /*
  367.          * \tf=<font_name>=<font_initialization_string>
  368.          */
  369.             case 'f':
  370.                 if ( ! Devfont || Fstr.i)
  371.                     break;
  372.                 if ((i = Convfont(Device, &line[i+2], &fn, &fi))
  373.                 < 0)
  374.                     err++;
  375.                 else if (fn && strcmp(Devfont, fn) == 0) {
  376.                     Fstr.i = fi;
  377.                     Fstr.il = i;
  378.                     fi = NULL;
  379.                 }
  380.                 if (fn) {
  381.                     (void) free(fn);
  382.                     fn = NULL;
  383.                 }
  384.                 if (fi) {
  385.                     (void) free((char *)fi);
  386.                     fi = NULL;
  387.                 }
  388.                 break;
  389.         /*
  390.          * ????
  391.          */
  392.             default:
  393.                 (void) fprintf(stderr,
  394.                     "%s: unknown device %s line: %s\n",
  395.                     Pname, Device, line);
  396.                 err++;
  397.             }
  398.         }
  399.         break;
  400.     }
  401.     (void) fclose(fs);
  402.     if (err)
  403.         return(1);
  404. /*
  405.  * See if the device stanza was located and the font exists.
  406.  */
  407.     if ( ! fd) {
  408.         (void) fprintf(stderr, "%s: can't find device %s in %s\n",
  409.             Pname, Device, p);
  410.         return(1);
  411.     }
  412.     if (Devfont && ! Fstr.i) {
  413.         (void) fprintf(stderr,
  414.             "%s: font %s for device %s not found in %s\n",
  415.             Pname, Devfont, Device, p);
  416.         return(1);
  417.     }
  418.     return(0);
  419. }
  420.