home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / xterm / part06 / screen.c < prev   
Encoding:
C/C++ Source or Header  |  1987-04-20  |  15.0 KB  |  569 lines

  1. /*
  2.  *    $Source: /u1/X/xterm/RCS/screen.c,v $
  3.  *    $Header: screen.c,v 10.100 86/12/01 14:45:17 jg Rel $
  4.  */
  5.  
  6. #include <X/mit-copyright.h>
  7.  
  8. /* Copyright    Massachusetts Institute of Technology    1984, 1985    */
  9.  
  10. /* screen.c */
  11.  
  12. #ifndef lint
  13. static char sccs_id[] = "@(#)screen.c\tX10/6.6B\t12/26/86";
  14. #endif    lint
  15.  
  16. #include <X/Xlib.h>
  17. #include <stdio.h>
  18. #include <sys/ioctl.h>
  19. #include <signal.h>
  20. #include "scrollbar.h"
  21. #include "ptyx.h"
  22. #include "error.h"
  23.  
  24. extern char *calloc();
  25. extern char *malloc();
  26. extern char *realloc();
  27.  
  28. ScrnBuf Allocate (nrow, ncol)
  29. /*
  30.    allocates memory for a 2-dimensional array of chars and returns a pointer
  31.    thereto
  32.    each line is formed from a pair of char arrays.  The first (even) one is
  33.    the actual character array and the second (odd) one is the attributes.
  34.  */
  35. register int nrow, ncol;
  36. {
  37.     register ScrnBuf base;
  38.  
  39.     if ((base = (ScrnBuf) calloc ((nrow *= 2), sizeof (char *))) == 0)
  40.         SysError (ERROR_SCALLOC);
  41.  
  42.     for (nrow--; nrow >= 0; nrow--)
  43.         if ((base [nrow] = calloc (ncol, sizeof(char))) == 0)
  44.             SysError (ERROR_SCALLOC2);
  45.  
  46.     return (base);
  47. }
  48.  
  49. ScreenWrite (screen, str, flags, length)
  50. /*
  51.    Writes str into buf at row row and column col.  Characters are set to match
  52.    flags.
  53.  */
  54. Screen *screen;
  55. char *str;
  56. register unsigned flags;
  57. register int length;        /* length of string */
  58. {
  59.     register char *att;
  60.     register int avail  = screen->max_col - screen->cur_col + 1;
  61.     register char *col;
  62.  
  63.     if (length > avail)
  64.         length = avail;
  65.     if (length <= 0)
  66.         return;
  67.  
  68.     col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col;
  69.     att = screen->buf[avail + 1] + screen->cur_col;
  70.     flags &= ATTRIBUTES;
  71.     bcopy(str, col, length);
  72.     while(length-- > 0)
  73.         *att++ = flags;
  74. }
  75.  
  76. ScrnInsertLine (sb, last, where, n, size)
  77. /*
  78.    Inserts n blank lines at sb + where, treating last as a bottom margin.
  79.    Size is the size of each entry in sb.
  80.    Requires: 0 <= where < where + n <= last
  81.             n <= MAX_ROWS
  82.  */
  83. register ScrnBuf sb;
  84. int last;
  85. register int where, n, size;
  86. {
  87.     register int i;
  88.     char *save [2 * MAX_ROWS];
  89.  
  90.     /* save n lines at bottom */
  91.     bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save,
  92.         2 * sizeof (char *) * n);
  93.     
  94.     /* clear contents of old rows */
  95.     for (i = 2 * n - 1; i >= 0; i--)
  96.         bzero ((char *) save [i], size);
  97.  
  98.     /* move down lines */
  99.     bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)],
  100.         2 * sizeof (char *) * (last - where));
  101.  
  102.     /* reuse storage for new lines at where */
  103.     bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n);
  104. }
  105.  
  106.  
  107. ScrnDeleteLine (sb, last, where, n, size)
  108. /*
  109.    Deletes n lines at sb + where, treating last as a bottom margin.
  110.    Size is the size of each entry in sb.
  111.    Requires 0 <= where < where + n < = last
  112.            n <= MAX_ROWS
  113.  */
  114. register ScrnBuf sb;
  115. register int n, last, size;
  116. int where;
  117. {
  118.     register int i;
  119.     char *save [2 * MAX_ROWS];
  120.  
  121.     /* save n lines at where */
  122.     bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n);
  123.  
  124.     /* clear contents of old rows */
  125.     for (i = 2 * n - 1 ; i >= 0 ; i--)
  126.         bzero ((char *) save [i], size);
  127.  
  128.     /* move up lines */
  129.     bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where],
  130.         2 * sizeof (char *) * ((last -= n - 1) - where));
  131.  
  132.     /* reuse storage for new bottom lines */
  133.     bcopy ((char *)save, (char *) &sb[2 * last],
  134.         2 * sizeof(char *) * n);
  135. }
  136.  
  137.  
  138. ScrnInsertChar (sb, row, col, n, size)
  139. /*
  140.    Inserts n blanks in sb at row, col.  Size is the size of each row.
  141.  */
  142. ScrnBuf sb;
  143. int row, size;
  144. register int col, n;
  145. {
  146.     register int i, j;
  147.     register char *ptr = sb [2 * row];
  148.     register char *att = sb [2 * row + 1];
  149.  
  150.     for (i = size - 1; i >= col + n; i--) {
  151.         ptr[i] = ptr[j = i - n];
  152.         att[i] = att[j];
  153.     }
  154.  
  155.     bzero (ptr + col, n);
  156.     bzero (att + col, n);
  157. }
  158.  
  159.  
  160. ScrnDeleteChar (sb, row, col, n, size)
  161. /*
  162.    Deletes n characters in sb at row, col. Size is the size of each row.
  163.  */
  164. ScrnBuf sb;
  165. register int row, size;
  166. register int n, col;
  167. {
  168.     register char *ptr = sb[2 * row];
  169.     register char *att = sb[2 * row + 1];
  170.     register nbytes = (size - n - col);
  171.  
  172.     bcopy (ptr + col + n, ptr + col, nbytes);
  173.     bcopy (att + col + n, att + col, nbytes);
  174.     bzero (ptr + size - n, n);
  175.     bzero (att + size - n, n);
  176. }
  177.  
  178.  
  179. ScrnRefresh (screen, toprow, leftcol, nrows, ncols)
  180. /*
  181.    Repaints the area enclosed by the parameters.
  182.    Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are
  183.             coordinates of characters in screen;
  184.          nrows and ncols positive.
  185.  */
  186. register Screen *screen;
  187. int toprow, leftcol, nrows, ncols;
  188. {
  189.     int y = toprow * FontHeight(screen) + screen->border + Titlebar(screen);
  190.     register int row;
  191.     register int topline = screen->topline;
  192.     int maxrow = toprow + nrows - 1;
  193.     int scrollamt = screen->scroll_amt;
  194.     int max = screen->max_row;
  195.     int dostatus = 0, left, width;
  196.     
  197.  
  198.     if(screen->statusline && maxrow == screen->max_row + 1) {
  199.         dostatus++;
  200.         maxrow--;
  201.     }
  202.     if(screen->cursor_col >= leftcol && screen->cursor_col <=
  203.      (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline &&
  204.      screen->cursor_row <= maxrow + topline)
  205.         screen->cursor_state = OFF;
  206.     for( ; ; ) {
  207.     for (row = toprow; row <= maxrow; y += FontHeight(screen), row++)
  208.     {
  209.        register char *chars;
  210.        register char *att;
  211.        register int col = leftcol;
  212.        int maxcol = leftcol + ncols - 1;
  213.        int lastind;
  214.        int flags;
  215.        int gxfunction;
  216.        Font fnt;
  217.        int x, yb, pix, n;
  218.  
  219.        lastind = row - scrollamt;
  220.        if (lastind < 0 || lastind > max)
  221.            continue;
  222.        chars = screen->buf [2 * (lastind + topline)];
  223.        att = screen->buf [2 * (lastind + topline) + 1];
  224.  
  225.        while (col <= maxcol && (att[col] & ~BOLD) == 0 &&
  226.         (chars[col] & ~040) == 0)
  227.         col++;
  228.  
  229.        while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 &&
  230.         (chars[maxcol] & ~040) == 0)
  231.         maxcol--;
  232.  
  233.        if (col > maxcol) continue;
  234.  
  235.        flags = att[col];
  236.  
  237.        fnt = ActiveIcon(screen)
  238.          ? screen->fnt_icon
  239.          : (flags & BOLD)
  240.            ? screen->fnt_bold
  241.            : screen->fnt_norm;
  242.  
  243.        x = col * FontWidth(screen) + screen->border;
  244.        lastind = col;
  245.  
  246.        for (; col <= maxcol; col++) {
  247.         if (att[col] != flags) {
  248.            if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
  249.             screen->reversestatus))
  250.                XText (VWindow(screen), x, y, &chars[lastind],
  251.                 n = col - lastind, fnt,
  252.                    pix = screen->background, screen->foreground);
  253.            else
  254.              XText (VWindow(screen), x, y, &chars[lastind],
  255.                 n = col - lastind, fnt,
  256.                    pix = screen->foreground, screen->background);
  257.            if((flags & BOLD) && screen->enbolden)
  258.              XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
  259.                 n, fnt, pix);
  260.            if(flags & UNDERLINE) {
  261.             yb = y + FontHeight(screen) - 2;
  262.             XLine(VWindow(screen), x, yb, x + n * FontWidth(screen),
  263.              yb, 1, 1, pix, GXcopy, AllPlanes);
  264.            }
  265.  
  266.            x += (col - lastind) * FontWidth(screen);
  267.  
  268.            lastind = col;
  269.  
  270.            flags = att[col];
  271.  
  272.            fnt = ActiveIcon(screen)
  273.                 ? screen->fnt_icon
  274.              : (flags & BOLD)
  275.                ? screen->fnt_bold
  276.                : screen->fnt_norm;
  277.         }
  278.  
  279.         if(chars[col] == 0)
  280.             chars[col] = ' ';
  281.        }
  282.  
  283.        if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
  284.         screen->reversestatus))
  285.            XText (VWindow(screen), x, y, &chars[lastind],
  286.          n = col - lastind, fnt, pix = screen->background,
  287.          screen->foreground);
  288.        else
  289.            XText (VWindow(screen), x, y, &chars[lastind],
  290.          n = col - lastind, fnt, pix = screen->foreground,
  291.          screen->background);
  292.        if((flags & BOLD) && screen->enbolden)
  293.         XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
  294.             n, fnt, pix);
  295.        if(flags & UNDERLINE) {
  296.         yb = y + FontHeight(screen) - 2;
  297.         XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1,
  298.          pix, GXcopy, AllPlanes);
  299.        }
  300.     }
  301.     if(dostatus <= 0)
  302.         break;
  303.     dostatus = -1;
  304.     topline = 0;
  305.     scrollamt = 0;
  306.     toprow = maxrow = max = screen->max_row + 1;
  307.     left = leftcol * FontWidth(screen) + screen->border;
  308.     width = ncols * FontWidth(screen);
  309.     if(leftcol == 0) {
  310.         left--;
  311.         width++;
  312.     }
  313.     if(leftcol + ncols - 1 >= screen->max_col)
  314.         width++;
  315.     XPixSet(VWindow(screen), left, y, width, screen->statusheight,
  316.      screen->reversestatus ? screen->foreground : screen->background);
  317.     if(!screen->reversestatus)
  318.         StatusBox(screen);
  319.     y++;
  320.     }
  321. }
  322.  
  323. ClearBufRows (screen, first, last)
  324. /*
  325.    Sets the rows first though last of the buffer of screen to spaces.
  326.    Requires first <= last; first, last are rows of screen->buf.
  327.  */
  328. register Screen *screen;
  329. register int first, last;
  330. {
  331.     first *= 2;
  332.     last = 2 * last + 1;
  333.     while (first <= last)
  334.         bzero (screen->buf [first++], (screen->max_col + 1));
  335. }
  336.  
  337. ScreenResize (screen, width, height, flags)
  338. /*
  339.    Resizes screen:
  340.    1. If new window would have fractional characters, sets window size so as to
  341.       discard fractional characters and returns -1.
  342.       Minimum screen size is 1 X 1.
  343.       Note that this causes another ExposeWindow event.
  344.    2. Enlarges screen->buf if necessary.  New space is appended to the bottom
  345.       and to the right
  346.    3. Reduces  screen->buf if necessary.  Old space is removed from the bottom
  347.       and from the right
  348.    4. Cursor is positioned as closely to its former position as possible
  349.    5. Sets screen->max_row and screen->max_col to reflect new size
  350.    6. Maintains the inner border.
  351.    7. Clears origin mode and sets scrolling region to be entire screen.
  352.    8. Returns 0
  353.  */
  354. register Screen *screen;
  355. int width, height;
  356. unsigned *flags;
  357. {
  358.     register int rows, cols;
  359.     register int index;
  360.     register int savelines;
  361.     register ScrnBuf sb = screen->allbuf;
  362.     register ScrnBuf ab = screen->altbuf;
  363.     register int x;
  364.     register int border = 2 * screen->border;
  365.     register int extra, i, j, k;
  366.     register char *sl0, *sl1;    /* keep status line */
  367.     double scale_x, scale_y;
  368. #ifdef sun
  369. #ifdef TIOCSSIZE
  370.     struct ttysize ts;
  371. #endif TIOCSSIZE
  372. #else sun
  373. #ifdef TIOCSWINSZ
  374.     struct winsize ws;
  375. #endif TIOCSWINSZ
  376. #endif sun
  377.  
  378.  
  379.     if (ActiveIcon(screen)) return( 0 );    /* don't resize on icon exposure */
  380.  
  381.     extra = Titlebar(screen) + screen->statusheight;
  382.     /* round so that it is unlikely the screen will change size on  */
  383.     /* small mouse movements.                    */
  384.     rows = (height + FontHeight(screen) / 2 - border - extra) /
  385.      FontHeight(screen);
  386.     cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) /
  387.      FontWidth(screen);
  388.     if (rows < 1) rows = 1;
  389.     if (cols < 1) cols = 1;
  390.  
  391.     if ((width - border - screen->scrollbar) % FontWidth(screen)
  392.      != 0 || (height - border - extra) % FontHeight(screen) != 0 ||
  393.      rows < screen->minrows) {
  394.         XChangeWindow (VWindow(screen),
  395.          cols * FontWidth(screen) + border + screen->scrollbar,
  396.          (rows < screen->minrows ? screen->minrows : rows) *
  397.          FontHeight(screen) + border + extra);
  398.         return (-1);
  399.     }
  400.  
  401.     /* change buffers if the screen has changed size */
  402.     if (screen->max_row != rows - 1 || screen->max_col != cols - 1) {
  403.         if(screen->cursor_state)
  404.             HideCursor();
  405.         savelines = screen->sb ? screen->savelines : 0;
  406.         j = screen->max_col + 1;
  407.         i = cols - j;
  408.         k = screen->max_row;
  409.         if(rows < k)
  410.             k = rows;
  411.         if(ab) {
  412.             /* resize current lines in alternate buf */
  413.             for (index = x = 0; index <= k; x += 2, index++) {
  414.                 if ((ab[x] = realloc(ab[x], cols)) == NULL)
  415.                     SysError(ERROR_SREALLOC);
  416.                 if((ab[x + 1] = realloc(ab[x + 1], cols)) ==
  417.                  NULL)
  418.                     SysError (ERROR_SREALLOC2);
  419.                 if (cols > j) {
  420.                     bzero (ab [x] + j, i);
  421.                     bzero (ab [x + 1] + j, i);
  422.                 }
  423.             }
  424.             /* discard excess bottom rows in alt buf */
  425.             for (index = rows, x = 2 * k ; index <=
  426.              screen->max_row; x += 2, index++) {
  427.                free (ab [x]);
  428.                free (ab [x + 1]);
  429.             }
  430.         }
  431.         /* resize current lines */
  432.         k += savelines + 1;    /* includes status line */
  433.         for (index = x = 0; index <= k; x += 2, index++) {
  434.             if ((sb[x] = realloc(sb[x], cols)) == NULL)
  435.                 SysError(ERROR_SREALLOC3);
  436.             if((sb[x + 1] = realloc(sb[x + 1], cols)) == NULL)
  437.                 SysError (ERROR_SREALLOC4);
  438.             if (cols > j) {
  439.                 bzero (sb [x] + j, i);
  440.                 bzero (sb [x + 1] + j, i);
  441.             }
  442.         }
  443.         /* discard excess bottom rows, but not status line */
  444.         for (index = rows, x = 2 * (k - 1); index <= screen->max_row;
  445.          x += 2, index++) {
  446.            free (sb [x]);
  447.            free (sb [x + 1]);
  448.         }
  449.         if(ab) {
  450.             if((ab = (ScrnBuf)realloc(ab, 2 * sizeof(char *) * rows))
  451.              == NULL)
  452.             SysError (ERROR_RESIZE);
  453.             screen->altbuf = ab;
  454.         }
  455.         /* save status line */
  456.         sl0 = sb[i = 2 * (savelines + screen->max_row + 1)];
  457.         sl1 = sb[i + 1];
  458.         k = 2 * (rows + savelines + 1);    /* includes status line */
  459.         /* resize sb */
  460.         if((sb = (ScrnBuf)realloc(sb, k * sizeof(char *))) == NULL)
  461.             SysError (ERROR_RESIZE2);
  462.         screen->allbuf = sb;
  463.         screen->buf = &sb[2 * savelines];
  464.     
  465.         if(ab) {
  466.             /* create additional bottom rows as required in alt */
  467.             for (index = screen->max_row + 1, x = 2 * index ;
  468.              index < rows; x += 2, index++) {
  469.                if((ab[x] = calloc (cols, sizeof(char))) == NULL)
  470.                 SysError(ERROR_RESIZROW);
  471.                if((ab[x + 1] = calloc (cols, sizeof(char))) == NULL)
  472.                 SysError(ERROR_RESIZROW2);
  473.             }
  474.         }
  475.         /* create additional bottom rows as required */
  476.         for (index = screen->max_row + 1, x = 2 * (index + savelines) ;
  477.          index < rows; x += 2, index++) {
  478.            if((sb[x] = calloc (cols, sizeof(char))) == NULL)
  479.             SysError(ERROR_RESIZROW3);
  480.            if((sb[x + 1] = calloc (cols, sizeof(char))) == NULL)
  481.             SysError(ERROR_RESIZROW4);
  482.         }
  483.  
  484.         /* reinstall status line */
  485.         sb[x = 2 * (rows + savelines)] = sl0;
  486.         sb[x + 1] = sl1;
  487.     
  488.         screen->max_row = rows - 1;
  489.         screen->max_col = cols - 1;
  490.     
  491.         /* adjust scrolling region */
  492.         screen->top_marg = 0;
  493.         screen->bot_marg = screen->max_row;
  494.         *flags &= ~ORIGIN;
  495.     
  496.         if (screen->instatus)
  497.             screen->cur_row = screen->max_row + 1;
  498.         else if (screen->cur_row > screen->max_row)
  499.             screen->cur_row = screen->max_row;
  500.         if (screen->cur_col > screen->max_col)
  501.             screen->cur_col = screen->max_col;
  502.     
  503.         screen->fullVwin.height = height - border - extra;
  504.         screen->fullVwin.width = width - border - screen->scrollbar;
  505.  
  506.         if (screen->active_icon)
  507.             SetIconSize( screen );
  508.  
  509.     } else if(FullHeight(screen) == height && FullWidth(screen) == width)
  510.          return(0);    /* nothing has changed at all */
  511.  
  512.     if(screen->sb)
  513.         ResizeScrollBar(screen->sb, width - SCROLLBARWIDTH,
  514.          Titlebar(screen) - 1, height - Titlebar(screen), rows);
  515.     if(screen->title.tbar && FullWidth(screen) != width)
  516.         VTTitleResize(width);
  517.     
  518.     screen->fullVwin.fullheight = height;
  519.     screen->fullVwin.fullwidth = width;
  520. #ifdef sun
  521. #ifdef TIOCSSIZE
  522.     /* Set tty's idea of window size */
  523.     ts.ts_lines = rows;
  524.     ts.ts_cols = cols;
  525.     ioctl (screen->respond, TIOCSSIZE, &ts);
  526. #ifdef SIGWINCH
  527.     if(screen->pid > 1)
  528.         killpg(getpgrp(screen->pid), SIGWINCH);
  529. #endif SIGWINCH
  530. #endif TIOCSSIZE
  531. #else sun
  532. #ifdef TIOCSWINSZ
  533.     /* Set tty's idea of window size */
  534.     ws.ws_row = rows;
  535.     ws.ws_col = cols;
  536.     ws.ws_xpixel = width;
  537.     ws.ws_ypixel = height;
  538.     ioctl (screen->respond, TIOCSWINSZ, &ws);
  539. #ifdef SIGWINCH
  540.     if(screen->pid > 1)
  541.         killpg(getpgrp(screen->pid), SIGWINCH);
  542. #endif SIGWINCH
  543. #endif TIOCSWINSZ
  544. #endif sun
  545.     return (0);
  546. }
  547.  
  548.  
  549. SetIconSize( screen )
  550.   Screen *screen;
  551. {
  552.     if (screen->active_icon) {
  553.         screen->iconVwin.width = (screen->max_col + 1)
  554.                      * screen->iconVwin.f_width
  555.                          + screen->border * 2;
  556.         screen->iconVwin.height = (screen->max_row + 1)
  557.                       * screen->iconVwin.f_height
  558.                           + screen->border * 2;
  559.         XChangeWindow( screen->iconVwin.window,
  560.                screen->iconVwin.width,
  561.                screen->iconVwin.height );
  562.     } else {
  563.         IconRecalc( screen );
  564.     }
  565.  
  566.     screen->iconVwin.fullwidth = screen->iconVwin.width;
  567.     screen->iconVwin.fullheight = screen->iconVwin.height;
  568. }
  569.