home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / less-321-src.tgz / tar.out / fsf / less / output.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  411 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  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. #if MSDOS_COMPILER==WIN32C
  34. #include "windows.h"
  35. #endif
  36.  
  37. public int errmsgs;    /* Count of messages displayed by error() */
  38. public int need_clr;
  39.  
  40. extern int sigs;
  41. extern int sc_width;
  42. extern int so_s_width, so_e_width;
  43. extern int screen_trashed;
  44. extern int any_display;
  45. extern int is_tty;
  46.  
  47. /*
  48.  * Display the line which is in the line buffer.
  49.  */
  50.     public void
  51. put_line()
  52. {
  53.     register int c;
  54.     register int i;
  55.     int a;
  56.     int curr_attr;
  57.  
  58.     if (ABORT_SIGS())
  59.     {
  60.         /*
  61.          * Don't output if a signal is pending.
  62.          */
  63.         screen_trashed = 1;
  64.         return;
  65.     }
  66.  
  67.     curr_attr = AT_NORMAL;
  68.  
  69.     for (i = 0;  (c = gline(i, &a)) != '\0';  i++)
  70.     {
  71.         if (a != curr_attr)
  72.         {
  73.             /*
  74.              * Changing attributes.
  75.              * Display the exit sequence for the old attribute
  76.              * and the enter sequence for the new one.
  77.              */
  78.             switch (curr_attr)
  79.             {
  80.             case AT_UNDERLINE:    ul_exit();    break;
  81.             case AT_BOLD:        bo_exit();    break;
  82.             case AT_BLINK:        bl_exit();    break;
  83.             case AT_STANDOUT:    so_exit();    break;
  84.             }
  85.             switch (a)
  86.             {
  87.             case AT_UNDERLINE:    ul_enter();    break;
  88.             case AT_BOLD:        bo_enter();    break;
  89.             case AT_BLINK:        bl_enter();    break;
  90.             case AT_STANDOUT:    so_enter();    break;
  91.             }
  92.             curr_attr = a;
  93.         }
  94.         if (curr_attr == AT_INVIS)
  95.             continue;
  96.         if (c == '\b')
  97.             putbs();
  98.         else
  99.             putchr(c);
  100.     }
  101.  
  102.     switch (curr_attr)
  103.     {
  104.     case AT_UNDERLINE:    ul_exit();    break;
  105.     case AT_BOLD:        bo_exit();    break;
  106.     case AT_BLINK:        bl_exit();    break;
  107.     case AT_STANDOUT:    so_exit();    break;
  108.     }
  109. }
  110.  
  111. static char obuf[OUTBUF_SIZE];
  112. static char *ob = obuf;
  113.  
  114. /*
  115.  * Flush buffered output.
  116.  *
  117.  * If we haven't displayed any file data yet,
  118.  * output messages on error output (file descriptor 2),
  119.  * otherwise output on standard output (file descriptor 1).
  120.  *
  121.  * This has the desirable effect of producing all
  122.  * error messages on error output if standard output
  123.  * is directed to a file.  It also does the same if
  124.  * we never produce any real output; for example, if
  125.  * the input file(s) cannot be opened.  If we do
  126.  * eventually produce output, code in edit() makes
  127.  * sure these messages can be seen before they are
  128.  * overwritten or scrolled away.
  129.  */
  130.     public void
  131. flush()
  132. {
  133.     register int n;
  134.     register int fd;
  135.  
  136. #if MSDOS_COMPILER==WIN32C
  137.     if (is_tty && any_display)
  138.     {
  139.         DWORD nwritten = 0;
  140.         extern HANDLE con_out;
  141.         *ob = '\0';
  142.         WriteConsole(con_out, obuf, strlen(obuf), &nwritten, NULL);
  143.         ob = obuf;
  144.         return;
  145.     }
  146. #else
  147. #if MSDOS_COMPILER==MSOFTC
  148.     if (is_tty && any_display)
  149.     {
  150.         *ob = '\0';
  151.         _outtext(obuf);
  152.         ob = obuf;
  153.         return;
  154.     }
  155. #else
  156. #if MSDOS_COMPILER==BORLANDC
  157.     if (is_tty && any_display)
  158.     {
  159.         *ob = '\0';
  160.         cputs(obuf);
  161.         ob = obuf;
  162.         return;
  163.     }
  164. #endif
  165. #endif
  166. #endif
  167.     n = ob - obuf;
  168.     if (n == 0)
  169.         return;
  170.     fd = (any_display) ? 1 : 2;
  171.     if (write(fd, obuf, n) != n)
  172.         screen_trashed = 1;
  173.     ob = obuf;
  174. }
  175.  
  176. /*
  177.  * Output a character.
  178.  */
  179.     public int
  180. putchr(c)
  181.     int c;
  182. {
  183.     if (ob >= &obuf[sizeof(obuf)])
  184.         flush();
  185.     if (need_clr)
  186.     {
  187.         need_clr = 0;
  188.         clear_bot();
  189.     }
  190. #if MSDOS_COMPILER
  191.     if (c == '\n' && is_tty)
  192.         putchr('\r');
  193. #else
  194. #ifdef _OSK
  195.     if (c == '\n' && is_tty)  /* In OS-9, '\n' == 0x0D */
  196.         putchr(0x0A);
  197. #endif
  198. #endif
  199.     *ob++ = c;
  200.     return (c);
  201. }
  202.  
  203. /*
  204.  * Output a string.
  205.  */
  206.     public void
  207. putstr(s)
  208.     register char *s;
  209. {
  210.     while (*s != '\0')
  211.         putchr(*s++);
  212. }
  213.  
  214.  
  215. /*
  216.  * Output an integer in a given radix.
  217.  */
  218.     static int
  219. iprintnum(num, radix)
  220.     int num;
  221.     int radix;
  222. {
  223.     register char *s;
  224.     int r;
  225.     int neg;
  226.     char buf[10];
  227.  
  228.     neg = (num < 0);
  229.     if (neg)
  230.         num = -num;
  231.  
  232.     s = buf;
  233.     do
  234.     {
  235.         *s++ = (num % radix) + '0';
  236.     } while ((num /= radix) != 0);
  237.  
  238.     if (neg)
  239.         *s++ = '-';
  240.     r = s - buf;
  241.  
  242.     while (s > buf)
  243.         putchr(*--s);
  244.     return (r);
  245. }
  246.  
  247. /*
  248.  * This function implements printf-like functionality
  249.  * using a more portable argument list mechanism than printf's.
  250.  */
  251.     static int
  252. iprintf(fmt, parg)
  253.     register char *fmt;
  254.     PARG *parg;
  255. {
  256.     register char *s;
  257.     register int n;
  258.     register int col;
  259.  
  260.     col = 0;
  261.     while (*fmt != '\0')
  262.     {
  263.         if (*fmt != '%')
  264.         {
  265.             putchr(*fmt++);
  266.             col++;
  267.         } else
  268.         {
  269.             ++fmt;
  270.             switch (*fmt++) {
  271.             case 's':
  272.                 s = parg->p_string;
  273.                 parg++;
  274.                 while (*s != '\0')
  275.                 {
  276.                     putchr(*s++);
  277.                     col++;
  278.                 }
  279.                 break;
  280.             case 'd':
  281.                 n = parg->p_int;
  282.                 parg++;
  283.                 col += iprintnum(n, 10);
  284.                 break;
  285.             }
  286.         }
  287.     }
  288.     return (col);
  289. }
  290.  
  291. /*
  292.  * Get a RETURN.
  293.  * If some other non-trivial char is pressed, unget it, so it will
  294.  * become the next command.
  295.  */
  296.     public void
  297. get_return()
  298. {
  299.     int c;
  300.  
  301. #if ONLY_RETURN
  302.     while ((c = getchr()) != '\n' && c != '\r')
  303.         bell();
  304. #else
  305.     c = getchr();
  306.     if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
  307.         ungetcc(c);
  308. #endif
  309. }
  310.  
  311. /*
  312.  * Output a message in the lower left corner of the screen
  313.  * and wait for carriage return.
  314.  */
  315.     public void
  316. error(fmt, parg)
  317.     char *fmt;
  318.     PARG *parg;
  319. {
  320.     int col = 0;
  321.     static char return_to_continue[] = "  (press RETURN)";
  322.  
  323.     errmsgs++;
  324.  
  325.     if (any_display)
  326.     {
  327.         clear_bot();
  328.         so_enter();
  329.         col += so_s_width;
  330.     }
  331.  
  332.     col += iprintf(fmt, parg);
  333.  
  334.     if (!any_display)
  335.     {
  336.         putchr('\n');
  337.         return;
  338.     }
  339.  
  340.     putstr(return_to_continue);
  341.     so_exit();
  342.     col += sizeof(return_to_continue) + so_e_width;
  343.  
  344.     get_return();
  345.     lower_left();
  346.  
  347.     if (col >= sc_width)
  348.         /*
  349.          * Printing the message has probably scrolled the screen.
  350.          * {{ Unless the terminal doesn't have auto margins,
  351.          *    in which case we just hammered on the right margin. }}
  352.          */
  353.         screen_trashed = 1;
  354.  
  355.     flush();
  356. }
  357.  
  358. static char intr_to_abort[] = "... (interrupt to abort)";
  359.  
  360. /*
  361.  * Output a message in the lower left corner of the screen
  362.  * and don't wait for carriage return.
  363.  * Usually used to warn that we are beginning a potentially
  364.  * time-consuming operation.
  365.  */
  366.     public void
  367. ierror(fmt, parg)
  368.     char *fmt;
  369.     PARG *parg;
  370. {
  371.     clear_bot();
  372.     so_enter();
  373.     (void) iprintf(fmt, parg);
  374.     putstr(intr_to_abort);
  375.     so_exit();
  376.     flush();
  377.     need_clr = 1;
  378. }
  379.  
  380. /*
  381.  * Output a message in the lower left corner of the screen
  382.  * and return a single-character response.
  383.  */
  384.     public int
  385. query(fmt, parg)
  386.     char *fmt;
  387.     PARG *parg;
  388. {
  389.     register int c;
  390.     int col = 0;
  391.  
  392.     if (any_display)
  393.         clear_bot();
  394.  
  395.     (void) iprintf(fmt, parg);
  396.     c = getchr();
  397.  
  398.     if (!any_display)
  399.     {
  400.         putchr('\n');
  401.         return (c);
  402.     }
  403.  
  404.     lower_left();
  405.     if (col >= sc_width)
  406.         screen_trashed = 1;
  407.     flush();
  408.  
  409.     return (c);
  410. }
  411.