home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less2912.zip / output.c < prev    next >
C/C++ Source or Header  |  1995-02-01  |  7KB  |  364 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
  3.  * 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 in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * High level routines dealing with the output to the screen.
  30.  */
  31.  
  32. #include "less.h"
  33.  
  34. public int errmsgs;    /* Count of messages displayed by error() */
  35. public int need_clr;
  36.  
  37. extern int sigs;
  38. extern int sc_width;
  39. extern int so_s_width, so_e_width;
  40. extern int screen_trashed;
  41. extern int any_display;
  42.  
  43. /*
  44.  * Display the line which is in the line buffer.
  45.  */
  46.     public void
  47. put_line()
  48. {
  49.     register int c;
  50.     register int i;
  51.     int a;
  52.     int curr_attr;
  53.  
  54.     if (ABORT_SIGS())
  55.     {
  56.         /*
  57.          * Don't output if a signal is pending.
  58.          */
  59.         screen_trashed = 1;
  60.         return;
  61.     }
  62.  
  63.     curr_attr = AT_NORMAL;
  64.  
  65.     for (i = 0;  (c = gline(i, &a)) != '\0';  i++)
  66.     {
  67.         if (a != curr_attr)
  68.         {
  69.             /*
  70.              * Changing attributes.
  71.              * Display the exit sequence for the old attribute
  72.              * and the enter sequence for the new one.
  73.              */
  74.             switch (curr_attr)
  75.             {
  76.             case AT_UNDERLINE:    ul_exit();    break;
  77.             case AT_BOLD:        bo_exit();    break;
  78.             case AT_BLINK:        bl_exit();    break;
  79.             case AT_STANDOUT:    so_exit();    break;
  80.             }
  81.             switch (a)
  82.             {
  83.             case AT_UNDERLINE:    ul_enter();    break;
  84.             case AT_BOLD:        bo_enter();    break;
  85.             case AT_BLINK:        bl_enter();    break;
  86.             case AT_STANDOUT:    so_enter();    break;
  87.             }
  88.             curr_attr = a;
  89.         }
  90.         if (curr_attr == AT_INVIS)
  91.             continue;
  92.         if (c == '\b')
  93.             putbs();
  94.         else
  95.             putchr(c);
  96.     }
  97.  
  98.     switch (curr_attr)
  99.     {
  100.     case AT_UNDERLINE:    ul_exit();    break;
  101.     case AT_BOLD:        bo_exit();    break;
  102.     case AT_BLINK:        bl_exit();    break;
  103.     case AT_STANDOUT:    so_exit();    break;
  104.     }
  105. }
  106.  
  107. static char obuf[1024];
  108. static char *ob = obuf;
  109.  
  110. /*
  111.  * Flush buffered output.
  112.  *
  113.  * If we haven't displayed any file data yet,
  114.  * output messages on error output (file descriptor 2),
  115.  * otherwise output on standard output (file descriptor 1).
  116.  *
  117.  * This has the desirable effect of producing all
  118.  * error messages on error output if standard output
  119.  * is directed to a file.  It also does the same if
  120.  * we never produce any real output; for example, if
  121.  * the input file(s) cannot be opened.  If we do
  122.  * eventually produce output, code in edit() makes
  123.  * sure these messages can be seen before they are
  124.  * overwritten or scrolled away.
  125.  */
  126.     public void
  127. flush()
  128. {
  129.     register int n;
  130.     register int fd;
  131.  
  132. #if MSOFTC
  133.     *ob = '\0';
  134.     _outtext(obuf);
  135.     ob = obuf;
  136. #else
  137.     n = ob - obuf;
  138.     if (n == 0)
  139.         return;
  140.     fd = (any_display) ? 1 : 2;
  141.     if (write(fd, obuf, n) != n)
  142.         screen_trashed = 1;
  143.     ob = obuf;
  144. #endif
  145. }
  146.  
  147. /*
  148.  * Output a character.
  149.  */
  150.     public int
  151. putchr(c)
  152.     int c;
  153. {
  154.     if (ob >= &obuf[sizeof(obuf)])
  155.         flush();
  156.     if (need_clr)
  157.     {
  158.         need_clr = 0;
  159.         clear_bot();
  160.     }
  161. #if MSOFTC
  162.     if (c == '\n')
  163.         putchr('\r');
  164. #endif
  165.     *ob++ = c;
  166.     return (c);
  167. }
  168.  
  169. /*
  170.  * Output a string.
  171.  */
  172.     public void
  173. putstr(s)
  174.     register char *s;
  175. {
  176.     while (*s != '\0')
  177.         putchr(*s++);
  178. }
  179.  
  180.  
  181. /*
  182.  * Output an integer in a given radix.
  183.  */
  184.     static int
  185. iprintnum(num, radix)
  186.     int num;
  187.     int radix;
  188. {
  189.     register char *s;
  190.     int r;
  191.     int neg;
  192.     char buf[10];
  193.  
  194.     if (neg = (num < 0))
  195.         num = -num;
  196.  
  197.     s = buf;
  198.     do
  199.     {
  200.         *s++ = (num % radix) + '0';
  201.     } while ((num /= radix) != 0);
  202.  
  203.     if (neg)
  204.         *s++ = '-';
  205.     r = s - buf;
  206.  
  207.     while (s > buf)
  208.         putchr(*--s);
  209.     return (r);
  210. }
  211.  
  212. /*
  213.  * This function implements printf-like functionality
  214.  * using a more portable argument list mechanism than printf's.
  215.  */
  216.     static int
  217. iprintf(fmt, parg)
  218.     register char *fmt;
  219.     PARG *parg;
  220. {
  221.     register char *s;
  222.     register int n;
  223.     register int col;
  224.  
  225.     col = 0;
  226.     while (*fmt != '\0')
  227.     {
  228.         if (*fmt != '%')
  229.         {
  230.             putchr(*fmt++);
  231.             col++;
  232.         } else
  233.         {
  234.             ++fmt;
  235.             switch (*fmt++) {
  236.             case 's':
  237.                 s = parg->p_string;
  238.                 parg++;
  239.                 while (*s != '\0')
  240.                 {
  241.                     putchr(*s++);
  242.                     col++;
  243.                 }
  244.                 break;
  245.             case 'd':
  246.                 n = parg->p_int;
  247.                 parg++;
  248.                 col += iprintnum(n, 10);
  249.                 break;
  250.             }
  251.         }
  252.     }
  253.     return (col);
  254. }
  255.  
  256. /*
  257.  * Output a message in the lower left corner of the screen
  258.  * and wait for carriage return.
  259.  */
  260.     public void
  261. error(fmt, parg)
  262.     char *fmt;
  263.     PARG *parg;
  264. {
  265.     int c;
  266.     int col = 0;
  267.     static char return_to_continue[] = "  (press RETURN)";
  268.  
  269.     errmsgs++;
  270.  
  271.     if (any_display)
  272.     {
  273.         clear_bot();
  274.         so_enter();
  275.         col += so_s_width;
  276.     }
  277.  
  278.     col += iprintf(fmt, parg);
  279.  
  280.     if (!any_display)
  281.     {
  282.         putchr('\n');
  283.         return;
  284.     }
  285.  
  286.     putstr(return_to_continue);
  287.     so_exit();
  288.     col += sizeof(return_to_continue) + so_e_width;
  289.  
  290. #if ONLY_RETURN
  291.     while ((c = getchr()) != '\n' && c != '\r')
  292.         bell();
  293. #else
  294.     c = getchr();
  295.     if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
  296.         ungetcc(c);
  297. #endif
  298.     lower_left();
  299.  
  300.     if (col >= sc_width)
  301.         /*
  302.          * Printing the message has probably scrolled the screen.
  303.          * {{ Unless the terminal doesn't have auto margins,
  304.          *    in which case we just hammered on the right margin. }}
  305.          */
  306.         screen_trashed = 1;
  307.  
  308.     flush();
  309. }
  310.  
  311. static char intr_to_abort[] = "... (interrupt to abort)";
  312.  
  313. /*
  314.  * Output a message in the lower left corner of the screen
  315.  * and don't wait for carriage return.
  316.  * Usually used to warn that we are beginning a potentially
  317.  * time-consuming operation.
  318.  */
  319.     public void
  320. ierror(fmt, parg)
  321.     char *fmt;
  322.     PARG *parg;
  323. {
  324.     clear_bot();
  325.     so_enter();
  326.     (void) iprintf(fmt, parg);
  327.     putstr(intr_to_abort);
  328.     so_exit();
  329.     flush();
  330.     need_clr = 1;
  331. }
  332.  
  333. /*
  334.  * Output a message in the lower left corner of the screen
  335.  * and return a single-character response.
  336.  */
  337.     public int
  338. query(fmt, parg)
  339.     char *fmt;
  340.     PARG *parg;
  341. {
  342.     register int c;
  343.     int col = 0;
  344.  
  345.     if (any_display)
  346.         clear_bot();
  347.  
  348.     (void) iprintf(fmt, parg);
  349.     c = getchr();
  350.  
  351.     if (!any_display)
  352.     {
  353.         putchr('\n');
  354.         return (c);
  355.     }
  356.  
  357.     lower_left();
  358.     if (col >= sc_width)
  359.         screen_trashed = 1;
  360.     flush();
  361.  
  362.     return (c);
  363. }
  364.