home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / slackwar / a / util / util-lin.2 / util-lin / util-linux-2.2 / text-utils / ul.c < prev   
Encoding:
C/C++ Source or Header  |  1995-02-22  |  10.2 KB  |  509 lines

  1. /*
  2.  * Copyright (c) 1980, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char copyright[] =
  36. "@(#) Copyright (c) 1980, 1993\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)ul.c    8.1 (Berkeley) 6/6/93";
  42. #endif /* not lint */
  43.  
  44. #include <stdio.h>
  45.  
  46. #define    IESC    '\033'
  47. #define    SO    '\016'
  48. #define    SI    '\017'
  49. #define    HFWD    '9'
  50. #define    HREV    '8'
  51. #define    FREV    '7'
  52. #define    MAXBUF    512
  53.  
  54. #define    NORMAL    000
  55. #define    ALTSET    001    /* Reverse */
  56. #define    SUPERSC    002    /* Dim */
  57. #define    SUBSC    004    /* Dim | Ul */
  58. #define    UNDERL    010    /* Ul */
  59. #define    BOLD    020    /* Bold */
  60.  
  61. int    must_use_uc, must_overstrike;
  62. char    *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
  63.     *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
  64.     *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
  65.  
  66. struct    CHAR    {
  67.     char    c_mode;
  68.     char    c_char;
  69. } ;
  70.  
  71. struct    CHAR    obuf[MAXBUF];
  72. int    col, maxcol;
  73. int    mode;
  74. int    halfpos;
  75. int    upln;
  76. int    iflag;
  77.  
  78. int    outchar();
  79. #define    PRINT(s)    if (s == NULL) /* void */; else tputs(s, 1, outchar)
  80.  
  81. main(argc, argv)
  82.     int argc;
  83.     char **argv;
  84. {
  85.     extern int optind;
  86.     extern char *optarg;
  87.     int c;
  88.     char *termtype;
  89.     FILE *f;
  90.     char termcap[1024];
  91.     char *getenv(), *strcpy();
  92.  
  93.     termtype = getenv("TERM");
  94.     if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
  95.         termtype = "lpr";
  96.     while ((c=getopt(argc, argv, "it:T:")) != EOF)
  97.         switch(c) {
  98.  
  99.         case 't':
  100.         case 'T': /* for nroff compatibility */
  101.                 termtype = optarg;
  102.             break;
  103.         case 'i':
  104.             iflag = 1;
  105.             break;
  106.  
  107.         default:
  108.             fprintf(stderr,
  109.                 "usage: %s [ -i ] [ -tTerm ] file...\n",
  110.                 argv[0]);
  111.             exit(1);
  112.         }
  113.  
  114.     switch(tgetent(termcap, termtype)) {
  115.  
  116.     case 1:
  117.         break;
  118.  
  119.     default:
  120.         fprintf(stderr,"trouble reading termcap");
  121.         /* fall through to ... */
  122.  
  123.     case 0:
  124.         /* No such terminal type - assume dumb */
  125.         (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
  126.         break;
  127.     }
  128.     initcap();
  129.     if (    (tgetflag("os") && ENTER_BOLD==NULL ) ||
  130.         (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
  131.             must_overstrike = 1;
  132.     initbuf();
  133.     if (optind == argc)
  134.         filter(stdin);
  135.     else for (; optind<argc; optind++) {
  136.         f = fopen(argv[optind],"r");
  137.         if (f == NULL) {
  138.             perror(argv[optind]);
  139.             exit(1);
  140.         } else
  141.             filter(f);
  142.     }
  143.     exit(0);
  144. }
  145.  
  146. filter(f)
  147.     FILE *f;
  148. {
  149.     register c;
  150.  
  151.     while ((c = getc(f)) != EOF) switch(c) {
  152.  
  153.     case '\b':
  154.         if (col > 0)
  155.             col--;
  156.         continue;
  157.  
  158.     case '\t':
  159.         col = (col+8) & ~07;
  160.         if (col > maxcol)
  161.             maxcol = col;
  162.         continue;
  163.  
  164.     case '\r':
  165.         col = 0;
  166.         continue;
  167.  
  168.     case SO:
  169.         mode |= ALTSET;
  170.         continue;
  171.  
  172.     case SI:
  173.         mode &= ~ALTSET;
  174.         continue;
  175.  
  176.     case IESC:
  177.         switch (c = getc(f)) {
  178.  
  179.         case HREV:
  180.             if (halfpos == 0) {
  181.                 mode |= SUPERSC;
  182.                 halfpos--;
  183.             } else if (halfpos > 0) {
  184.                 mode &= ~SUBSC;
  185.                 halfpos--;
  186.             } else {
  187.                 halfpos = 0;
  188.                 reverse();
  189.             }
  190.             continue;
  191.  
  192.         case HFWD:
  193.             if (halfpos == 0) {
  194.                 mode |= SUBSC;
  195.                 halfpos++;
  196.             } else if (halfpos < 0) {
  197.                 mode &= ~SUPERSC;
  198.                 halfpos++;
  199.             } else {
  200.                 halfpos = 0;
  201.                 fwd();
  202.             }
  203.             continue;
  204.  
  205.         case FREV:
  206.             reverse();
  207.             continue;
  208.  
  209.         default:
  210.             fprintf(stderr,
  211.                 "Unknown escape sequence in input: %o, %o\n",
  212.                 IESC, c);
  213.             exit(1);
  214.         }
  215.         continue;
  216.  
  217.     case '_':
  218.         if (obuf[col].c_char)
  219.             obuf[col].c_mode |= UNDERL | mode;
  220.         else
  221.             obuf[col].c_char = '_';
  222.     case ' ':
  223.         col++;
  224.         if (col > maxcol)
  225.             maxcol = col;
  226.         continue;
  227.  
  228.     case '\n':
  229.         flushln();
  230.         continue;
  231.  
  232.     case '\f':
  233.         flushln();
  234.         putchar('\f');
  235.         continue;
  236.  
  237.     default:
  238.         if (c < ' ')    /* non printing */
  239.             continue;
  240.         if (obuf[col].c_char == '\0') {
  241.             obuf[col].c_char = c;
  242.             obuf[col].c_mode = mode;
  243.         } else if (obuf[col].c_char == '_') {
  244.             obuf[col].c_char = c;
  245.             obuf[col].c_mode |= UNDERL|mode;
  246.         } else if (obuf[col].c_char == c)
  247.             obuf[col].c_mode |= BOLD|mode;
  248.         else
  249.             obuf[col].c_mode = mode;
  250.         col++;
  251.         if (col > maxcol)
  252.             maxcol = col;
  253.         continue;
  254.     }
  255.     if (maxcol)
  256.         flushln();
  257. }
  258.  
  259. flushln()
  260. {
  261.     register lastmode;
  262.     register i;
  263.     int hadmodes = 0;
  264.  
  265.     lastmode = NORMAL;
  266.     for (i=0; i<maxcol; i++) {
  267.         if (obuf[i].c_mode != lastmode) {
  268.             hadmodes++;
  269.             setmode(obuf[i].c_mode);
  270.             lastmode = obuf[i].c_mode;
  271.         }
  272.         if (obuf[i].c_char == '\0') {
  273.             if (upln)
  274.                 PRINT(CURS_RIGHT);
  275.             else
  276.                 outc(' ');
  277.         } else
  278.             outc(obuf[i].c_char);
  279.     }
  280.     if (lastmode != NORMAL) {
  281.         setmode(0);
  282.     }
  283.     if (must_overstrike && hadmodes)
  284.         overstrike();
  285.     putchar('\n');
  286.     if (iflag && hadmodes)
  287.         iattr();
  288.     (void)fflush(stdout);
  289.     if (upln)
  290.         upln--;
  291.     initbuf();
  292. }
  293.  
  294. /*
  295.  * For terminals that can overstrike, overstrike underlines and bolds.
  296.  * We don't do anything with halfline ups and downs, or Greek.
  297.  */
  298. overstrike()
  299. {
  300.     register int i;
  301.     char lbuf[256];
  302.     register char *cp = lbuf;
  303.     int hadbold=0;
  304.  
  305.     /* Set up overstrike buffer */
  306.     for (i=0; i<maxcol; i++)
  307.         switch (obuf[i].c_mode) {
  308.         case NORMAL:
  309.         default:
  310.             *cp++ = ' ';
  311.             break;
  312.         case UNDERL:
  313.             *cp++ = '_';
  314.             break;
  315.         case BOLD:
  316.             *cp++ = obuf[i].c_char;
  317.             hadbold=1;
  318.             break;
  319.         }
  320.     putchar('\r');
  321.     for (*cp=' '; *cp==' '; cp--)
  322.         *cp = 0;
  323.     for (cp=lbuf; *cp; cp++)
  324.         putchar(*cp);
  325.     if (hadbold) {
  326.         putchar('\r');
  327.         for (cp=lbuf; *cp; cp++)
  328.             putchar(*cp=='_' ? ' ' : *cp);
  329.         putchar('\r');
  330.         for (cp=lbuf; *cp; cp++)
  331.             putchar(*cp=='_' ? ' ' : *cp);
  332.     }
  333. }
  334.  
  335. iattr()
  336. {
  337.     register int i;
  338.     char lbuf[256];
  339.     register char *cp = lbuf;
  340.  
  341.     for (i=0; i<maxcol; i++)
  342.         switch (obuf[i].c_mode) {
  343.         case NORMAL:    *cp++ = ' '; break;
  344.         case ALTSET:    *cp++ = 'g'; break;
  345.         case SUPERSC:    *cp++ = '^'; break;
  346.         case SUBSC:    *cp++ = 'v'; break;
  347.         case UNDERL:    *cp++ = '_'; break;
  348.         case BOLD:    *cp++ = '!'; break;
  349.         default:    *cp++ = 'X'; break;
  350.         }
  351.     for (*cp=' '; *cp==' '; cp--)
  352.         *cp = 0;
  353.     for (cp=lbuf; *cp; cp++)
  354.         putchar(*cp);
  355.     putchar('\n');
  356. }
  357.  
  358. initbuf()
  359. {
  360.  
  361.     bzero((char *)obuf, sizeof (obuf));    /* depends on NORMAL == 0 */
  362.     col = 0;
  363.     maxcol = 0;
  364.     mode &= ALTSET;
  365. }
  366.  
  367. fwd()
  368. {
  369.     register oldcol, oldmax;
  370.  
  371.     oldcol = col;
  372.     oldmax = maxcol;
  373.     flushln();
  374.     col = oldcol;
  375.     maxcol = oldmax;
  376. }
  377.  
  378. reverse()
  379. {
  380.     upln++;
  381.     fwd();
  382.     PRINT(CURS_UP);
  383.     PRINT(CURS_UP);
  384.     upln++;
  385. }
  386.  
  387. initcap()
  388. {
  389.     static char tcapbuf[512];
  390.     char *bp = tcapbuf;
  391.     char *getenv(), *tgetstr();
  392.  
  393.     /* This nonsense attempts to work with both old and new termcap */
  394.     CURS_UP =        tgetstr("up", &bp);
  395.     CURS_RIGHT =        tgetstr("ri", &bp);
  396.     if (CURS_RIGHT == NULL)
  397.         CURS_RIGHT =    tgetstr("nd", &bp);
  398.     CURS_LEFT =        tgetstr("le", &bp);
  399.     if (CURS_LEFT == NULL)
  400.         CURS_LEFT =    tgetstr("bc", &bp);
  401.     if (CURS_LEFT == NULL && tgetflag("bs"))
  402.         CURS_LEFT =    "\b";
  403.  
  404.     ENTER_STANDOUT =    tgetstr("so", &bp);
  405.     EXIT_STANDOUT =        tgetstr("se", &bp);
  406.     ENTER_UNDERLINE =    tgetstr("us", &bp);
  407.     EXIT_UNDERLINE =    tgetstr("ue", &bp);
  408.     ENTER_DIM =        tgetstr("mh", &bp);
  409.     ENTER_BOLD =        tgetstr("md", &bp);
  410.     ENTER_REVERSE =        tgetstr("mr", &bp);
  411.     EXIT_ATTRIBUTES =    tgetstr("me", &bp);
  412.  
  413.     if (!ENTER_BOLD && ENTER_REVERSE)
  414.         ENTER_BOLD = ENTER_REVERSE;
  415.     if (!ENTER_BOLD && ENTER_STANDOUT)
  416.         ENTER_BOLD = ENTER_STANDOUT;
  417.     if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
  418.         ENTER_UNDERLINE = ENTER_STANDOUT;
  419.         EXIT_UNDERLINE = EXIT_STANDOUT;
  420.     }
  421.     if (!ENTER_DIM && ENTER_STANDOUT)
  422.         ENTER_DIM = ENTER_STANDOUT;
  423.     if (!ENTER_REVERSE && ENTER_STANDOUT)
  424.         ENTER_REVERSE = ENTER_STANDOUT;
  425.     if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
  426.         EXIT_ATTRIBUTES = EXIT_STANDOUT;
  427.     
  428.     /*
  429.      * Note that we use REVERSE for the alternate character set,
  430.      * not the as/ae capabilities.  This is because we are modelling
  431.      * the model 37 teletype (since that's what nroff outputs) and
  432.      * the typical as/ae is more of a graphics set, not the greek
  433.      * letters the 37 has.
  434.      */
  435.  
  436.     UNDER_CHAR =        tgetstr("uc", &bp);
  437.     must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
  438. }
  439.  
  440. outchar(c)
  441.     int c;
  442. {
  443.     putchar(c & 0177);
  444. }
  445.  
  446. static int curmode = 0;
  447.  
  448. outc(c)
  449.     int c;
  450. {
  451.     putchar(c);
  452.     if (must_use_uc && (curmode&UNDERL)) {
  453.         PRINT(CURS_LEFT);
  454.         PRINT(UNDER_CHAR);
  455.     }
  456. }
  457.  
  458. setmode(newmode)
  459.     int newmode;
  460. {
  461.     if (!iflag) {
  462.         if (curmode != NORMAL && newmode != NORMAL)
  463.             setmode(NORMAL);
  464.         switch (newmode) {
  465.         case NORMAL:
  466.             switch(curmode) {
  467.             case NORMAL:
  468.                 break;
  469.             case UNDERL:
  470.                 PRINT(EXIT_UNDERLINE);
  471.                 break;
  472.             default:
  473.                 /* This includes standout */
  474.                 PRINT(EXIT_ATTRIBUTES);
  475.                 break;
  476.             }
  477.             break;
  478.         case ALTSET:
  479.             PRINT(ENTER_REVERSE);
  480.             break;
  481.         case SUPERSC:
  482.             /*
  483.              * This only works on a few terminals.
  484.              * It should be fixed.
  485.              */
  486.             PRINT(ENTER_UNDERLINE);
  487.             PRINT(ENTER_DIM);
  488.             break;
  489.         case SUBSC:
  490.             PRINT(ENTER_DIM);
  491.             break;
  492.         case UNDERL:
  493.             PRINT(ENTER_UNDERLINE);
  494.             break;
  495.         case BOLD:
  496.             PRINT(ENTER_BOLD);
  497.             break;
  498.         default:
  499.             /*
  500.              * We should have some provision here for multiple modes
  501.              * on at once.  This will have to come later.
  502.              */
  503.             PRINT(ENTER_STANDOUT);
  504.             break;
  505.         }
  506.     }
  507.     curmode = newmode;
  508. }
  509.