home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2995 / charset.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-06  |  3.2 KB  |  191 lines

  1. /*
  2.  * Functions to define the character set
  3.  * and do things specific to the character set.
  4.  */
  5.  
  6. #include "less.h"
  7.  
  8. /*
  9.  * Predefined character sets,
  10.  * selected by the LESSCHARSET environment variable.
  11.  */
  12. struct charset {
  13.     char *name;
  14.     char *desc;
  15. } charsets[] = {
  16.     { "ascii",    "8bcccbcc18b95.b"    },
  17.     { "latin1",    "8bcccbcc18b95.33b."    },
  18.     { NULL }
  19. };
  20.  
  21. #define    IS_BINARY_CHAR    01
  22. #define    IS_CONTROL_CHAR    02
  23.  
  24. static char chardef[256];
  25. static char *binfmt = "\\%o";
  26.  
  27. extern char *getenv();
  28.  
  29. /*
  30.  * Define a charset, given a description string.
  31.  * The string consists of 256 letters,
  32.  * one for each character in the charset.
  33.  * If the string is shorter than 256 letters, missing letters
  34.  * are taken to be identical to the last one.
  35.  * A decimal number followed by a letter is taken to be a 
  36.  * repetition of the letter.
  37.  *
  38.  * Each letter is one of:
  39.  *    . normal character
  40.  *    b binary character
  41.  *    c control character
  42.  */
  43.     static void
  44. ichardef(s)
  45.     char *s;
  46. {
  47.     register char *cp;
  48.     register int n;
  49.     register char v;
  50.  
  51.     n = 0;
  52.     cp = chardef;
  53.     while (*s != '\0')
  54.     {
  55.         switch (*s++)
  56.         {
  57.         case '.':
  58.             v = 0;
  59.             break;
  60.         case 'c':
  61.             v = IS_CONTROL_CHAR;
  62.             break;
  63.         case 'b':
  64.             v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
  65.             break;
  66.  
  67.         case '0': case '1': case '2': case '3': case '4':
  68.         case '5': case '6': case '7': case '8': case '9':
  69.             n = (10 * n) + (s[-1] - '0');
  70.             continue;
  71.  
  72.         default:
  73.             error("invalid chardef", NULL_PARG);
  74.             quit(1);
  75.             /*NOTREACHED*/
  76.         }
  77.  
  78.         do
  79.         {
  80.             if (cp >= chardef + sizeof(chardef))
  81.             {
  82.                 error("chardef longer than 256", NULL_PARG);
  83.                 quit(1);
  84.                 /*NOTREACHED*/
  85.             }
  86.             *cp++ = v;
  87.         } while (--n > 0);
  88.         n = 0;
  89.     }
  90.  
  91.     while (cp < chardef + sizeof(chardef))
  92.         *cp++ = v;
  93. }
  94.  
  95. /*
  96.  * Define a charset, given a charset name.
  97.  * The valid charset names are listed in the "charsets" array.
  98.  */
  99.     static int
  100. icharset(name)
  101.     register char *name;
  102. {
  103.     register struct charset *p;
  104.  
  105.     if (name == NULL || *name == '\0')
  106.         return (0);
  107.  
  108.     for (p = charsets;  p->name != NULL;  p++)
  109.     {
  110.         if (strcmp(name, p->name) == 0)
  111.         {
  112.             ichardef(p->desc);
  113.             return (1);
  114.         }
  115.     }
  116.  
  117.     error("invalid charset name", NULL_PARG);
  118.     quit(1);
  119.     /*NOTREACHED*/
  120. }
  121.  
  122. /*
  123.  * Initialize charset data structures.
  124.  */
  125.     public void
  126. init_charset()
  127. {
  128.     register char *s;
  129.  
  130.     /*
  131.      * Try environment variable LESSCHARSET.
  132.      * If LESSCHARSET is not set, try LESSCHARDEF.
  133.      * If LESSCHARDEF is not set, default to "ascii" charset.
  134.      */
  135.     s = getenv("LESSCHARSET");
  136.     if (icharset(s))
  137.         return;
  138.  
  139.     s = getenv("LESSCHARDEF");
  140.     if (s != NULL && *s != '\0')
  141.     {
  142.         ichardef(s);
  143.         return;
  144.     }
  145.  
  146.     (void) icharset("ascii");
  147.  
  148.     s = getenv("LESSBINFMT");
  149.     if (s != NULL && *s != '\0')
  150.         binfmt = s;
  151. }
  152.  
  153. /*
  154.  * Is a given character a "binary" character?
  155.  */
  156.     public int
  157. binary_char(c)
  158.     int c;
  159. {
  160.     return (chardef[c] & IS_BINARY_CHAR);
  161. }
  162.  
  163. /*
  164.  * Is a given character a "control" character?
  165.  */
  166.     public int
  167. control_char(c)
  168.     int c;
  169. {
  170.     return (chardef[c] & IS_CONTROL_CHAR);
  171. }
  172.  
  173. /*
  174.  * Return the printable form of a character.
  175.  * For example, in the "ascii" charset '\3' is printed as "^C".
  176.  */
  177.     public char *
  178. prchar(c)
  179.     int c;
  180. {
  181.     static char buf[8];
  182.  
  183.     if (!control_char(c))
  184.         sprintf(buf, "%c", c);
  185.     else if (!control_char(c ^ 0100))
  186.         sprintf(buf, "^%c", c ^ 0100);
  187.     else
  188.         sprintf(buf, binfmt, c);
  189.     return (buf);
  190. }
  191.