home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / most423.zip / display.c < prev    next >
C/C++ Source or Header  |  1997-03-05  |  17KB  |  674 lines

  1. #include <stdio.h>
  2.  
  3. #ifndef sequent
  4. #include <stdlib.h>
  5. #endif
  6.  
  7. #ifdef unix
  8. #ifndef sequent
  9. # include <unistd.h>
  10. #endif
  11. #endif
  12.  
  13.  
  14. #include "externs.h"
  15. #include "buffer.h"
  16. #include "display.h"
  17. #include "sysdep.h"
  18.  
  19. int SCREEN_WIDTH = 80;
  20. #ifdef __EMX__
  21. int SCREEN_HEIGHT = 25;
  22. int SCREEN_ROWS = 24; /* height - 1 */
  23. #else
  24. int SCREEN_HEIGHT = 24;
  25. int SCREEN_ROWS = 23; /* height - 1 */
  26. #endif
  27.  
  28.  
  29. int Term_Cannot_Insert = 0;
  30. /* 1 if terminal lacks the ability to do into insert mode or into delete
  31.    mode. Currently controlled by S-Lang but later perhaps termcap. */
  32. int Term_Cannot_Scroll = 0;
  33.  
  34. char *INS_MODE_STR; /* = "\033[4h"; */   /* ins mode (im) */
  35. char *EINS_MODE_STR; /* = "\033[4l"; */  /* end ins mode (ei) */
  36. char *SCROLL_R_STR; /* = "\033[%d;%dr"; */ /* scroll region */
  37. char *CLS_STR; /* = "\033[2J\033[H"; */  /* cl termcap STR  for ansi terminals */
  38. char *DEL_EOL_STR; /* = "\033[K"; */           /* ce */
  39. char *DEL_CHAR_STR; /* = "\033[P"; */   /* dc */
  40. char *DEL_N_LINES_STR; /* = "\033[%dM"; */  /* DL */
  41. char *ADD_N_LINES_STR; /* = "\033[%dL"; */  /* AL */
  42. char *REV_SCROLL_STR;
  43.  
  44. char *TT_BOLD_STR; /* = "\033[1m"; */          /* md */
  45. char *TT_NORM_STR; /* = "\033[0m"; */          /* me */
  46. char *TT_ULIN_STR; /* = "\033[4m"; */          /* us */
  47. char *TT_REVV_STR; /* = "\033[7m"; */          /* mr */
  48. char *CURS_F_STR; /* = "\033[%dC"; */    /* RI termcap string */
  49.  
  50. static int LEN_CURS_F_STR = 5;
  51.  
  52. /* cm string has %i%d since termcap numbers columns from 0 */
  53. /* char *CURS_POS_STR = "\033[%d;%df";  ansi-- hor and vert pos */
  54. char *CURS_POS_STR; /* = "\033[%i%d;%dH";*/   /* cm termcap string */
  55.  
  56. int  Output_Rate = 0;          /* number of chars to output in 1 second */
  57.  
  58. /* scrolling region */
  59. static int Scroll_r1 = 0, Scroll_r2 = 23;
  60. static int Cursor_r;
  61.  
  62. static void tt_write(char *str, int n)
  63. {
  64. /*   static unsigned long last_time;
  65.    static int total;
  66.    unsigned long now;
  67.   */
  68.    if (str == NULL) return;
  69. /*   total += n; */
  70.    write(fileno(stdout), str, n);
  71. /*   if ((Output_Rate > 20) && (total > Output_Rate))
  72.      {
  73.         total = 0;
  74.         if ((now = sys_time()) - last_time <= 1)
  75.           {
  76.              sleep((unsigned) 1);
  77.           }
  78.         last_time = now;
  79.      }
  80.      */
  81. }
  82.  
  83.  
  84. void send_string_to_term(char *str)
  85. {
  86.    if (str == NULL) return;
  87.    tt_write(str, strlen(str));
  88. }
  89.  
  90.  
  91. void tt_putchar(char ch)
  92. {
  93. #if !defined(VMS) && !HAS_TERMIOS
  94.      write(fileno(stdout), &ch, 1);
  95.     if (ch == '\n') ch = '\r';
  96.     else return;
  97. #endif
  98.    write(fileno(stdout), &ch, 1);
  99. }
  100.  
  101. /* this is supposed to be fast--- also handles
  102.    termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
  103. int tt_sprintf(char *buf, char *fmt, int x, int y)
  104. {
  105.    register unsigned char *f = (unsigned char *) fmt, *b, ch;
  106.    int offset = 0, tinfo = 0;
  107.    int stack[10];
  108.    int i = 0, z;
  109.    stack[0] = y; stack[1] = x; i = 2;
  110.  
  111.    b = (unsigned char *) buf;
  112.    if (fmt != NULL) while ((ch = *f++) != 0)
  113.      {
  114.         if (ch != '%') *b++ = ch;
  115.         else
  116.           {
  117.              ch = *f++;
  118.              if (ch == 'p')
  119.                {
  120.                   tinfo = 1;
  121.                   ch = *f++;
  122.                   if (ch == '1') stack[i++] = x; else stack[i++] = y;
  123.                }
  124.              else if (ch == '\'')   /* 'x' */
  125.                {
  126.                   stack[i++] = *f++;
  127.                   f++;
  128.                }
  129.              else if ((ch == 'd') || (ch == 2) || (ch == 3))
  130.                {
  131.                   z = stack[--i];
  132.                   z += offset;
  133.                   if (z >= 100)
  134.                     {
  135.                        *b++ = z / 100 + '0';
  136.                        z = z % 100;
  137.                        goto ten;
  138.                     }
  139.                   else if (ch == 3)
  140.                     {
  141.                        *b++ = '0';
  142.                        ch = '2';
  143.                     }
  144.  
  145.                   if (z >= 10)
  146.                     {
  147.                        ten:
  148.                        *b++ = z / 10 + '0';
  149.                        z = z % 10;
  150.                     }
  151.                   else if (ch == 2) *b++ = '0';
  152.  
  153.                   *b++ = z + '0';
  154.                }
  155.              else if (ch == 'i')
  156.                {
  157.                   offset = 1;
  158.                }
  159.              else if (ch == '+')
  160.                {
  161.                   if (tinfo)
  162.                     {
  163.                        z = stack[--i];
  164.                        stack[i-1] += z;
  165.                     }
  166.                   else
  167.                     {
  168.                        ch = *f++;
  169.                        if ((unsigned char) ch == 128) ch = 0;
  170.                        ch = ch + (unsigned char) stack[--i];
  171.                        if (ch == '\n') ch++;
  172.                        *b++ = ch;
  173.                     }
  174.                }
  175.              else if (ch == 'r')
  176.                {
  177.                   stack[0] = x;
  178.                   stack[1] = y;
  179.                }
  180.              else if ((ch == '.') || (ch == 'c'))
  181.                {
  182.                   ch = (unsigned char) stack[--i];
  183.                   if (ch == '\n') ch++;
  184.                   *b++ = ch;
  185.                }
  186.              else *b++ = ch;
  187.           }
  188.      }
  189.    *b = 0;
  190.    return((int) (b - (unsigned char *) buf));
  191. }
  192.  
  193. void tt_printf(char *fmt, int x, int y)
  194. {
  195.    char buf[256];
  196.    int n;
  197.    n = tt_sprintf(buf, fmt, x, y);
  198.    tt_write(buf, n);
  199. }
  200.  
  201. void curs_bol()
  202. {
  203.    tt_putchar('\r');
  204. }
  205.  
  206. void set_scroll_region(int r1, int r2)
  207. {
  208.    Scroll_r1 = r1 - 1;
  209.    Scroll_r2 = r2 - 1;
  210.    tt_printf(SCROLL_R_STR,Scroll_r1, Scroll_r2);
  211. }
  212.  
  213. void reset_scroll_region()
  214. {
  215.     set_scroll_region(1, SCREEN_HEIGHT);
  216. }
  217.  
  218. /* the goto_rc function moves to row relative to scrolling region */
  219. void goto_rc(int r, int c)
  220. {
  221.    Cursor_r = r - 1 + Scroll_r1;
  222.    tt_printf(CURS_POS_STR, Cursor_r,c - 1);
  223. }
  224.  
  225. void begin_insert()
  226. {
  227.     send_string_to_term(INS_MODE_STR);
  228. }
  229.  
  230. void end_insert()
  231. {
  232.     send_string_to_term(EINS_MODE_STR);
  233. }
  234.  
  235. void tt_delete_char()
  236. {
  237.     send_string_to_term(DEL_CHAR_STR);
  238. }
  239.  
  240. void tt_erase_line()
  241. {
  242.    curs_bol();
  243.    send_string_to_term(DEL_EOL_STR);
  244. }
  245.  
  246. void tt_delete_nlines(int n)
  247. {
  248.    int r1, curs;
  249.    if (!n) return;
  250.    if (DEL_N_LINES_STR != NULL) tt_printf(DEL_N_LINES_STR,n, 0);
  251.    else
  252.    /* get a new terminal */
  253.      {
  254.         r1 = Scroll_r1 + 1;
  255.         curs = Cursor_r + 1;
  256.         set_scroll_region(curs, Scroll_r2 + 1);
  257.         goto_rc(Scroll_r2 - Scroll_r1 + 1, 1);
  258.         while (n--) tt_putchar('\n');
  259.         set_scroll_region(r1, Scroll_r2 + 1);
  260.         goto_rc(curs, 1);
  261.      }
  262. }
  263.  
  264. void cls()
  265. {
  266.     send_string_to_term(CLS_STR);
  267. }
  268.  
  269.  
  270.  
  271. void reverse_index(int n)
  272. {
  273.    if (!n) return;
  274.  
  275.    if (ADD_N_LINES_STR != NULL) tt_printf(ADD_N_LINES_STR,n, 0);
  276.    else
  277.      {
  278.         while(n--) send_string_to_term(REV_SCROLL_STR);
  279.      }
  280. }
  281.  
  282. void beep()
  283. {
  284.    tt_putchar('\007');
  285. }
  286.  
  287. void tt_del_eol()
  288. {
  289.     send_string_to_term(DEL_EOL_STR);
  290. }
  291. void tt_reverse_video()
  292. {
  293.     send_string_to_term(TT_REVV_STR);
  294. }
  295.  
  296. void tt_normal_video()
  297. {
  298.     send_string_to_term(TT_NORM_STR);
  299. }
  300.  
  301. void narrow_width()
  302. {
  303.     send_string_to_term("\033[?3l");
  304. }
  305.  
  306. void wide_width()
  307. {
  308.     send_string_to_term("\033[?3h");
  309. }
  310.  
  311. void smart_puts(char *neww,char *oldd, int row, int spc)
  312. {
  313.    char out[250], curs[20], *mark;
  314.    register char *p, ch, ch1;
  315.    register char *neew = neww, *old = oldd;
  316.    int ii,max_len,i, curs_set = 0, curs_len = 0;
  317.    char *new_save;
  318.  
  319.  
  320.     i = 0;
  321.     ii = 0;
  322.     *curs = 0;
  323.     max_len = LEN_CURS_F_STR;
  324.  
  325.  
  326.    /* many times we are scrolling and line to compare is blank.  Treat this
  327.     case special */
  328.    if (spc == 0)
  329.      {
  330.         p = neew;
  331.         while(*p == ' ') p++;
  332.  
  333.         if (*p == 0) return;
  334.         goto_rc(row, p - neew + 1);
  335.         old = out;
  336.         ch1 = ' ';
  337.         while (1)
  338.           {
  339.              while (ch = *p++, (ch1 != ch) && ch) *old++ = ch;
  340.              mark = old;
  341.              if (!ch) break;
  342.              *old++ = ch1;
  343.              while(ch = *p++, (ch == ch1) && ch) *old++ = ch;
  344.              if (old - mark > max_len)
  345.                {
  346.                   *mark = 0;
  347.                   send_string_to_term(out);
  348.                   if (ch == 0) return;
  349.                   if (mark != out) goto_rc(row, p - neew);
  350.                   old = out;
  351.                }
  352.              if (!ch) break;
  353.              p--;
  354.           }
  355.         *old = 0;
  356.         send_string_to_term(out);
  357.         return;
  358.      }
  359.  
  360.  
  361.     /* while they match, go on */
  362.    /* Note that neew - new_save is then column of character */
  363.    new_save = neew + 1;
  364.    while (((ch = *neew++) == *old++) && ch);
  365.    i += neew - new_save;
  366.  
  367.    if (!ch)
  368.     /* we are at the end of the new, so delete eond of old line */
  369.       {
  370.          if ((ch1 = *(old - 1)) == ' ')
  371.            {
  372.               while (*old++ == ch1);
  373.               ch1 = *(old - 1);
  374.            }
  375.  
  376.          if (ch1 == 0) return;
  377.  
  378.          goto_rc(row, i + 1);
  379.          tt_del_eol();
  380.          return;
  381.       }
  382.  
  383.  
  384.     if (i)
  385.       {
  386.          curs_len = tt_sprintf(curs, CURS_POS_STR, row - 1, i);
  387.          curs_set = 1;
  388.       }
  389.  
  390.     while(1)
  391.       {
  392.          ch1 = 0;
  393.          p = out;
  394.          *p++ = ch;
  395.          while (ch1 = *old++, ch = *neew++, (ch != ch1) && ch) *p++ = ch;
  396.          mark = p;
  397.          *p++ = ch;
  398.          if (ch) while (ch = *neew++, ch1 = *old++, (ch == ch1) && ch)
  399.            {
  400.               *p++ = ch;
  401.            }
  402.          *p = 0;
  403.          i = p - mark;
  404.          if (i > max_len)
  405.            {
  406.               *mark = 0;
  407.               if (*curs)
  408.                 {
  409.                    tt_write(curs, curs_len);
  410.                    *curs = 0;
  411.                 }
  412.  
  413.               if (!curs_set)
  414.                 {
  415.                    goto_rc(row, 1);
  416.                    curs_set = 1;
  417.                 }
  418.  
  419.               send_string_to_term(out);
  420.               if (!ch)
  421.                 {
  422.                    if (ch1)
  423.                      {
  424.                         old--;  ch = ' ';
  425.                         while (ch1 = *old++, (ch1 == ch));
  426.                      }
  427.  
  428.                    if (ch1 == 0) return;
  429.                    if (curs_set && (CURS_F_STR != NULL)) tt_printf(CURS_F_STR, i, 0);
  430.                    else
  431.                      {
  432.                         tt_printf(CURS_POS_STR, row - 1, neew - new_save);
  433.                         curs_set = 1;
  434.                      }
  435.  
  436.                    tt_del_eol();
  437.                    return;
  438.                 }
  439.  
  440.               if (i)
  441.                 {
  442.                    if (curs_set && (CURS_F_STR != NULL)) curs_len = tt_sprintf(curs, CURS_F_STR, i, 0);
  443.                    else
  444.                      {
  445.                         curs_len = tt_sprintf(curs, CURS_POS_STR, row - 1, neew - new_save);
  446.                         curs_set = 1;
  447.                      }
  448.                 }
  449.            }
  450.          else
  451.            {
  452.               if (*curs)
  453.                 {
  454.                    tt_write(curs, curs_len);
  455.                    *curs = 0;
  456.                 }
  457.               if (!curs_set)
  458.                 {
  459.                    goto_rc(row, 1);
  460.                    curs_set = 1;
  461.                 }
  462.               send_string_to_term(out);
  463.               if (!ch)
  464.                 {
  465.                    if (ch1 == ' ')
  466.                      {
  467.                         while (*old++ == ch1);
  468.                         ch1 = *(old - 1);
  469.                      }
  470.  
  471.                    if (ch1) tt_del_eol();
  472.                    return;
  473.                 }
  474.            }
  475.       }
  476. }
  477.  
  478. /* termcap stuff */
  479. static int vt100_like = 0;
  480.  
  481. #ifdef unix
  482. extern char *tgetstr(char *, char **);
  483. extern int tgetent(char *, char *);
  484. extern int tgetnum(char *);
  485. static char tbuf[1024];
  486. static char *Null_String = "";
  487.  
  488. static char *my_tgetstr(char *what, char **p)
  489. {
  490.    register char *w, *w1;
  491.    char *wsave;
  492.    what = tgetstr(what, p);
  493.    if (what != NULL)
  494.      {
  495.         /* lose pad info --- with today's technology, term is a loser if
  496.            it is really needed */
  497.         while ((*what == '.') ||
  498.                ((*what >= '0') && (*what <= '9'))) what++;
  499.         if (*what == '*') what++;
  500.  
  501.         /* lose terminfo padding--- looks like $<...> */
  502.         w = what;
  503.         while (*w) if ((*w++ == '$') && (*w == '<'))
  504.           {
  505.              w1 = w - 1;
  506.              while (*w && (*w != '>')) w++;
  507.              if (*w == 0) break;
  508.              w++;
  509.              wsave = w1;
  510.              while ((*w1++ = *w++) != 0);
  511.              w = wsave;
  512.           }
  513.         if (*what == 0) what = NULL;
  514.      }
  515.    return(what);
  516. }
  517. extern char *getenv();
  518.  
  519. static char tstr_buf[512];
  520. void get_terminfo()
  521. {
  522.    char *t, *term, ch;
  523.    char *p = tstr_buf;
  524.  
  525. #ifdef TIOCSTI
  526.     (void) signal(SIGWINCH,resize_display);
  527. #endif
  528.  
  529.  
  530.    if (NULL == (term = getenv("TERM")))
  531.      {
  532.         exit_error("TERM environment variable needs set.");
  533.      }
  534.    if (1 != tgetent(tbuf, term)) exit_error("Unknown terminal.");
  535.  
  536.    if ((SCREEN_WIDTH = tgetnum("co")) <= 0) SCREEN_WIDTH = 80;
  537. #ifdef __EMX__
  538.    if ((SCREEN_HEIGHT = tgetnum("li")) <= 0) SCREEN_HEIGHT = 25;
  539. #else
  540.    if ((SCREEN_HEIGHT = tgetnum("li")) <= 0) SCREEN_HEIGHT = 24;
  541. #endif
  542.    SCREEN_ROWS = SCREEN_HEIGHT - 1;
  543.  
  544.    t = term;
  545.    if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
  546.        && (ch = *t, (ch >= '1') && (ch <= '9')))
  547.      {
  548.         vt100_like = 1;
  549.         /* make up for DEC'S braindead termcaps (probably most other unix too) */
  550.         if ((ch >= 2) || !strcmp(t, "102"))
  551.           {
  552.              set_term_vtxxx(0);
  553.              return;
  554.           }
  555.      }
  556.  
  557.  
  558.    if ((NULL == (CLS_STR = my_tgetstr("cl", &p)))
  559.        || (NULL == (CURS_POS_STR = my_tgetstr("cm", &p))))
  560.      {
  561.         exit_error("Terminal not powerful enough for MOST.");
  562.      }
  563.  
  564.    if ((NULL == (INS_MODE_STR = my_tgetstr("im", &p)))
  565.        || ( NULL == (EINS_MODE_STR = my_tgetstr("ei", &p)))
  566.        || ( NULL == (DEL_CHAR_STR = my_tgetstr("dc", &p))))
  567.      Term_Cannot_Insert = 1;
  568.  
  569.    REV_SCROLL_STR = my_tgetstr("sr", &p);
  570.    DEL_N_LINES_STR = my_tgetstr("DL", &p);
  571.    ADD_N_LINES_STR = my_tgetstr("AL", &p);
  572.    SCROLL_R_STR = my_tgetstr("cs", &p);
  573.  
  574.    if ((SCROLL_R_STR == NULL)
  575.        || (((NULL == DEL_N_LINES_STR) || (NULL == ADD_N_LINES_STR))
  576.            && (NULL == REV_SCROLL_STR)))
  577.      Term_Cannot_Scroll = 1;
  578.  
  579. #ifdef __linux__
  580.    if (!strcmp(term, "console")) Term_Cannot_Scroll = 1;
  581. #endif
  582.  
  583.  
  584.    DEL_EOL_STR = my_tgetstr("ce", &p);
  585.  
  586.    /* so, se */
  587.    if (NULL == (TT_REVV_STR = my_tgetstr("mr", &p))) TT_REVV_STR = Null_String;
  588.    if (NULL == (TT_BOLD_STR = my_tgetstr("md", &p))) TT_BOLD_STR = Null_String;
  589.    if (NULL == (TT_NORM_STR = my_tgetstr("me", &p))) TT_NORM_STR = Null_String;
  590.    if (NULL == (TT_ULIN_STR = my_tgetstr("us", &p))) TT_ULIN_STR = Null_String;
  591.  
  592.    if (NULL != (CURS_F_STR = my_tgetstr("RI", &p)))
  593.      {
  594.         LEN_CURS_F_STR = strlen(CURS_F_STR);
  595.      }
  596.    else LEN_CURS_F_STR = strlen(CURS_POS_STR);
  597.  
  598.    get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
  599.    SCREEN_ROWS = SCREEN_HEIGHT - 1;
  600. }
  601.  
  602. #endif
  603.  
  604. /* specific to vtxxx only */
  605. void enable_cursor_keys()
  606. {
  607.    if (vt100_like) send_string_to_term("\033=\033[?1l");
  608. }
  609.  
  610. /* This sets term for vt102 terminals it parameter vt100 is 0.  If vt100
  611.   is non-zero, set terminal appropriate for a only vt100
  612.   (no add line capability). */
  613.  
  614. void set_term_vtxxx(int is_vt100)
  615. {
  616.    vt100_like = 1;
  617.    SCROLL_R_STR = "\033[%i%d;%dr";
  618.    CLS_STR = "\033[2J\033[H";
  619.    TT_REVV_STR = "\033[7m";
  620.    TT_NORM_STR = "\033[m";
  621.    TT_BOLD_STR = "\033[1m";
  622.    TT_ULIN_STR = "\033[4m";
  623.    DEL_EOL_STR = "\033[K";
  624.    REV_SCROLL_STR = "\033M";
  625.    CURS_F_STR = "\033[%dC";
  626.    CURS_POS_STR = "\033[%i%d;%dH";
  627.  
  628.    if (!is_vt100)
  629.      {
  630.         DEL_N_LINES_STR = "\033[%dM";
  631.         INS_MODE_STR = "\033[4h";
  632.         EINS_MODE_STR = "\033[4l";
  633.         DEL_CHAR_STR =  "\033[P";
  634.         ADD_N_LINES_STR = "\033[%dL";
  635.      }
  636.    else
  637.      {
  638.         DEL_N_LINES_STR = NULL;
  639.         INS_MODE_STR = NULL;
  640.         EINS_MODE_STR = NULL;
  641.         DEL_CHAR_STR = NULL;
  642.         ADD_N_LINES_STR = NULL;
  643.      }
  644.    get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
  645.    SCREEN_ROWS = SCREEN_HEIGHT - 1;
  646.    Term_Cannot_Insert = 0;
  647.    enable_cursor_keys();
  648. }
  649.  
  650. #ifndef VMS
  651. /*  This routine may be problematic when there are more windows than
  652.     the new screen size can support.  Until I think of what to do,
  653.     I  have not touched this routine. */
  654. #ifdef TIOCSTI
  655.  
  656. void resize_display()
  657. {
  658.     char c;
  659.  
  660.     get_term_dimensions(&SCREEN_WIDTH, &SCREEN_HEIGHT);
  661.     SCREEN_ROWS = SCREEN_HEIGHT - 1;
  662.  
  663.     c = 'R';   /* force a redraw of screen */
  664.     ioctl(0,TIOCSTI,&c);
  665.  
  666. #ifdef TIOCSTI
  667.     (void) signal(SIGWINCH,resize_display);
  668. #endif
  669.  
  670. }
  671. #endif
  672. #endif
  673.  
  674.