home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / DOSCREEN.C < prev    next >
C/C++ Source or Header  |  1994-08-24  |  11KB  |  567 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  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.  * Routines which deal with the characteristics of the terminal.
  30.  *
  31.  * This file is specific to MS-DOS and uses Microsoft C graphics functions.
  32.  */
  33.  
  34. #include "less.h"
  35. #include "cmd.h"
  36.  
  37. #include <graph.h>
  38. #include <time.h>
  39.  
  40. static int init_done = 0;
  41. static int videopages;
  42. static long msec_loops;
  43.  
  44. public int auto_wrap;        /* Terminal does \r\n when write past margin */
  45. public int ignaw;        /* Terminal ignores \n immediately after wrap */
  46. public int erase_char, kill_char; /* The user's erase and line-kill chars */
  47. public int sc_width, sc_height;    /* Height & width of screen */
  48. public int bo_s_width, bo_e_width;    /* Printing width of boldface seq */
  49. public int ul_s_width, ul_e_width;    /* Printing width of underline seq */
  50. public int so_s_width, so_e_width;    /* Printing width of standout seq */
  51. public int bl_s_width, bl_e_width;    /* Printing width of blink seq */
  52.  
  53. public int nm_fg_color = 7;            /* Color of normal text */
  54. public int nm_bg_color = 0;
  55. public int bo_fg_color = 15;        /* Color of bold text */
  56. public int bo_bg_color = 0;
  57. public int ul_fg_color = 9;            /* Color of underlined text */
  58. public int ul_bg_color = 0;
  59. public int so_fg_color = 0;            /* Color of standout text */
  60. public int so_bg_color = 7;
  61. public int bl_fg_color = 12;        /* Color of blinking text */
  62. public int bl_bg_color = 0;
  63.  
  64. static int sy_fg_color;
  65. static int sy_bg_color;
  66. static int flash_created = 0;
  67.  
  68. extern int quiet;        /* If VERY_QUIET, use visual bell for bell */
  69. extern int know_dumb;        /* Don't complain about a dumb terminal */
  70. extern int back_scroll;
  71. extern int swindow;
  72. extern char *getenv();
  73.  
  74. /*
  75.  * Change terminal to "raw mode", or restore to "normal" mode.
  76.  * "Raw mode" means 
  77.  *    1. An outstanding read will complete on receipt of a single keystroke.
  78.  *    2. Input is not echoed.  
  79.  *    3. On output, \n is mapped to \r\n.
  80.  *    4. \t is NOT expanded into spaces.
  81.  *    5. Signal-causing characters such as ctrl-C (interrupt),
  82.  *       etc. are NOT disabled.
  83.  * It doesn't matter whether an input \n is mapped to \r, or vice versa.
  84.  */
  85.     public void
  86. raw_mode(on)
  87.     int on;
  88. {
  89.     static int curr_on = 0;
  90.  
  91.     if (on == curr_on)
  92.         return;
  93.     erase_char = CONTROL('h');
  94.     kill_char = '\33'; /* ESC */
  95.     curr_on = on;
  96. }
  97.  
  98. /*
  99.  * Get size of the output screen.
  100.  */
  101.     public void
  102. scrsize(p_height, p_width)
  103.     int *p_height;
  104.     int *p_width;
  105. {
  106.     register char *s;
  107.     struct videoconfig w;
  108.  
  109.     _getvideoconfig(&w);
  110.  
  111.     if (w.numtextrows)
  112.         *p_height = w.numtextrows;
  113.     else if ((s = getenv("LINES")) != NULL && *s != '\0')
  114.         *p_height = atoi(s);
  115.     if (*p_height <= 0)
  116.         *p_height = 24;
  117.         
  118.     if (w.numtextcols > 0)
  119.         *p_width = w.numtextcols;
  120.     else if ((s = getenv("COLUMNS")) != NULL)
  121.         *p_width = atoi(s);
  122.     if (*p_width <= 0)
  123.           *p_width = 80;
  124. }
  125.  
  126. /*
  127.  * Figure out how many empty loops it takes to delay a millisecond.
  128.  */
  129.     static void
  130. get_clock()
  131. {
  132.     clock_t start;
  133.     
  134.     /*
  135.      * Get synchronized at the start of a tick.
  136.      */
  137.     start = clock();
  138.     while (clock() == start)
  139.         ;
  140.     /*
  141.      * Now count loops till the next tick.
  142.      */
  143.     start = clock();
  144.     msec_loops = 0;
  145.     while (clock() == start)
  146.         msec_loops++;
  147.     /*
  148.      * Convert from (loops per clock) to (loops per millisecond).
  149.      */
  150.     msec_loops *= CLOCKS_PER_SEC;
  151.     msec_loops /= 1000;
  152. }
  153.  
  154. /*
  155.  * Get terminal capabilities via termcap.
  156.  */
  157.     public void
  158. get_term()
  159. {
  160.     scrsize(&sc_height, &sc_width);
  161.     pos_init();
  162.     auto_wrap = 1;
  163.     ignaw = 0;
  164.     so_e_width = so_s_width = 0;
  165.     bo_s_width = bo_e_width = 0;
  166.     ul_s_width = ul_e_width = 0;
  167.     bl_s_width = bl_e_width = 0;
  168.     get_clock();
  169. }
  170.  
  171.  
  172. /*
  173.  * Below are the functions which perform all the 
  174.  * terminal-specific screen manipulation.
  175.  */
  176.  
  177.  
  178. /*
  179.  * Initialize terminal
  180.  */
  181.     public void
  182. init()
  183. {
  184.     /* {{ What could we take no_init (-X) to mean? }} */
  185.     sy_bg_color = _getbkcolor();
  186.     sy_fg_color = _gettextcolor();
  187.     flush();
  188.     init_done = 1;
  189. }
  190.  
  191. /*
  192.  * Create an alternate screen which is all white.
  193.  * This screen is used to create a "flash" effect, by displaying it
  194.  * briefly and then switching back to the normal screen.
  195.  * {{ Yuck!  There must be a better way to get a visual bell. }}
  196.  */
  197.     static void
  198. create_flash()
  199. {
  200.     struct videoconfig w;
  201.     char *blanks;
  202.     int row, col;
  203.     
  204.     _getvideoconfig(&w);
  205.     videopages = w.numvideopages;
  206.     if (videopages < 2)
  207.     {
  208.         so_enter();
  209.         so_exit();
  210.     } else
  211.     {
  212.         _setactivepage(1);
  213.         so_enter();
  214.         blanks = (char *) ecalloc(w.numtextcols, sizeof(char));
  215.         for (col = 0;  col < w.numtextcols;  col++)
  216.             blanks[col] = ' ';
  217.         for (row = w.numtextrows;  row > 0;  row--)
  218.             _outmem(blanks, w.numtextcols);
  219.         _setactivepage(0);
  220.         _setvisualpage(0);
  221.         free(blanks);
  222.         so_exit();
  223.     }
  224.     flash_created = 1;
  225. }
  226.  
  227. /*
  228.  * Deinitialize terminal
  229.  */
  230.     public void
  231. deinit()
  232. {
  233.     if (!init_done)
  234.         return;
  235.     _setbkcolor(sy_bg_color);
  236.     _settextcolor(sy_fg_color);
  237.     putstr("\n");
  238.     init_done = 0;
  239. }
  240.  
  241. /*
  242.  * Home cursor (move to upper left corner of screen).
  243.  */
  244.     public void
  245. home()
  246. {
  247.     flush();
  248.     _settextposition(1,1);
  249. }
  250.  
  251. /*
  252.  * Add a blank line (called with cursor at home).
  253.  * Should scroll the display down.
  254.  */
  255.     public void
  256. add_line()
  257. {
  258.     flush();
  259.     _scrolltextwindow(_GSCROLLDOWN);
  260.     _settextposition(1,1);
  261. }
  262.  
  263. /*
  264.  * Move cursor to lower left corner of screen.
  265.  */
  266.     public void
  267. lower_left()
  268. {
  269.     flush();
  270.     _settextposition(sc_height,1);
  271. }
  272.  
  273. /*
  274.  * Delay for a specified number of milliseconds.
  275.  */
  276.     static void
  277. dummy_func()
  278. {
  279.     static long delay_dummy = 0;
  280.     delay_dummy++;
  281. }
  282.  
  283.     static void
  284. delay(msec)
  285.     int msec;
  286. {
  287.     long i;
  288.     
  289.     while (msec-- > 0)
  290.     {
  291.         for (i = 0;  i < msec_loops;  i++)
  292.         {
  293.             /*
  294.              * Make it look like we're doing something here,
  295.              * so the optimizer doesn't remove the whole loop.
  296.              */
  297.             dummy_func();
  298.         }
  299.     }
  300. }
  301.  
  302. /*
  303.  * Make a noise.
  304.  */
  305.     static void
  306. beep()
  307. {
  308.     write(1, "\7", 1);
  309. }
  310.  
  311. /*
  312.  * Output the "visual bell", if there is one.
  313.  */
  314.     public void
  315. vbell()
  316. {
  317.     if (!flash_created)
  318.         /*
  319.          * Create a "flash" on the second video page.
  320.          */
  321.         create_flash();
  322.     if (videopages < 2)
  323.         /*
  324.          * There is no "second video page".
  325.          */
  326.         return;
  327.     _setvisualpage(1);
  328.     /*
  329.      * Leave it displayed for 100 msec.
  330.      */
  331.     delay(100);
  332.     _setvisualpage(0);
  333. }
  334.  
  335. /*
  336.  * Ring the terminal bell.
  337.  */
  338.     public void
  339. bell()
  340. {
  341.     if (quiet == VERY_QUIET)
  342.         vbell();
  343.     else
  344.         beep();
  345. }
  346.  
  347. /*
  348.  * Clear the screen.
  349.  */
  350.     public void
  351. clear()
  352. {
  353.     flush();
  354.     _clearscreen(_GCLEARSCREEN);
  355. }
  356.  
  357. /*
  358.  * Clear from the cursor to the end of the cursor's line.
  359.  * {{ This must not move the cursor. }}
  360.  */
  361.     public void
  362. clear_eol()
  363. {
  364.     short top, left;
  365.     short bot, right;
  366.     struct rccoord tpos;
  367.     
  368.     flush();
  369.     /*
  370.      * Save current state.
  371.      */
  372.     tpos = _gettextposition();
  373.     _gettextwindow(&top, &left, &bot, &right);
  374.     /*
  375.      * Set a temporary window to the current line,
  376.      * from the cursor's position to the right edge of the screen.
  377.      * Then clear that window.
  378.      */
  379.     _settextwindow(tpos.row, tpos.col, tpos.row, sc_width);
  380.     _clearscreen(_GWINDOW);
  381.     /*
  382.      * Restore state.
  383.      */
  384.     _settextwindow(top, left, bot, right);
  385.     _settextposition(tpos.row, tpos.col);
  386. }
  387.  
  388. /*
  389.  * Clear the bottom line of the display.
  390.  * Leave the cursor at the beginning of the bottom line.
  391.  */
  392.     public void
  393. clear_bot()
  394. {
  395.     lower_left();
  396.     clear_eol();
  397. }
  398.  
  399. /*
  400.  * Begin "standout" (bold, underline, or whatever).
  401.  */
  402.     public void
  403. so_enter()
  404. {
  405.     flush();
  406.     _setbkcolor(so_bg_color);
  407.     _settextcolor(so_fg_color);
  408. }
  409.  
  410. /*
  411.  * End "standout".
  412.  */
  413.     public void
  414. so_exit()
  415. {
  416.     flush();
  417.     _setbkcolor(nm_bg_color);
  418.     _settextcolor(nm_fg_color);
  419. }
  420.  
  421. /*
  422.  * Begin "underline" (hopefully real underlining, 
  423.  * otherwise whatever the terminal provides).
  424.  */
  425.     public void
  426. ul_enter()
  427. {
  428.     flush();
  429.     _setbkcolor(ul_bg_color);
  430.     _settextcolor(ul_fg_color);
  431. }
  432.  
  433. /*
  434.  * End "underline".
  435.  */
  436.     public void
  437. ul_exit()
  438. {
  439.     flush();
  440.     _setbkcolor(nm_bg_color);
  441.     _settextcolor(nm_fg_color);
  442. }
  443.  
  444. /*
  445.  * Begin "bold"
  446.  */
  447.     public void
  448. bo_enter()
  449. {
  450.     flush();
  451.     _setbkcolor(bo_bg_color);
  452.     _settextcolor(bo_fg_color);
  453. }
  454.  
  455. /*
  456.  * End "bold".
  457.  */
  458.     public void
  459. bo_exit()
  460. {
  461.     flush();
  462.     _setbkcolor(nm_bg_color);
  463.     _settextcolor(nm_fg_color);
  464. }
  465.  
  466. /*
  467.  * Begin "blink"
  468.  */
  469.     public void
  470. bl_enter()
  471. {
  472.     flush();
  473.     _setbkcolor(bl_bg_color);
  474.     _settextcolor(bl_fg_color);
  475. }
  476.  
  477. /*
  478.  * End "blink".
  479.  */
  480.     public void
  481. bl_exit()
  482. {
  483.     flush();
  484.     _setbkcolor(nm_bg_color);
  485.     _settextcolor(nm_fg_color);
  486. }
  487.  
  488. /*
  489.  * Erase the character to the left of the cursor 
  490.  * and move the cursor left.
  491.  */
  492.     public void
  493. backspace()
  494. {
  495.     struct rccoord tpos;
  496.     
  497.     /* 
  498.      * Erase the previous character by overstriking with a space.
  499.      */
  500.     flush();
  501.     tpos = _gettextposition();
  502.     if (tpos.col <= 1)
  503.         return;
  504.     _settextposition(tpos.row, tpos.col-1);
  505.     _outtext(" ");
  506.     _settextposition(tpos.row, tpos.col-1);
  507. }
  508.  
  509. /*
  510.  * Output a plain backspace, without erasing the previous char.
  511.  */
  512.     public void
  513. putbs()
  514. {
  515.     struct rccoord tpos;
  516.     
  517.     flush();
  518.     tpos = _gettextposition();
  519.     if (tpos.col <= 1)
  520.         return;
  521.     _settextposition(tpos.row, tpos.col-1);
  522. }
  523.  
  524. /*
  525.  * Table of line editting characters, for editchar() in decode.c.
  526.  */
  527. char edittable[] = {
  528.     '\340','\115',0,    EC_RIGHT,    /* RIGHTARROW */
  529.     '\340','\113',0,    EC_LEFT,    /* LEFTARROW */
  530.     '\340','\163',0,    EC_W_LEFT,    /* CTRL-LEFTARROW */
  531.     '\340','\164',0,    EC_W_RIGHT,    /* CTRL-RIGHTARROW */
  532.     '\340','\122',0,    EC_INSERT,    /* INSERT */
  533.     '\340','\123',0,    EC_DELETE,    /* DELETE */
  534.     '\340','\223',0,    EC_W_DELETE,    /* CTRL-DELETE */
  535.     '\177',0,        EC_W_BACKSPACE,    /* CTRL-BACKSPACE */
  536.     '\340','\107',0,    EC_HOME,    /* HOME */
  537.     '\340','\117',0,    EC_END,        /* END */
  538.     '\340','\110',0,    EC_UP,        /* UPARROW */
  539.     '\340','\120',0,    EC_DOWN,    /* DOWNARROW */
  540.     '\t',0,            EC_F_COMPLETE,    /* TAB */
  541.     '\17',0,        EC_B_COMPLETE,    /* BACKTAB (?) */
  542.     '\340','\17',0,        EC_B_COMPLETE,    /* BACKTAB */
  543.     '\14',0,        EC_EXPAND,    /* CTRL-L */
  544.     0  /* Extra byte to terminate; subtracted from size, below */
  545. };
  546.  
  547. int sz_edittable = sizeof(edittable) -1;
  548.  
  549.  
  550. char kcmdtable[] =
  551. {
  552.     /*
  553.      * PC function keys.
  554.      * Note that '\0' is converted to '\340' on input.
  555.      */
  556.     '\340','\120',0,        A_F_LINE,        /* down arrow */
  557.     '\340','\121',0,        A_F_SCREEN,        /* page down */
  558.     '\340','\110',0,        A_B_LINE,        /* up arrow */
  559.     '\340','\111',0,        A_B_SCREEN,        /* page up */
  560.     '\340','\107',0,        A_GOLINE,        /* home */
  561.     '\340','\117',0,        A_GOEND,        /* end */
  562.     '\340','\073',0,        A_HELP,            /* F1 */
  563.     '\340','\022',0,        A_EXAMINE,        /* Alt-E */
  564.     0
  565. };
  566. int sz_kcmdtable = sizeof(kcmdtable) - 1;
  567.