home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / slang / slsmg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  25.6 KB  |  1,206 lines

  1. /* SLang Screen management routines */
  2. /* Copyright (c) 1992, 1995 John E. Davis
  3.  * All rights reserved.
  4.  * 
  5.  * You may distribute under the terms of either the GNU General Public
  6.  * License or the Perl Artistic License.
  7.  */
  8. #include <config.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11.  
  12. #include "config.h"
  13. #include "slang.h"
  14. #include "_slang.h"
  15.  
  16. typedef struct Screen_Type
  17.   {
  18.      int n;                    /* number of chars written last time */
  19.      int flags;                /* line untouched, etc... */
  20.      SLang_Char_Type *old, *neew;
  21. #ifndef pc_system
  22.      unsigned long old_hash, new_hash;
  23. #endif
  24.   }
  25. Screen_Type;
  26.  
  27. #ifdef linux_unicode
  28. struct _uniconv
  29.   {
  30.     unsigned char acs;
  31.     unsigned short uni;
  32.   }
  33. UniConv_Table [] = {
  34. { SLSMG_HLINE_CHAR, SLUNI_HLINE_CHAR },
  35. { SLSMG_VLINE_CHAR, SLUNI_VLINE_CHAR },
  36. { SLSMG_ULCORN_CHAR, SLUNI_ULCORN_CHAR },
  37. { SLSMG_URCORN_CHAR, SLUNI_URCORN_CHAR },
  38. { SLSMG_LLCORN_CHAR, SLUNI_LLCORN_CHAR },
  39. { SLSMG_LRCORN_CHAR, SLUNI_LRCORN_CHAR },
  40. { SLSMG_CKBRD_CHAR, SLUNI_CKBRD_CHAR },
  41. { SLSMG_RTEE_CHAR, SLUNI_RTEE_CHAR },
  42. { SLSMG_LTEE_CHAR, SLUNI_LTEE_CHAR },
  43. { SLSMG_UTEE_CHAR, SLUNI_UTEE_CHAR },
  44. { SLSMG_DTEE_CHAR, SLUNI_DTEE_CHAR },
  45. { SLSMG_CROSS_CHAR, SLUNI_CROSS_CHAR }
  46. };
  47. #define colorshift 16
  48. #else
  49. #define colorshift 8
  50. #endif
  51.  
  52. #define TOUCHED 0x1
  53. #define TRASHED 0x2
  54.  
  55. #ifndef pc_system
  56. #define MAX_SCREEN_SIZE 120
  57. #else
  58. #define MAX_SCREEN_SIZE 75
  59. #endif
  60.  
  61. Screen_Type SL_Screen[MAX_SCREEN_SIZE];
  62. static int Start_Col, Start_Row;
  63. static int Screen_Cols, Screen_Rows;
  64. static int This_Row, This_Col;
  65. static int This_Color;               /* only the first 8 bits of this
  66.                     * are used.  The highest bit is used
  67.                     * to indicate an alternate character
  68.                     * set.  This leaves 127 userdefineable
  69.                     * color combination.
  70.                     */
  71.  
  72. #ifndef pc_system
  73. #define ALT_CHAR_FLAG 0x80
  74. #else
  75. #define ALT_CHAR_FLAG 0x00
  76. #endif
  77.  
  78.  
  79. static void blank_line (SLang_Char_Type *p, int n, unsigned char ch)
  80. {
  81.    register SLang_Char_Type *pmax = p + n;
  82.    
  83.    while (p < pmax)
  84.      {
  85.     *p = (This_Color << colorshift) | (SLang_Char_Type) ch;
  86.     p++;
  87.      }
  88. }
  89.  
  90.  
  91. static void clear_region (int row, int n)
  92. {
  93.    int i;
  94.    int imax = row + n;
  95.    
  96.    if (imax > Screen_Rows) imax = Screen_Rows;
  97.    for (i = row; i < imax; i++)
  98.      {
  99.     if (i >= 0)
  100.       {
  101.          blank_line (SL_Screen[i].neew, Screen_Cols, ' ');
  102.          SL_Screen[i].flags |= TOUCHED;
  103.       }
  104.      }
  105. }
  106.  
  107. void SLsmg_erase_eol (void)
  108. {
  109.    int c = This_Col;
  110.    if ((This_Row < 0) || (This_Row >= Screen_Rows)) return;
  111.    if (c < 0) c = 0; else if (c >= Screen_Cols) return;
  112.    blank_line (SL_Screen[This_Row].neew + c , Screen_Cols - c, ' ');
  113.    SL_Screen[This_Row].flags |= TOUCHED;
  114. }
  115.  
  116. void SLsmg_gotorc (int r, int c)
  117. {
  118.    This_Row = r;
  119.    This_Col = c;
  120. }
  121.  
  122. int SLsmg_get_row (void)
  123. {
  124.    return This_Row;
  125. }
  126.  
  127. int SLsmg_get_column (void)
  128. {
  129.    return This_Col;
  130. }
  131.  
  132. void SLsmg_erase_eos (void)
  133. {
  134.    SLsmg_erase_eol ();
  135.    clear_region (This_Row + 1, Screen_Rows);
  136. }
  137.  
  138. static int This_Alt_Char;
  139.  
  140. #ifndef pc_system
  141. void SLsmg_set_char_set (int i)
  142. {
  143. #ifdef linux_unicode
  144.    if (SLtt_Unicode) return; /* char set has no meaning :) */
  145. #endif   
  146.    if (SLtt_Use_Blink_For_ACS) return; /* alt chars not used and the alt bit
  147.                     * is used to indicate a blink.
  148.                     */
  149.    if (i) This_Alt_Char = ALT_CHAR_FLAG;
  150.    else This_Alt_Char = 0;
  151.    This_Color &= 0x7F;
  152.    This_Color |= This_Alt_Char;
  153. }
  154. #endif
  155.  
  156. void SLsmg_set_color (int color)
  157. {
  158.    if (color < 0) return;
  159.    This_Color = color | This_Alt_Char;
  160. }
  161.  
  162.  
  163. void SLsmg_reverse_video (void)
  164. {
  165.    SLsmg_set_color (1);
  166. }
  167.  
  168.  
  169. void SLsmg_normal_video (void)
  170. {
  171.    This_Color = This_Alt_Char;           /* reset video but NOT char set. */
  172. }
  173.  
  174.  
  175. static int point_visible (int col_too)
  176. {
  177.    return ((This_Row >= Start_Row) && (This_Row < Start_Row + Screen_Rows)
  178.        && ((col_too == 0)
  179.            || ((This_Col >= Start_Col) 
  180.            && (This_Col < Start_Col + Screen_Cols))));
  181. }
  182.    
  183. void SLsmg_printf (char *fmt, ...)
  184. {
  185.    char p[1000];
  186.    va_list ap;
  187.  
  188.    va_start(ap, fmt);
  189.    (void) vsprintf(p, fmt, ap);
  190.    va_end(ap);
  191.    
  192.    SLsmg_write_string (p);
  193. }
  194.  
  195. void SLsmg_write_string (char *str)
  196. {
  197.    SLsmg_write_nchars (str, strlen (str));
  198. }
  199.  
  200. void SLsmg_write_nstring (char *str, int n)
  201. {
  202.    int width;
  203.    char blank = ' ';
  204.    if (str == NULL) width = 0;
  205.    else 
  206.      {
  207.     width = strlen (str);
  208.     if (width > n) width = n;
  209.     SLsmg_write_nchars (str, width);
  210.      }
  211.    while (width++ < n) SLsmg_write_nchars (&blank, 1);
  212. }
  213.  
  214. void SLsmg_write_wrapped_string (char *s, int r, int c, int dr, int dc, int fill)
  215. {
  216.    register char ch, *p;
  217.    int maxc = dc;
  218.    
  219.    if ((dr == 0) || (dc == 0)) return;
  220.    p = s;
  221.    dc = 0;
  222.    while (1)
  223.      {
  224.     ch = *p++;
  225.     if ((ch == 0) || (ch == '\n'))
  226.       {
  227.          int diff;
  228.          
  229.          diff = maxc - dc;
  230.          
  231.          SLsmg_gotorc (r, c);
  232.          SLsmg_write_nchars (s, dc);
  233.          if (fill && (diff > 0))
  234.            {
  235.           while (diff--) SLsmg_write_char (' ');
  236.            }
  237.          if ((ch == 0) || (dr == 1)) break;
  238.          
  239.          r++;
  240.          dc = 0;
  241.          dr--;
  242.          s = p;
  243.       }
  244.     else if (dc == maxc)
  245.       {
  246.          SLsmg_gotorc (r, c);
  247.          SLsmg_write_nchars (s, dc + 1);
  248.          if (dr == 1) break;
  249.  
  250.          r++;
  251.          dc = 0;
  252.          dr--;
  253.          s = p;
  254.       }
  255.     else dc++;
  256.      }
  257. }
  258.  
  259.    
  260.  
  261. int SLsmg_Tab_Width = 8;
  262.  
  263. /* Minimum value for which eight bit char is displayed as is. */
  264.  
  265. #ifndef pc_system
  266. int SLsmg_Display_Eight_Bit = 160;
  267. static unsigned char Alt_Char_Set[129];/* 129th is used as a flag */
  268. #else
  269. int SLsmg_Display_Eight_Bit = 128;
  270. #endif
  271.  
  272. void SLsmg_write_nchars (char *str, int n)
  273. {
  274.    register SLang_Char_Type *p, old, neew;
  275.    unsigned char ch;
  276.    unsigned int flags;
  277.    int len, start_len = Start_Col, max_len;
  278.    char *str_max = str + n;
  279.    
  280.    if (point_visible (0) == 0) return;
  281.    
  282.    len = This_Col;
  283.    max_len = start_len + Screen_Cols;
  284.  
  285.    p = SL_Screen[This_Row].neew;
  286.    if (len > start_len) p += (len - start_len);
  287.    
  288.    flags = SL_Screen[This_Row].flags;
  289.    while ((len < max_len) && (str < str_max))
  290.      {    
  291.     ch = (unsigned char) *str++;
  292. #ifndef pc_system
  293. #ifdef linux_unicode
  294.         if (!SLtt_Unicode)
  295. #endif
  296.       if (This_Alt_Char)
  297.         {
  298.            ch = Alt_Char_Set[ch & 0x7F];
  299.         }
  300. #endif
  301.     if (((ch >= ' ') && (ch < 127))
  302.         || (ch >= (unsigned char) SLsmg_Display_Eight_Bit))
  303.       {
  304.          len += 1;
  305.          if (len > start_len)
  306.            {
  307.           old = *p;
  308.           neew = (This_Color << colorshift) | (SLang_Char_Type) ch;
  309.           if (old != neew)
  310.             {
  311.                flags |= TOUCHED;
  312.                *p = neew;
  313.             }
  314.           p++;
  315.            }
  316.       }
  317.     
  318.     else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
  319.       {
  320.          n = len;
  321.          n += SLsmg_Tab_Width;
  322.          n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
  323.          if (len + n > max_len) n = max_len - len;
  324.          neew = (This_Color << colorshift) | (SLang_Char_Type) ' ';
  325.          while (n--)
  326.            {
  327.           len += 1;
  328.           if (len > start_len)
  329.             {
  330.                if (*p != neew) 
  331.              {
  332.                 flags |= TOUCHED;
  333.                 *p = neew;
  334.              }
  335.                p++;
  336.             }
  337.            }
  338.       }
  339.     else if (ch == '\n') break;
  340.     else
  341.       {
  342.          if (ch & 0x80)
  343.            {
  344.           neew = (This_Color << colorshift) | (SLang_Char_Type) '~';
  345.           len += 1;
  346.           if (len > start_len)
  347.             {
  348.                if (*p != neew)
  349.              {
  350.                 *p = neew;
  351.                 flags |= TOUCHED;
  352.              }
  353.                p++;
  354.                if (len == max_len) break;
  355.                ch &= 0x7F;
  356.             }
  357.            }
  358.          
  359.          len += 1;
  360.          if (len > start_len)
  361.            {
  362.           neew = (This_Color << colorshift) | (SLang_Char_Type) '^';
  363.           if (*p != neew)
  364.             {
  365.                *p = neew;
  366.                flags |= TOUCHED;
  367.             }
  368.           p++;
  369.           if (len == max_len) break;
  370.            }
  371.          
  372.          if (ch == 127) ch = '?'; else ch = ch + '@';
  373.          len++;
  374.          if (len > start_len)
  375.            {
  376.           neew = (This_Color << colorshift) | (SLang_Char_Type) ch;
  377.           if (*p != neew)
  378.             {
  379.                *p = neew;
  380.                flags |= TOUCHED;
  381.             }
  382.           p++;
  383.            }
  384.       }
  385.      }
  386.    
  387.    SL_Screen[This_Row].flags = flags;
  388.    This_Col = len;
  389. }
  390.  
  391. void SLsmg_write_unicode (unsigned short ch)
  392. {
  393. #ifdef linux_unicode
  394.    register SLang_Char_Type *p, old, neew;
  395.    
  396.    if (ch < 0x100) 
  397.      {
  398.         SLsmg_write_nchars ((char *) &ch, 1);
  399.         return;
  400.      }
  401.    
  402.    if (point_visible (0) == 0) return;
  403.    
  404.    p = SL_Screen[This_Row].neew;
  405.    if (This_Col > Start_Col) p += (This_Col - Start_Col);
  406.    if (This_Col >= Start_Col + Screen_Cols)
  407.         return;
  408.    This_Col++;
  409.    if (This_Col > Start_Col)
  410.      {
  411.     old = *p;
  412.     neew = (This_Color << colorshift) | (SLang_Char_Type) ch;
  413.     if (old != neew)
  414.       {
  415.          SL_Screen[This_Row].flags |= TOUCHED;
  416.          *p = neew;
  417.       }
  418.      }    
  419. #endif
  420. }
  421.  
  422. void SLsmg_write_char (char ch)
  423. {
  424.    SLsmg_write_nchars (&ch, 1);
  425. }
  426.  
  427. static int Cls_Flag;
  428.  
  429.  
  430. void SLsmg_cls (void)
  431. {
  432.    This_Color = This_Alt_Char;
  433.    clear_region (0, Screen_Rows);
  434.    Cls_Flag = 1;
  435. }
  436.  
  437. static void do_copy (SLang_Char_Type *a, SLang_Char_Type *b)
  438. {
  439.    SLang_Char_Type *amax = a + Screen_Cols;
  440.    
  441.    while (a < amax) *a++ = *b++;
  442. }
  443.  
  444. #ifndef pc_system
  445. int SLsmg_Scroll_Hash_Border = 0;
  446. static unsigned long compute_hash (SLang_Char_Type *s, int n)
  447. {
  448.    register unsigned long h = 0, g;
  449.    register unsigned long sum = 0;
  450.    register SLang_Char_Type *smax, ch;
  451.    int is_blank = 2;
  452.    
  453.    s += SLsmg_Scroll_Hash_Border;
  454.    smax = s + (n - SLsmg_Scroll_Hash_Border);
  455.    while (s < smax) 
  456.      {
  457.     ch = *s++;
  458. #ifdef linux_unicode
  459.     if (is_blank && ((ch & 0xFFFF) != 32)) is_blank--;
  460. #else    
  461.     if (is_blank && ((ch & 0xFF) != 32)) is_blank--;
  462. #endif    
  463.     
  464.     sum += ch & 0xFFFF;
  465.     
  466.     h = sum + (h << 3);
  467.     if ((g = h & 0xE0000000L) != 0)
  468.       {
  469.          h = h ^ (g >> 24);
  470.          h = h ^ g;
  471.       }
  472. #ifdef linux_unicode      
  473.     sum += (ch >> 16) & 0xFFFF;
  474.     
  475.     h = sum + (h << 3);
  476.     if ((g = h & 0xE0000000L) != 0)
  477.       {
  478.          h = h ^ (g >> 24);
  479.          h = h ^ g;
  480.       }
  481. #endif      
  482.      }
  483.    if (is_blank) return 0;
  484.    return h;
  485. }
  486.  
  487. unsigned long Blank_Hash;
  488.  
  489. static void try_scroll (void)
  490. {
  491.    int i, j, di, r1, r2, rmin, rmax;
  492.    unsigned long hash;
  493.    int color, did_scroll = 0;
  494.    SLang_Char_Type *tmp;
  495.    int ignore;
  496.    
  497.    /* find region limits */
  498.    for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
  499.      {
  500.     if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
  501.       break;
  502.      }
  503.    
  504.    for (rmin = 0; rmin < rmax; rmin++)
  505.      {
  506.     if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
  507.       break;
  508.      }
  509.    
  510.    for (i = rmax; i > rmin; i--)
  511.      {
  512.     hash = SL_Screen[i].new_hash;
  513.     if (hash == Blank_Hash) continue;
  514.     
  515.     if ((hash == SL_Screen[i].old_hash)
  516.         || ((i + 1 < Screen_Rows) && (hash == SL_Screen[i + 1].old_hash))
  517.         || ((i - 1 > rmin) && (SL_Screen[i].old_hash == SL_Screen[i - 1].new_hash)))
  518.       continue;
  519.     
  520.     for (j = i - 1; j >= rmin; j--)
  521.       {
  522.          if (hash == SL_Screen[j].old_hash) break;
  523.       }
  524.     if (j < rmin) continue;
  525.     
  526.     r2 = i;                   /* end scroll region */
  527.     
  528.     di = i - j;
  529.     j--;
  530.     ignore = 0;
  531.     while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
  532.       {
  533.          if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
  534.          j--;
  535.       }
  536.     r1 = j + 1;
  537.     
  538.     /* If this scroll only scrolls this line into place, don't do it.
  539.      */
  540.     if ((di > 1) && (r1 + di + ignore == r2)) continue;
  541.     
  542.     /* If there is anything in the scrolling region that is ok, abort the 
  543.      * scroll.
  544.      */
  545.  
  546.     for (j = r1; j <= r2; j++)
  547.       {
  548.          if ((SL_Screen[j].old_hash != Blank_Hash)
  549.          && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
  550.            {
  551.           /* See if the scroll is happens to scroll this one into place. */
  552.           if ((j + di > r2) || (SL_Screen[j].old_hash != SL_Screen[j + di].new_hash))
  553.             break;
  554.            }
  555.       }
  556.     if (j <= r2) continue;
  557.     
  558.     color = This_Color;  This_Color = 0;
  559.     did_scroll = 1;
  560.     SLtt_normal_video ();
  561.     SLtt_set_scroll_region (r1, r2);
  562.     SLtt_goto_rc (0, 0);
  563.     SLtt_reverse_index (di);
  564.     SLtt_reset_scroll_region ();
  565.     /* Now we have a hole in the screen.  Make the virtual screen look 
  566.      * like it.
  567.      */
  568.     for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
  569.     
  570.     while (di--)
  571.       {
  572.          tmp = SL_Screen[r2].old;
  573.          for (j = r2; j > r1; j--)
  574.            {
  575.           SL_Screen[j].old = SL_Screen[j - 1].old;
  576.           SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
  577.            }
  578.          SL_Screen[r1].old = tmp;
  579.          blank_line (SL_Screen[r1].old, Screen_Cols, ' ');
  580.          SL_Screen[r1].old_hash = Blank_Hash;
  581.          r1++;
  582.       }
  583.     This_Color = color;
  584.      }
  585.    if (did_scroll) return;
  586.    
  587.    /* Try other direction */
  588.  
  589.    for (i = rmin; i < rmax; i++)
  590.      {
  591.     hash = SL_Screen[i].new_hash;
  592.     if (hash == Blank_Hash) continue;
  593.     if (hash == SL_Screen[i].old_hash) continue;
  594.     
  595.     /* find a match further down screen */
  596.     for (j = i + 1; j <= rmax; j++)
  597.       {
  598.          if (hash == SL_Screen[j].old_hash) break;
  599.       }
  600.     if (j > rmax) continue;
  601.     
  602.     r1 = i;                   /* beg scroll region */
  603.     di = j - i;               /* number of lines to scroll */
  604.     j++;                   /* since we know this is a match */
  605.     
  606.     /* find end of scroll region */
  607.     ignore = 0;
  608.     while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
  609.       {
  610.          if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
  611.          j++;
  612.       }
  613.     r2 = j - 1;               /* end of scroll region */
  614.     
  615.     /* If this scroll only scrolls this line into place, don't do it.
  616.      */
  617.     if ((di > 1) && (r1 + di + ignore == r2)) continue;
  618.  
  619.     /* If there is anything in the scrolling region that is ok, abort the 
  620.      * scroll.
  621.      */
  622.     
  623.     for (j = r1; j <= r2; j++)
  624.       {
  625.          if ((SL_Screen[j].old_hash != Blank_Hash)
  626.          && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
  627.            {
  628.           if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
  629.             break;
  630.            }
  631.          
  632.       }
  633.     if (j <= r2) continue;
  634.     
  635.     color = This_Color;  This_Color = 0;
  636.     SLtt_normal_video ();
  637.     SLtt_set_scroll_region (r1, r2);
  638.     SLtt_goto_rc (0, 0);           /* relative to scroll region */
  639.     SLtt_delete_nlines (di);
  640.     SLtt_reset_scroll_region ();
  641.     /* Now we have a hole in the screen.  Make the virtual screen look 
  642.      * like it.
  643.      */
  644.     for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
  645.     
  646.     while (di--)
  647.       {
  648.          tmp = SL_Screen[r1].old;
  649.          for (j = r1; j < r2; j++)
  650.            {
  651.           SL_Screen[j].old = SL_Screen[j + 1].old;
  652.           SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
  653.            }
  654.          SL_Screen[r2].old = tmp;
  655.          blank_line (SL_Screen[r2].old, Screen_Cols, ' ');
  656.          SL_Screen[r2].old_hash = Blank_Hash;
  657.          r2--;
  658.       }
  659.     This_Color = color;
  660.      }
  661. }
  662.  
  663. #endif   /* NOT pc_system */
  664.         
  665.     
  666.     
  667. static int Smg_Inited;
  668.  
  669. void SLsmg_refresh (void)
  670. {
  671.    int i;
  672.    
  673.    if (Smg_Inited == 0) return;
  674. #ifndef pc_system
  675.    for (i = 0; i < Screen_Rows; i++)
  676.      {
  677.     if (SL_Screen[i].flags == 0) continue;
  678.     SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
  679.      }
  680. #endif
  681.    
  682.    if (Cls_Flag) 
  683.      {
  684.     SLtt_normal_video ();  SLtt_cls ();
  685.      }
  686. #ifndef pc_system
  687.    else if (SLtt_Term_Cannot_Scroll == 0) try_scroll ();
  688. #endif
  689.  
  690.    for (i = 0; i < Screen_Rows; i++)
  691.      {
  692.     int trashed;
  693.     
  694.     if (SL_Screen[i].flags == 0) continue;
  695.     
  696.     if (SL_Screen[i].flags & TRASHED)
  697.       {
  698.          SLtt_goto_rc (i, -1); /* Force cursor to move */
  699.          SLtt_goto_rc (i, 0);
  700.          if (Cls_Flag == 0) SLtt_del_eol ();
  701.          trashed = 1;
  702.       }
  703.     else trashed = 0;
  704.     
  705.     if (Cls_Flag || trashed) 
  706.       {
  707.          int color = This_Color;
  708.          This_Color = 0;
  709.          blank_line (SL_Screen[i].old, Screen_Cols, ' ');
  710.          This_Color = color;
  711.       }
  712.     
  713.     SL_Screen[i].old[Screen_Cols] = 0;
  714.     SL_Screen[i].neew[Screen_Cols] = 0;
  715.     
  716.     SLtt_smart_puts (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
  717.     do_copy (SL_Screen[i].old, SL_Screen[i].neew);
  718.     SL_Screen[i].flags = 0;
  719. #ifndef pc_system
  720.     SL_Screen[i].old_hash = SL_Screen[i].new_hash;
  721. #endif
  722.      }
  723.    
  724.    if (point_visible (1)) SLtt_goto_rc (This_Row - Start_Row, This_Col - Start_Col);
  725.    SLtt_flush_output ();
  726.    Cls_Flag = 0;
  727. }
  728.  
  729. static int compute_clip (int row, int n, int box_start, int box_end,
  730.              int *rmin, int *rmax)
  731. {
  732.    int row_max;
  733.    
  734.    if (n < 0) return 0;
  735.    if (row >= box_end) return 0;
  736.    row_max = row + n;
  737.    if (row_max <= box_start) return 0;
  738.    
  739.    if (row < box_start) row = box_start;
  740.    if (row_max >= box_end) row_max = box_end;
  741.    *rmin = row;
  742.    *rmax = row_max;
  743.    return 1;
  744. }
  745.  
  746. void SLsmg_touch_lines (int row, int n)
  747. {
  748.    int i;
  749.    int r1, r2;
  750.    
  751.    if (0 == compute_clip (row, n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
  752.      return;
  753.    
  754.    r1 -= Start_Row;
  755.    r2 -= Start_Row;
  756.    for (i = r1; i < r2; i++)
  757.      {
  758.     SL_Screen[i].flags |= TRASHED;
  759.      }
  760. }
  761.  
  762. #ifndef pc_system
  763. static char Fake_Alt_Char_Pairs [] = "a:j+k+l+m+q-t+u+v+w+x|";
  764.  
  765. static void init_alt_char_set (void)
  766. {
  767.    int i = 0;
  768.    unsigned char *p, *pmax, ch;
  769.    
  770.    if (Alt_Char_Set[128] == 128) return;
  771.  
  772.    while (i <= 128) 
  773.      {
  774.     Alt_Char_Set [i] = i;
  775.     i++;
  776.      }
  777.    
  778.    /* Map to VT100 */
  779.    if (SLtt_Has_Alt_Charset)
  780.      {
  781.     p = (unsigned char *) SLtt_Graphics_Char_Pairs;
  782.     if (p == NULL) return;
  783.      }
  784.    else    p = (unsigned char *) Fake_Alt_Char_Pairs;
  785.    pmax = p + strlen ((char *) p);
  786.    
  787.    /* Some systems have messed up entries for this */
  788.    while (p < pmax)
  789.      {
  790.     ch = *p++;
  791.     ch &= 0x7F;               /* should be unnecessary */
  792.     Alt_Char_Set [ch] = *p;
  793.     p++;
  794.      }
  795. }
  796. #endif
  797.  
  798. void SLsmg_suspend_smg (void)
  799. {
  800.    SLtt_reset_video ();
  801. }
  802.  
  803. void SLsmg_resume_smg (void)
  804. {
  805.    int i;
  806.    SLtt_init_video ();
  807.    Cls_Flag = 1;
  808.    for (i = 0; i < Screen_Rows; i++)
  809.      SL_Screen[i].flags |= TRASHED;
  810.    SLsmg_refresh ();
  811. }
  812.  
  813.  
  814. int SLsmg_init_smg (void)
  815. {
  816.    int i, len;
  817.    SLang_Char_Type *old, *neew;
  818.    
  819.    if (Smg_Inited) SLsmg_reset_smg ();
  820.    SLtt_init_video ();
  821.    Screen_Cols = SLtt_Screen_Cols;
  822.    Screen_Rows = SLtt_Screen_Rows;
  823.    This_Col = This_Row = Start_Col = Start_Row = 0;
  824.  
  825.    This_Color = 0;
  826.    This_Alt_Char = 0;
  827.    Cls_Flag = 1;
  828. #ifndef pc_system
  829.    init_alt_char_set ();
  830. #endif
  831.    len = Screen_Cols + 3;
  832.    for (i = 0; i < Screen_Rows; i++)
  833.      {
  834.     if ((NULL == (old = (SLang_Char_Type *) SLMALLOC (sizeof(SLang_Char_Type) * len)))
  835.         || ((NULL == (neew = (SLang_Char_Type *) SLMALLOC (sizeof(SLang_Char_Type) * len)))))
  836.       {
  837.          SLang_Error = SL_MALLOC_ERROR;
  838.          return 0;
  839.       }
  840.     blank_line (old, len, ' ');
  841.     blank_line (neew, len, ' ');
  842.     SL_Screen[i].old = old;
  843.     SL_Screen[i].neew = neew;
  844.     SL_Screen[i].flags = 0;
  845. #ifndef pc_system
  846.     Blank_Hash = compute_hash (old, Screen_Cols);
  847.     SL_Screen[i].new_hash = SL_Screen[i].old_hash =  Blank_Hash;
  848. #endif
  849.      }
  850.    Smg_Inited = 1;
  851.    return 1;
  852. }
  853.  
  854.  
  855. void SLsmg_reset_smg (void)
  856. {
  857.    int i;
  858.    
  859.    if (Smg_Inited == 0) return;
  860.    for (i = 0; i < Screen_Rows; i++)
  861.      {
  862.     if (SL_Screen[i].old != NULL) SLFREE (SL_Screen[i].old);
  863.     if (SL_Screen[i].neew != NULL) SLFREE (SL_Screen[i].neew);
  864.     SL_Screen[i].old = SL_Screen[i].neew = NULL;
  865.      }
  866.    SLtt_reset_video ();
  867.    This_Alt_Char = This_Color = 0;
  868.    Smg_Inited = 0;
  869. }
  870.  
  871.  
  872. SLang_Char_Type SLsmg_char_at (void)
  873. {
  874.    if (point_visible (1))
  875.      {
  876.     return SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
  877.      }
  878.    return 0;
  879. }
  880.  
  881. void SLsmg_vprintf (char *fmt, va_list ap)
  882. {
  883.    char p[1000];
  884.    
  885.    (void) vsprintf(p, fmt, ap);
  886.    
  887.    SLsmg_write_string (p);
  888. }
  889.  
  890. void SLsmg_set_screen_start (int *r, int *c)
  891. {
  892.    int or = Start_Row, oc = Start_Col;
  893.    
  894.    if (c == NULL) Start_Col = 0;
  895.    else
  896.      {
  897.     Start_Col = *c;
  898.     *c = oc;
  899.      }
  900.    if (r == NULL) Start_Row = 0;
  901.    else
  902.      {
  903.     Start_Row = *r;
  904.     *r = or;
  905.      }
  906. }
  907.  
  908. void SLsmg_draw_object (int r, int c, unsigned char object)
  909. {
  910.    This_Row = r;  This_Col = c;
  911.  
  912. #ifdef linux_unicode
  913.    if (SLtt_Unicode)
  914.      {
  915.         int i;
  916.         unsigned short ch = 0xfffd;
  917.         
  918.         for (i = 0; i < sizeof (UniConv_Table) / sizeof (UniConv_Table [0]);
  919.             i++)
  920.           if (object == UniConv_Table [i].acs)
  921.             {
  922.                ch = UniConv_Table [i].uni;
  923.                break;
  924.             }
  925.         if (point_visible (1))
  926.             SLsmg_write_unicode (SLtt_fix_unicode (ch));
  927.         This_Col = c + 1;
  928.         return;
  929.      }
  930. #endif
  931.    if (point_visible (1))
  932.      {
  933.     int tac = This_Alt_Char;
  934.     This_Alt_Char = ALT_CHAR_FLAG;
  935.     This_Color |= This_Alt_Char;
  936.     SLsmg_write_char (object);
  937.     This_Alt_Char = tac;
  938.     This_Color = (This_Color & 0x7F) | This_Alt_Char;
  939.      }
  940.  
  941.    This_Col = c + 1;
  942. }
  943.  
  944. void SLsmg_draw_unicode (int r, int c, unsigned short object)
  945. {
  946. #ifdef linux_unicode
  947.     This_Row = r; This_Col = c;
  948.     
  949.     SLsmg_write_unicode (SLtt_fix_unicode (object));
  950.     This_Col = c + 1;
  951. #endif
  952. }
  953.  
  954. void SLsmg_draw_hline (int n)
  955. {
  956.    static unsigned char hbuf[16];
  957.    int count;
  958.    int cmin, cmax;
  959.    int final_col = This_Col + n;
  960.    int tac = This_Alt_Char;
  961.    
  962.    if ((This_Row < Start_Row) || (This_Row >= Start_Row + Screen_Rows) 
  963.        || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + Screen_Cols,
  964.                   &cmin, &cmax)))
  965.      {
  966.     This_Col = final_col;
  967.     return;
  968.      }
  969.  
  970.    n = cmax - cmin;
  971.    This_Col = cmin;
  972.    
  973. #ifdef linux_unicode   
  974.    if (SLtt_Unicode)
  975.      {
  976.         unsigned short ch = SLtt_fix_unicode (SLUNI_HLINE_CHAR);
  977.         while (n-- > 0)
  978.            SLsmg_write_unicode (ch);
  979.         This_Col = final_col;
  980.         return;
  981.      }
  982. #endif     
  983.    if (hbuf[0] == 0)
  984.      {
  985.     MEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
  986.      }
  987.    
  988.    count = n / 16;
  989.    This_Alt_Char = ALT_CHAR_FLAG;
  990.    This_Color |= This_Alt_Char;
  991.    
  992.    SLsmg_write_nchars ((char *) hbuf, n % 16);
  993.    while (count-- > 0)
  994.      {
  995.     SLsmg_write_nchars ((char *) hbuf, 16);
  996.      }
  997.    
  998.    This_Alt_Char = tac;
  999.    This_Color = (This_Color & 0x7F) | This_Alt_Char;
  1000.    This_Col = final_col;
  1001. }
  1002.  
  1003. void SLsmg_draw_double_hline (int n)
  1004. {
  1005. #ifdef linux_unicode
  1006.    int cmin, cmax;
  1007.    int final_col = This_Col + n;
  1008.    
  1009.    if (SLtt_Unicode)
  1010.      {
  1011.         unsigned short ch;
  1012.         
  1013.         if ((This_Row < Start_Row) || (This_Row >= Start_Row + Screen_Rows) 
  1014.             || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + Screen_Cols,
  1015.                        &cmin, &cmax)))
  1016.           {
  1017.          This_Col = final_col;
  1018.          return;
  1019.           }
  1020.  
  1021.         n = cmax - cmin;
  1022.         This_Col = cmin;
  1023.         ch = SLtt_fix_unicode (SLUNI_DHLINE_CHAR);
  1024.    
  1025.         while (n-- > 0)
  1026.            SLsmg_write_unicode (ch);
  1027.         This_Col = final_col;
  1028.         return;
  1029.      }
  1030.    else
  1031. #endif
  1032.      SLsmg_draw_hline (n);
  1033. }
  1034.  
  1035. void SLsmg_draw_vline (int n)
  1036. {
  1037.    unsigned char ch = SLSMG_VLINE_CHAR;
  1038.    int tac = This_Alt_Char;
  1039.    int c = This_Col;   
  1040.    int rmin, rmax;
  1041.    int final_row = This_Row + n;
  1042.  
  1043.    if (((c < Start_Col) || (c >= Start_Col + Screen_Cols)) ||
  1044.        (0 == compute_clip (This_Row, n, Start_Row, Start_Row + Screen_Rows,
  1045.               &rmin, &rmax)))
  1046.      {
  1047.     This_Row = final_row;
  1048.     return;
  1049.      }
  1050.  
  1051. #ifdef linux_unicode
  1052.    if (SLtt_Unicode)
  1053.      {
  1054.         unsigned short ch = SLtt_fix_unicode (SLUNI_VLINE_CHAR);
  1055.         
  1056.         for (This_Row = rmin; This_Row < rmax; This_Row++)
  1057.           {
  1058.              This_Col = c;
  1059.              SLsmg_write_unicode (ch);
  1060.           }
  1061.      }
  1062.    else
  1063. #endif   
  1064.      {
  1065.         This_Alt_Char = ALT_CHAR_FLAG;
  1066.         This_Color |= This_Alt_Char;
  1067.     
  1068.         for (This_Row = rmin; This_Row < rmax; This_Row++)
  1069.           {
  1070.          This_Col = c;
  1071.          SLsmg_write_nchars ((char *) &ch, 1);
  1072.           }
  1073.    
  1074.         This_Alt_Char = tac;
  1075.         This_Color = (This_Color & 0x7F) | This_Alt_Char;
  1076.      }
  1077.    
  1078.    This_Col = c;  This_Row = final_row;
  1079. }
  1080.  
  1081. void SLsmg_draw_double_vline (int n)
  1082. {
  1083. #ifdef linux_unicode
  1084.    int c = This_Col, rmin, rmax;
  1085.    int final_row = This_Row + n;
  1086.  
  1087.    if (SLtt_Unicode)
  1088.      {   
  1089.         unsigned short ch = SLtt_fix_unicode (SLUNI_DVLINE_CHAR);
  1090.         
  1091.         if (((c < Start_Col) || (c >= Start_Col + Screen_Cols)) ||
  1092.             (0 == compute_clip (This_Row, n, Start_Row, Start_Row + Screen_Rows,
  1093.                    &rmin, &rmax)))
  1094.           {
  1095.          This_Row = final_row;
  1096.          return;
  1097.           }
  1098.         
  1099.         for (This_Row = rmin; This_Row < rmax; This_Row++)
  1100.           {
  1101.              This_Col = c;
  1102.              SLsmg_write_unicode (ch);
  1103.           }
  1104.         This_Col = c;  This_Row = final_row;
  1105.      }
  1106.    else
  1107. #endif
  1108.      SLsmg_draw_vline (n);   
  1109. }
  1110.  
  1111. void SLsmg_draw_box (int r, int c, int dr, int dc)
  1112. {
  1113.    if (!dr || !dc) return; 
  1114.    This_Row = r;  This_Col = c;
  1115.    dr--; dc--;
  1116.    SLsmg_draw_hline (dc);  
  1117.    SLsmg_draw_vline (dr);
  1118.    This_Row = r;  This_Col = c;
  1119.    SLsmg_draw_vline (dr);
  1120.    SLsmg_draw_hline (dc);   
  1121. #ifdef linux_unicode
  1122.    if (SLtt_Unicode)
  1123.      {
  1124.         SLsmg_draw_unicode (r, c, SLUNI_ULCORN_CHAR);
  1125.         SLsmg_draw_unicode (r, c + dc, SLUNI_URCORN_CHAR);
  1126.         SLsmg_draw_unicode (r + dr, c, SLUNI_LLCORN_CHAR);
  1127.         SLsmg_draw_unicode (r + dr, c + dc, SLUNI_LRCORN_CHAR);
  1128.      }
  1129.    else
  1130. #endif
  1131.      {
  1132.         SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
  1133.         SLsmg_draw_object (r, c + dc, SLSMG_URCORN_CHAR);
  1134.         SLsmg_draw_object (r + dr, c, SLSMG_LLCORN_CHAR);
  1135.         SLsmg_draw_object (r + dr, c + dc, SLSMG_LRCORN_CHAR);
  1136.      }
  1137.    This_Row = r; This_Col = c;
  1138. }
  1139.    
  1140. void SLsmg_draw_double_box (int r, int c, int dr, int dc)
  1141. {
  1142.    if (!dr || !dc) return; 
  1143.    This_Row = r;  This_Col = c;
  1144.    dr--; dc--;
  1145.    SLsmg_draw_double_hline (dc);  
  1146.    SLsmg_draw_double_vline (dr);
  1147.    This_Row = r;  This_Col = c;
  1148.    SLsmg_draw_double_vline (dr);
  1149.    SLsmg_draw_double_hline (dc);   
  1150. #ifdef linux_unicode
  1151.    if (SLtt_Unicode)
  1152.      {
  1153.         SLsmg_draw_unicode (r, c, SLUNI_DULCORN_CHAR);
  1154.         SLsmg_draw_unicode (r, c + dc, SLUNI_DURCORN_CHAR);
  1155.         SLsmg_draw_unicode (r + dr, c, SLUNI_DLLCORN_CHAR);
  1156.         SLsmg_draw_unicode (r + dr, c + dc, SLUNI_DLRCORN_CHAR);
  1157.      }
  1158.    else
  1159. #endif
  1160.      {
  1161.         SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
  1162.         SLsmg_draw_object (r, c + dc, SLSMG_URCORN_CHAR);
  1163.         SLsmg_draw_object (r + dr, c, SLSMG_LLCORN_CHAR);
  1164.         SLsmg_draw_object (r + dr, c + dc, SLSMG_LRCORN_CHAR);
  1165.      }
  1166.    This_Row = r; This_Col = c;
  1167. }
  1168.    
  1169. void SLsmg_fill_region (int r, int c, int dr, int dc, unsigned char ch)
  1170. {
  1171.    static unsigned char hbuf[16];
  1172.    int count;
  1173.    int dcmax, rmax;
  1174.    
  1175.    
  1176.    if ((dc < 0) || (dr < 0)) return;
  1177.    
  1178.    SLsmg_gotorc (r, c);
  1179.    r = This_Row; c = This_Col;
  1180.    
  1181.    dcmax = Screen_Cols - This_Col;
  1182.    if (dc > dcmax) dc = dcmax;
  1183.    
  1184.    rmax = This_Row + dr;
  1185.    if (rmax > Screen_Rows) rmax = Screen_Rows;
  1186.  
  1187. #ifndef pc_system
  1188.    ch = Alt_Char_Set[ch];
  1189. #endif
  1190.    if (ch != hbuf[0]) MEMSET ((char *) hbuf, (char) ch, 16);
  1191.    
  1192.    for (This_Row = r; This_Row < rmax; This_Row++)
  1193.      {
  1194.     This_Col = c;
  1195.     count = dc / 16;
  1196.     SLsmg_write_nchars ((char *) hbuf, dc % 16);
  1197.     while (count-- > 0)
  1198.       {
  1199.          SLsmg_write_nchars ((char *) hbuf, 16);
  1200.       }
  1201.      }
  1202.    
  1203.    This_Row = r;
  1204. }
  1205.  
  1206.