home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / less_332.lzh / less_332 / output.c < prev    next >
Text File  |  1998-03-03  |  9KB  |  446 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.     n = ob - obuf;
  137.     if (n == 0)
  138.         return;
  139. #if MSDOS_COMPILER==WIN32C
  140.     if (is_tty && any_display)
  141.         {
  142.         char *p;
  143.         DWORD nwritten = 0;
  144.         CONSOLE_SCREEN_BUFFER_INFO scr;
  145.         DWORD nchars;
  146.         COORD cpos;
  147.         extern HANDLE con_out;
  148.  
  149.         *ob = '\0';
  150.         GetConsoleScreenBufferInfo(con_out, &scr);
  151.         if (scr.dwCursorPosition.Y != scr.srWindow.Bottom ||
  152.             (p = strchr(obuf, '\n')) == NULL)
  153.         {
  154.             WriteConsole(con_out, obuf, strlen(obuf), 
  155.                     &nwritten, NULL);
  156.         } else
  157.         {
  158.             /*
  159.              * To avoid color problems, if we're writing a
  160.              * newline at the bottom of the screen, we write
  161.              * only up to the newline, then fill the bottom
  162.              * line with the correct attribute, then write
  163.              * the rest.  When Windows-95 scrolls, it takes the
  164.              * attributes for the new line from the first char 
  165.              * of the (previously) bottom line.
  166.              */
  167.             WriteConsole(con_out, obuf, p - obuf + 1, 
  168.                     &nwritten, NULL);
  169.             cpos.X = 0;
  170.             cpos.Y = scr.dwCursorPosition.Y;
  171.             FillConsoleOutputAttribute(con_out, scr.wAttributes,
  172.                         sc_width, cpos, &nchars);
  173.             WriteConsole(con_out, p + 1, strlen(p + 1), 
  174.                     &nwritten, NULL);
  175.         }
  176.         ob = obuf;
  177.         return;
  178.         }
  179.  
  180. #else
  181. #if MSDOS_COMPILER==MSOFTC
  182.     if (is_tty && any_display)
  183.     {
  184.         *ob = '\0';
  185.         _outtext(obuf);
  186.         ob = obuf;
  187.         return;
  188.     }
  189. #else
  190. #if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
  191.     if (is_tty && any_display)
  192.     {
  193.         *ob = '\0';
  194.         cputs(obuf);
  195.         ob = obuf;
  196.         return;
  197.     }
  198. #endif
  199. #endif
  200. #endif
  201.     fd = (any_display) ? 1 : 2;
  202.     if (write(fd, obuf, n) != n)
  203.         screen_trashed = 1;
  204.     ob = obuf;
  205. }
  206.  
  207. /*
  208.  * Output a character.
  209.  */
  210.     public int
  211. putchr(c)
  212.     int c;
  213. {
  214.     if (need_clr)
  215.     {
  216.         need_clr = 0;
  217.         clear_bot();
  218.     }
  219. #if MSDOS_COMPILER
  220.     if (c == '\n' && is_tty)
  221.         putchr('\r');
  222. #else
  223. #ifdef _OSK
  224.     if (c == '\n' && is_tty)  /* In OS-9, '\n' == 0x0D */
  225.         putchr(0x0A);
  226. #endif
  227. #endif
  228.     /*
  229.      * Some versions of flush() write to *ob, so we must flush
  230.      * when we are still one char from the end of obuf.
  231.      */
  232.     if (ob >= &obuf[sizeof(obuf)-1])
  233.         flush();
  234.     *ob++ = c;
  235.     return (c);
  236. }
  237.  
  238. /*
  239.  * Output a string.
  240.  */
  241.     public void
  242. putstr(s)
  243.     register char *s;
  244. {
  245.     while (*s != '\0')
  246.         putchr(*s++);
  247. }
  248.  
  249.  
  250. /*
  251.  * Output an integer in a given radix.
  252.  */
  253.     static int
  254. iprintnum(num, radix)
  255.     int num;
  256.     int radix;
  257. {
  258.     register char *s;
  259.     int r;
  260.     int neg;
  261.     char buf[10];
  262.  
  263.     neg = (num < 0);
  264.     if (neg)
  265.         num = -num;
  266.  
  267.     s = buf;
  268.     do
  269.     {
  270.         *s++ = (num % radix) + '0';
  271.     } while ((num /= radix) != 0);
  272.  
  273.     if (neg)
  274.         *s++ = '-';
  275.     r = s - buf;
  276.  
  277.     while (s > buf)
  278.         putchr(*--s);
  279.     return (r);
  280. }
  281.  
  282. /*
  283.  * This function implements printf-like functionality
  284.  * using a more portable argument list mechanism than printf's.
  285.  */
  286.     static int
  287. iprintf(fmt, parg)
  288.     register char *fmt;
  289.     PARG *parg;
  290. {
  291.     register char *s;
  292.     register int n;
  293.     register int col;
  294.  
  295.     col = 0;
  296.     while (*fmt != '\0')
  297.     {
  298.         if (*fmt != '%')
  299.         {
  300.             putchr(*fmt++);
  301.             col++;
  302.         } else
  303.         {
  304.             ++fmt;
  305.             switch (*fmt++) {
  306.             case 's':
  307.                 s = parg->p_string;
  308.                 parg++;
  309.                 while (*s != '\0')
  310.                 {
  311.                     putchr(*s++);
  312.                     col++;
  313.                 }
  314.                 break;
  315.             case 'd':
  316.                 n = parg->p_int;
  317.                 parg++;
  318.                 col += iprintnum(n, 10);
  319.                 break;
  320.             }
  321.         }
  322.     }
  323.     return (col);
  324. }
  325.  
  326. /*
  327.  * Get a RETURN.
  328.  * If some other non-trivial char is pressed, unget it, so it will
  329.  * become the next command.
  330.  */
  331.     public void
  332. get_return()
  333. {
  334.     int c;
  335.  
  336. #if ONLY_RETURN
  337.     while ((c = getchr()) != '\n' && c != '\r')
  338.         bell();
  339. #else
  340.     c = getchr();
  341.     if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
  342.         ungetcc(c);
  343. #endif
  344. }
  345.  
  346. /*
  347.  * Output a message in the lower left corner of the screen
  348.  * and wait for carriage return.
  349.  */
  350.     public void
  351. error(fmt, parg)
  352.     char *fmt;
  353.     PARG *parg;
  354. {
  355.     int col = 0;
  356.     static char return_to_continue[] = "  (press RETURN)";
  357.  
  358.     errmsgs++;
  359.  
  360.     if (any_display && is_tty)
  361.     {
  362.         clear_bot();
  363.         so_enter();
  364.         col += so_s_width;
  365.     }
  366.  
  367.     col += iprintf(fmt, parg);
  368.  
  369.     if (!(any_display && is_tty))
  370.     {
  371.         putchr('\n');
  372.         return;
  373.     }
  374.  
  375.     putstr(return_to_continue);
  376.     so_exit();
  377.     col += sizeof(return_to_continue) + so_e_width;
  378.  
  379.     get_return();
  380.     lower_left();
  381.  
  382.     if (col >= sc_width)
  383.         /*
  384.          * Printing the message has probably scrolled the screen.
  385.          * {{ Unless the terminal doesn't have auto margins,
  386.          *    in which case we just hammered on the right margin. }}
  387.          */
  388.         screen_trashed = 1;
  389.  
  390.     flush();
  391. }
  392.  
  393. static char intr_to_abort[] = "... (interrupt to abort)";
  394.  
  395. /*
  396.  * Output a message in the lower left corner of the screen
  397.  * and don't wait for carriage return.
  398.  * Usually used to warn that we are beginning a potentially
  399.  * time-consuming operation.
  400.  */
  401.     public void
  402. ierror(fmt, parg)
  403.     char *fmt;
  404.     PARG *parg;
  405. {
  406.     clear_bot();
  407.     so_enter();
  408.     (void) iprintf(fmt, parg);
  409.     putstr(intr_to_abort);
  410.     so_exit();
  411.     flush();
  412.     need_clr = 1;
  413. }
  414.  
  415. /*
  416.  * Output a message in the lower left corner of the screen
  417.  * and return a single-character response.
  418.  */
  419.     public int
  420. query(fmt, parg)
  421.     char *fmt;
  422.     PARG *parg;
  423. {
  424.     register int c;
  425.     int col = 0;
  426.  
  427.     if (any_display && is_tty)
  428.         clear_bot();
  429.  
  430.     (void) iprintf(fmt, parg);
  431.     c = getchr();
  432.  
  433.     if (!(any_display && is_tty))
  434.     {
  435.         putchr('\n');
  436.         return (c);
  437.     }
  438.  
  439.     lower_left();
  440.     if (col >= sc_width)
  441.         screen_trashed = 1;
  442.     flush();
  443.  
  444.     return (c);
  445. }
  446.