home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / most423.zip / window.c < prev    next >
C/C++ Source or Header  |  1994-01-28  |  20KB  |  896 lines

  1. #include <stdio.h>
  2.  
  3. #ifndef VMS
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <malloc.h>
  7. #endif
  8. #include <stdlib.h>
  9.  
  10. #include "externs.h"
  11. #include "window.h"
  12. #include "line.h"
  13. #include "display.h"
  14. #include "sysdep.h"
  15. #include "file.h"
  16. #include "buffer.h"
  17.  
  18. Window *WIN;
  19. Window *TOP_WIN;
  20. int COLUMN = 1;
  21. int BEEP_MINI_B = 0;
  22. int MINIBUFFER_SELECTED = 0;
  23. int CURS_ROW;
  24. int CURS_COL;
  25. int RESTORE_WIDTH_TO = 0;
  26. unsigned char *CURS_POS;
  27.  
  28. int read_string(char *str)
  29. {
  30.     char ch;
  31.     int i;
  32.  
  33.     i = strlen(str);
  34.     do 
  35.       {
  36.      ch = getkey();
  37.      if (ch == 2)               /* ^B erases line */
  38.        {
  39.           while(i)
  40.         {
  41.            ch = str[--i];
  42.            if ((ch < 32) || ((unsigned char) ch >= 127)) 
  43.              send_string_to_term("\b \b"); /* erase the ^ */
  44.            send_string_to_term("\b \b");
  45.         }
  46.        }
  47.      else if ((ch == '\b') || (ch == 127))
  48.             {
  49.                 if (i > 0)
  50.                   {
  51.              ch = str[--i];
  52.              if ((ch < 32) || ((unsigned char) ch >= 127)) 
  53.                send_string_to_term("\b \b"); /* erase the ^ */
  54.              send_string_to_term("\b \b");
  55.                   }
  56.                 else beep();
  57.             }
  58.           else if ((ch < 32) && (ch != 10) && (ch != 13))
  59.             {
  60.         if ((ch == '\007') || (ch == '\025')) /* ^G or ^U aborts */
  61.            {
  62.               beep();
  63.               return(-1);    /* ^G quits */
  64.            }
  65.         if (ch == '\033')  /* Allow KP ENTER as a terminator */
  66.            {
  67.               ch = getkey();
  68.               if (ch == 'O')
  69.              {
  70.                 ch = getkey();
  71.                 if (ch == 'M')
  72.                    {
  73.                   str[i] = '\0';
  74.                   return(i);
  75.                    }
  76.                 else
  77.                    {
  78.                   send_string_to_term("^[O");
  79.                   tt_putchar(ch);
  80.                   str[i++] = 27;
  81.                   str[i++] = 'O';
  82.                   str[i++] = ch;
  83.                    }
  84.              }
  85.               else
  86.              {
  87.                 send_string_to_term("^[");
  88.                 tt_putchar(ch);
  89.                 str[i++] = 27;
  90.                 str[i++] = ch;
  91.              }
  92.            }
  93.         else
  94.            {
  95.               str[i++] = ch;
  96.               tt_putchar('^');
  97.               tt_putchar(ch + '@');
  98.            }
  99.             }
  100.           else if (ch == '`')   /* quoted insert */
  101.             {
  102.                 ch = getkey();
  103.                 str[i++] = ch;
  104.                 if ((ch < ' ') || (ch == 127)) 
  105.                   {
  106.                       if (ch == 127) ch = '?'; else ch = ch + '@';
  107.                       tt_putchar('^');
  108.                   }
  109.                 tt_putchar(ch);
  110.             }
  111.       else if ((ch != 10) && (ch != 13))
  112.             {
  113.                 str[i++] = ch;
  114.                 tt_putchar(ch);
  115.             }
  116.           
  117.           fflush(stdout);
  118.       }
  119.     while ((ch != 10) && (ch != 13));
  120.       
  121.     str[i] = '\0';
  122.     return(i);
  123. }
  124.  
  125.  
  126. void message(char *what, int how)
  127. {
  128.     strcpy(MINI_BUF,what);
  129.     if (how) BEEP_MINI_B = 1; else BEEP_MINI_B = 0;
  130. }
  131.  
  132. void select_minibuffer()
  133. {
  134.     if (MINIBUFFER_SELECTED) return;
  135.     MINIBUFFER_SELECTED = 1;
  136.    /* set_scroll_region(1,SCREEN_HEIGHT); */
  137.     goto_rc(SCREEN_HEIGHT,1);
  138.     fflush(stdout);
  139. }
  140.  
  141. void exit_minibuffer()
  142. {
  143.     if (!MINIBUFFER_SELECTED) return;
  144.     MINIBUFFER_SELECTED = 0;
  145.    /* set_scroll_region(WIN->top,WIN->bot); */
  146.     fflush(stdout);
  147. }
  148.  
  149. /* put out string, expanding control chars */
  150. void nicely_puts(char *str)
  151. {
  152.    unsigned char ch;
  153.     while ((ch = (unsigned char) *str++) != 0)
  154.       {
  155.           if ((ch < ' ') || (ch >= 127))
  156.             {
  157.            tt_putchar('^');
  158.            if (ch != 127) ch = ch + '@'; else ch = '?';
  159.             }
  160.      tt_putchar((char) ch);
  161.       }
  162. }
  163.  
  164. void put_message()
  165. {
  166.     select_minibuffer();
  167.     tt_erase_line();
  168.     if (BEEP_MINI_B) beep();
  169.     BEEP_MINI_B = 0;
  170.     if (*MINI_BUF != '\0') nicely_puts((char *) MINI_BUF);
  171.     exit_minibuffer();
  172. }
  173.  
  174. /* puts 'what in the minibuffer to be edited. */
  175. /* returns number of chars read */
  176. int read_from_minibuffer(char *prompt, char *what)
  177. {
  178.     int i;
  179.     char str[132];
  180.     char p[132];
  181.    
  182.    if (*what)
  183.      {
  184.     sprintf(p, "%s (^B kills): ", prompt);
  185.      }
  186.    else    sprintf(p, "%s: ", prompt);
  187.    
  188.     select_minibuffer();
  189.     send_string_to_term(p);
  190.     if (*what != '\0')
  191.       nicely_puts(what);
  192.     strcpy(str,what);
  193.     i = read_string(str);
  194.     if (i > 0) strcpy(what,str);
  195.     tt_erase_line();
  196.     exit_minibuffer();
  197.     return(i);
  198. }
  199.  
  200.     
  201. void clear_minibuffer()
  202. {
  203.     MINI_BUF[0] = '\0';
  204.     BEEP_MINI_B = 0;
  205.     put_message();
  206. }
  207.  
  208.  
  209. int get_scroll(int *line)
  210. {
  211.     /* line is the line we want at the topo of the window if possible */
  212.     int dtop, dbot,n,top,bot,wsize;
  213.  
  214.     top = WIN->beg_line;
  215.     wsize = WIN->bot - WIN->top; /* actually 1 less than window size */
  216.     bot = top + wsize;
  217.  
  218.     if ((*line == 1) && (top == 1))
  219.       {
  220.           message("Top of Buffer.",1);
  221.           return(0);
  222.       }
  223.     
  224.     /* handles endof file in a window */
  225.     if ((bot > NUM_LINES) && *line > C_LINE)
  226.       {
  227.           *line = top;
  228.           message("End of Buffer.",1);
  229.           return(0);
  230.       }
  231.     
  232.     if (NUM_LINES <= wsize)     /* short file */
  233.       {
  234.           *line = 1;
  235.           return(0);
  236.       }
  237.  
  238.     dtop = top - 1;
  239.     dbot = NUM_LINES - bot;
  240.     n = *line - top;
  241.  
  242.     if ((n>0) && (dbot < n))
  243.       {
  244.           n = dbot;
  245.           *line = top + n;
  246.           if (!n) message("End of buffer.",1);
  247.       }
  248.     else if ((n < 0) && (dtop + n < 0))
  249.       {
  250.           n = -dtop;
  251.           if (!n) message("Top of buffer.",1);
  252.           *line = n + top;
  253.       }
  254.     return(n);
  255. }
  256.  
  257.  
  258. void update_window(int line)
  259. {
  260.     int n,max_n, save_line, save_col, npos;
  261.     unsigned char *save_pos;
  262.  
  263.    read_to_line(line);
  264.     if (COLUMN != WIN->col)
  265.       {
  266.           if (COLUMN < 1) COLUMN = 1;
  267.           if (COLUMN != WIN->col)
  268.             {
  269.                 save_pos = CURS_POS; save_line = CURS_ROW; save_col = CURS_COL;
  270.                 redraw_window();
  271.                 update_status(0);
  272.                 WIN->curs_pos = CURS_POS = save_pos;
  273.                 WIN->curs_line = CURS_ROW = save_line;
  274.                 WIN->curs_col = CURS_COL = save_col;
  275.             }
  276.           return;
  277.       }
  278.  
  279.     
  280.     n = get_scroll(&line);
  281.     max_n = WIN->bot - WIN->top;
  282.     if (Term_Cannot_Scroll || (abs(n) > max_n))
  283.       {
  284.           goto_line(line);
  285.           redraw_window();
  286.           update_status(0);
  287.           return;
  288.       }
  289.     if (!n) return;
  290.  
  291.     set_scroll_region(WIN->top, WIN->bot);
  292.     goto_rc(1, 1);
  293.     forward_line(n);
  294.     WIN->beg_pos = C_POS;
  295.     WIN->beg_line = C_LINE;
  296.  
  297.     if (n>0)
  298.       {
  299.           npos = 1;
  300.           tt_delete_nlines(n);
  301.      set_scroll_region(1, SCREEN_HEIGHT);
  302.      goto_rc(WIN->bot - n + 1,1); 
  303.      
  304.           forward_line(max_n - n + 1);
  305.       }
  306.     else
  307.       {
  308.           npos = 0;
  309.           CURS_ROW = 1; CURS_COL = 1; CURS_POS = C_POS;
  310.           n = -n;
  311.           reverse_index(n);
  312.      set_scroll_region(1, SCREEN_HEIGHT);
  313.      goto_rc(WIN->top, 1);
  314.       }
  315.     n = n - 1;
  316.     display_line();
  317.     while(n--)
  318.       {
  319.           forward_line(1);
  320.           tt_putchar('\n');
  321.           display_line();
  322.       }
  323.     if (npos) 
  324.       {
  325.           
  326.           CURS_ROW = C_LINE - WIN->beg_line + 1;
  327.           CURS_COL = 1; CURS_POS = C_POS;
  328.       }
  329.     
  330.     C_POS = WIN->beg_pos;
  331.     C_LINE = WIN->beg_line;
  332.    /* set_scroll_region(1, SCREEN_HEIGHT); */
  333.     update_status(0);
  334.     fflush(stdout);
  335. }
  336.  
  337. /* updates current window as well as scroll lock ones */
  338. /* Although current window is update in an absolute fashion, scroll locked
  339.    ones are updated in a relative fashion */
  340. void update_windows(int line)
  341. {
  342.     int dline,flg;
  343.     Window *w;
  344.     
  345.     dline = line - C_LINE;
  346.     update_window(line);
  347.     if (!WIN->lock) return;
  348.     flg = 0;
  349.     w = WIN;
  350.     while(WIN = WIN->next, WIN != w)
  351.       {
  352.           if (WIN->lock)
  353.             {
  354.                 flg = 1;
  355.                 set_window(WIN);
  356.                 line = C_LINE + dline;
  357.                 update_window(line);
  358.             }
  359.       }
  360.     WIN = w;
  361.     if (flg) set_window(WIN);
  362. }
  363.  
  364.  
  365. void redraw_window()
  366. {
  367.     int n,t;
  368.    
  369.    if (Term_Cannot_Scroll) t = 0; else t = WIN->top;
  370.     if (t == 1) clear_window();
  371.    
  372.     goto_rc(WIN->top, 1);
  373.     n = WIN->bot - WIN->top;
  374.     if ((C_LINE + n) > NUM_LINES) goto_line(NUM_LINES - n);
  375.     WIN->curs_pos = CURS_POS = WIN->beg_pos = C_POS;
  376.     WIN->beg_line = C_LINE;
  377.     WIN->col = COLUMN;
  378.     WIN->curs_col = CURS_COL = 1;
  379.     WIN->curs_line = CURS_ROW = 1;
  380.     if (t != 1) 
  381.      {
  382.     tt_erase_line();
  383.      }
  384.    
  385.     display_line();
  386.     while(n--)
  387.       {
  388.           tt_putchar('\n');
  389.           if (t != 1) tt_erase_line();
  390.           if (forward_line(1)) display_line();
  391.       }
  392.     
  393.         
  394.     C_POS = WIN->beg_pos;
  395.     C_LINE = WIN->beg_line;
  396. }
  397.  
  398. /* associates current window with current buffer */
  399. void save_win_flags(Window *w)
  400. {
  401.     w->flags = 0;
  402.     if (MOST_V_OPT) w->flags |= _MOST_V_OPT;
  403.     if (MOST_B_OPT) w->flags |= _MOST_B_OPT;
  404.     if (MOST_T_OPT) w->flags |= _MOST_T_OPT;
  405.     if (MOST_W_OPT) w->flags |= _MOST_W_OPT;
  406.     if (SQUEEZE_LINES) w->flags |= _MOST_SQ_OPT;
  407.     w->n_lines = NUM_LINES;
  408.     w->display = MOST_S_OPT;
  409. }
  410.  
  411. void window_buffer()
  412. {
  413.     WIN->beg_line = C_LINE;
  414.     WIN->beg_pos = C_POS;
  415.     WIN->col = COLUMN;
  416.     WIN->buf = BUF;
  417.     MOST_S_OPT = 0;
  418.     save_win_flags(WIN);
  419. }
  420.  
  421. void clear_window()
  422. {
  423.     int i,n;
  424.     i = WIN->top;
  425.     n = WIN->bot - WIN->top;
  426.    
  427.    set_scroll_region(WIN->top, WIN->bot);
  428.     if ((i == 1) && !Term_Cannot_Scroll)
  429.       {
  430.          /*  goto_rc(WIN->bot - WIN->top + 1,SCREEN_WIDTH); */
  431.      tt_delete_nlines(1 + WIN->bot - WIN->top);
  432.      /* clr_bos(); */
  433.       }
  434.     else
  435.       {
  436.           goto_rc(i - WIN->top + 1,1);
  437.           tt_erase_line();
  438.           while(n--)
  439.             {
  440.                 tt_putchar('\n');
  441.                 tt_erase_line();
  442.             }
  443.       }
  444.     
  445.     goto_rc(i - WIN->top + 1,1);
  446.    set_scroll_region(1, SCREEN_HEIGHT);
  447.     fflush(stdout);
  448. }
  449.  
  450. void restore_win_flags()
  451. {
  452.     MOST_V_OPT = WIN->flags & _MOST_V_OPT;
  453.     MOST_B_OPT = WIN->flags & _MOST_B_OPT;
  454.     MOST_T_OPT = WIN->flags & _MOST_T_OPT;
  455.     MOST_W_OPT = WIN->flags & _MOST_W_OPT;
  456.     SQUEEZE_LINES = WIN->flags & _MOST_SQ_OPT;
  457.     NUM_LINES = WIN->n_lines;
  458.     MOST_S_OPT = WIN->display;
  459. }
  460.  
  461.  
  462. Window *make_window(int r1,int r2)
  463. {
  464.     int i;
  465.     Window *new;
  466.     new = (Window *) MALLOC(sizeof(Window));
  467.     new->status = (char *) MALLOC(135);
  468.     for (i = 0; i <= SCREEN_WIDTH; i++) new->status[i] = '\0';
  469.     new->col = COLUMN;
  470.     new->top = r1;
  471.     new->bot = r2;
  472.     new->lock = 0;
  473.     save_win_flags(new);
  474.     return(new);
  475. }
  476.  
  477. void init_display()
  478. {
  479.     TOP_WIN = WIN = make_window(1,SCREEN_HEIGHT - 2);
  480.     WIN->prev = WIN->next = WIN;
  481.     cls();
  482.     set_scroll_region(1, SCREEN_HEIGHT);
  483.     goto_rc(WIN->top,1);
  484.     fflush(stdout);
  485. }
  486.  
  487. void reset_display()
  488. {
  489.     set_scroll_region(1,SCREEN_HEIGHT);
  490.     goto_rc(SCREEN_HEIGHT,1);
  491.     if (RESTORE_WIDTH_TO)
  492.       {
  493.           set_width(RESTORE_WIDTH_TO, 0);
  494.           RESTORE_WIDTH_TO = 0;
  495.       }
  496.     
  497.     fflush(stdout);
  498. }
  499.  
  500. void update_status1(int new_status)
  501. {
  502.     char str[30], ch, *strp;
  503.     static char new[135];
  504.     int i,ii,r,x,line_p = 60;
  505.    Buffer *buf = WIN->buf;
  506.    
  507.     r = WIN->bot + 1;
  508.    goto_rc(r,1); 
  509.  
  510.     i = ii = 0;
  511.     new[ii++] = '-';
  512.     if (WIN->lock) new[ii++] = '*'; else new[ii++] = '-';
  513.     strp = " MOST: ";
  514.     while(*strp != '\0') new[ii++] = *strp++;
  515.     
  516.     while(ch = buf->file[i++], ch != '\0') new[ii++] = ch;
  517.  
  518.     while(ii < line_p) new[ii++] = ' ';
  519.    x = (C_POS - BEG) * 100;
  520.    if (buf->fd == -1) 
  521.      {
  522.     if (EOB == BEG) x = 100; else x = x / (EOB - BEG);
  523.     if (C_LINE + (WIN->bot - WIN->top + 1) >= NUM_LINES) x = 100;
  524.      }
  525.    else 
  526.      {
  527.     x = x / (buf->size);
  528.      }
  529.  
  530.    /* x = (C_LINE + WIN->bot - WIN->top) * 100; x = x / NUM_LINES; */
  531.  
  532.     /* for files with end of file above the bottom row (due to window manipulations) */
  533.     if (x > 100) x = 100;
  534.    
  535.    /* stdin may not be read in yet and I do not know how big it is. */
  536.    if (buf->fd == 0) sprintf(str,"(%d,%d) ",C_LINE,COLUMN);
  537.    else
  538.    sprintf(str,"(%d,%d) %d%%",C_LINE,COLUMN,x);
  539.    
  540.     i = 0; while(ch = str[i++], ch != '\0') new[ii++] = ch;
  541.  
  542.     while(ii < SCREEN_WIDTH) new[ii++] = '-';
  543.     new[SCREEN_WIDTH] = '\0';
  544.    tt_reverse_video();
  545.     if (new_status)
  546.       send_string_to_term(new);
  547.     else
  548.       smart_puts((char *) new,(char *) WIN->status, r, 1);
  549.    tt_normal_video();
  550.     strcpy(WIN->status,new);
  551. }
  552.  
  553. void update_status(int new_status)
  554. {
  555.  
  556.     C_LINE = WIN->beg_line;
  557.     C_POS = WIN->beg_pos;
  558.    /* set_scroll_region(1,SCREEN_HEIGHT); */
  559.     update_status1(new_status);
  560.    /* set_scroll_region(WIN->top,WIN->bot); */
  561.     fflush(stdout);
  562. }
  563.  
  564. /* splits window-- no screen update, does not affect scrolling region */
  565. int split_window()
  566. {
  567.     Window *new, *old;
  568.     int b2,t2,b1, line;
  569.  
  570.     b2 = WIN->bot;
  571.     b1 = (WIN->bot + WIN->top) / 2 - 1;
  572.     t2 = b1 + 2;
  573.     if ((b1 == WIN->top) || (t2 == b2)) return(0);
  574.  
  575.     /* line is top line of new window. */
  576.     line = WIN->beg_line + t2 - WIN->top;
  577.     old = WIN;
  578.     WIN->bot = b1;
  579.     new = make_window(t2,b2);
  580.     /* add to ring */
  581.     WIN->next->prev = new;
  582.     new->next = WIN->next;
  583.     new->prev = WIN;
  584.     WIN->next = new;
  585.  
  586.     new->beg_line = line;
  587.     new->buf = BUF;
  588.     /* new window status line is at same position as old */
  589.     strcpy(new->status,WIN->status);
  590.     return(1);
  591. }
  592.  
  593.     
  594. void two_windows()
  595. {
  596.     int line;
  597.     Window *new, *old;
  598.     if (!split_window()) return;
  599.  
  600.     old = WIN;
  601.     new = WIN->next;
  602.     line = new->beg_line;
  603.     if (line + new->bot - new->top > NUM_LINES)
  604.       {
  605.           other_window(1);
  606.           /* since split window left new window undefined... */
  607.           C_POS = old->beg_pos;
  608.           C_LINE = old->beg_line;
  609.           if (NUM_LINES <= new->bot - new->top + 1)
  610.             {
  611.                 C_LINE = new->beg_line = 1;
  612.                 C_POS = new->beg_pos = BUF->beg;
  613.                 redraw_window();
  614.                 update_status(0);
  615.             }
  616.           else if (line > NUM_LINES)
  617.             {
  618.                 goto_line(NUM_LINES - new->bot + new->top);
  619.                 WIN->beg_pos = C_POS;
  620.                 WIN->beg_line = C_LINE;
  621.                 redraw_window();
  622.                 update_status(0);
  623.             }    
  624.           else
  625.             {
  626.                 goto_line(line);
  627.                 WIN->beg_pos = C_POS;
  628.                 WIN->beg_line = C_LINE;
  629.                 update_window(NUM_LINES - new->bot + new->top);
  630.             }
  631.           WIN->curs_line = 1;
  632.           WIN->curs_col = COLUMN;
  633.           WIN->curs_pos = C_POS;
  634.           other_window(-1);
  635.       }
  636.     else
  637.       {
  638.           WIN = new;
  639.           (void) forward_line(line - old->beg_line);
  640.           new->beg_pos = C_POS;
  641.           new->beg_line = C_LINE;
  642.           new->curs_line = 1;
  643.           new->curs_col = COLUMN;
  644.           new->curs_pos = C_POS;
  645.           update_status(0);
  646.           WIN = old;
  647.       }    
  648.     update_status(1);
  649. }
  650.  
  651. void expand_window1(int dn)
  652. {
  653.     int l, save_top, save_line;
  654.     unsigned char *save_pos;
  655.  
  656.     /* l is line after last line of current window (where status line is) */
  657.     l = WIN->beg_line + WIN->bot - WIN->top + 1;
  658.     save_top = WIN->top;
  659.     WIN->top = WIN->bot + 1;
  660.     WIN->bot = WIN->bot + dn;
  661.    /* set_scroll_region(WIN->top, WIN->bot); */
  662.     if (l > NUM_LINES)
  663.       {
  664.           clear_window();
  665.       }
  666.     else
  667.       {
  668.           /* should add something here for smarter scrolling...
  669.              if ((WIN->next->BUF == BUF) && (l >= WIN->next->beg_line)
  670.              && (l <= (WIN->next->beg_line + WIN->next)
  671.              */
  672.                 
  673.           save_line = C_LINE;
  674.           save_pos = C_POS;
  675.           goto_line(l);
  676.           redraw_window();
  677.           WIN->beg_line = C_LINE = save_line;
  678.           WIN->beg_pos = C_POS = save_pos;
  679.       }
  680.     WIN->top = save_top;
  681.    /* set_scroll_region(WIN->top, WIN->bot); */
  682. }
  683.  
  684. void one_window()
  685. {
  686.     Window *w, *tmp;
  687.     int diff;
  688.     
  689.     if (WIN->next == WIN) return;
  690.     w = WIN;
  691.     WIN = WIN->next;
  692.     /* delete other windows preserving the ring! */
  693.     while(WIN != w)
  694.       {
  695.           free_window_buffer(); /* needs a ring */
  696.           tmp = WIN->next;
  697.           /* if this is the bottom window, save its status line */
  698.           if (tmp == TOP_WIN) strcpy(w->status,WIN->status);
  699.           tmp->prev = WIN->prev;
  700.           WIN->prev->next = tmp;
  701.           free(WIN);
  702.           WIN = tmp;
  703.       }
  704.     WIN = w;
  705.    if (Term_Cannot_Scroll) 
  706.      {
  707.     WIN->top = 1;
  708.     WIN->bot = SCREEN_HEIGHT - 2;
  709.     redraw_window();
  710.      }
  711.    else
  712.      {
  713.     /* slide the window to the top and expand it */
  714.     diff = WIN->top - 1;
  715.     if (diff)
  716.       {
  717.          set_scroll_region(1,SCREEN_HEIGHT - 2);
  718.          goto_rc(1,1);
  719.          tt_delete_nlines(diff);
  720.          WIN->top = 1;
  721.          WIN->bot -=  diff;
  722.          TOP_WIN = WIN;
  723.       }
  724.     expand_window1(SCREEN_HEIGHT - 2 - WIN->bot);
  725.     set_scroll_region(1, SCREEN_HEIGHT);
  726.      }
  727.    
  728.     update_status(0);
  729. }
  730.  
  731.           
  732. void set_window(Window *w)
  733. {
  734.     WIN = w;
  735.     CURS_ROW = WIN->curs_line;
  736.     CURS_COL = WIN->curs_col;
  737.     CURS_POS = WIN->curs_pos;
  738.     C_LINE = WIN->beg_line;
  739.     C_POS = WIN->beg_pos;
  740.     COLUMN = WIN->col;
  741.     BUF = WIN->buf;
  742.     switch_to_buffer(BUF);
  743.    /* set_scroll_region(WIN->top,WIN->bot); */
  744.     restore_win_flags();
  745.     fflush(stdout);
  746. }
  747.  
  748. void other_window(int n)
  749. {
  750.     if (!n) return;
  751.     WIN->beg_pos = C_POS;
  752.     WIN->curs_pos = CURS_POS;
  753.     WIN->curs_line = CURS_ROW;
  754.     WIN->curs_col = CURS_COL;
  755.     WIN->beg_line = C_LINE;
  756.     save_win_flags(WIN);
  757.     if (n < 0)
  758.       while (n++) WIN = WIN->prev;
  759.     else
  760.       while (n--) WIN = WIN->next;
  761.     set_window(WIN);
  762. }
  763.  
  764.  
  765.  
  766. /* kills window by moving lower window up */
  767. void delete_as_top_window()
  768. {
  769.     int t1,t2,b1,b2;
  770.     t1 = WIN->top;
  771.     t2 = WIN->next->top;
  772.     b1 = WIN->bot;
  773.     b2 = WIN->next->bot;
  774.     WIN->prev->next = WIN->next;
  775.     WIN->next->prev = WIN->prev;
  776.  
  777.    if (Term_Cannot_Scroll)
  778.      {
  779.     other_window(1);
  780.     WIN->top = t1;
  781.     redraw_window();
  782.      }
  783.    else
  784.      {
  785.     /* scroll contents of window below to top */
  786.     set_scroll_region(t1,b2);
  787.     goto_rc(1,1);
  788.     tt_delete_nlines(t2 - t1);
  789.     other_window(1);
  790.     WIN->top = t1;
  791.     WIN->bot = b2 - t2 + t1;
  792.     expand_window1(b2 - WIN->bot);
  793.      }
  794.    
  795.     update_status(0);
  796. }
  797.  
  798. /* free buffer for this window if no other windows are viewing it. */
  799. void free_window_buffer()
  800. {
  801.    Window *w;
  802.    Buffer *b;
  803.    
  804.     w = WIN->next;
  805.    
  806.     while(WIN != w)
  807.       {
  808.      if (!strcmp(WIN->buf->file,w->buf->file)) return;
  809.      w = w->next;
  810.       }
  811.    b = w->buf;
  812.    if (b->fd != -1) close(b->fd);
  813.    free(b->beg);
  814.    free(b);
  815. }
  816.  
  817.  
  818. void delete_window()
  819. {
  820.     int new_b, old_b;
  821.     Window *w;
  822.     
  823.     w = WIN;
  824.     if (WIN->next == WIN) return;
  825.     free_window_buffer();
  826.     if (WIN->next != TOP_WIN)
  827.       {
  828.           if (WIN == TOP_WIN)
  829.             {
  830.                 delete_as_top_window();
  831.                 TOP_WIN = WIN;  /* not anymore, this one is */
  832.             }
  833.           else
  834.             delete_as_top_window();
  835.           
  836.           free(w);
  837.           return;
  838.       }
  839.     old_b = WIN->top - 2;
  840.     new_b = WIN->bot;
  841.     other_window(-1);
  842.    if (Term_Cannot_Scroll)
  843.      {
  844.     WIN->bot = new_b;
  845.     redraw_window();
  846.      }
  847.    else expand_window1(new_b - old_b);
  848.    
  849.    strcpy(WIN->status,w->status); /* share the same line */
  850.     
  851.    WIN->next = w->next;
  852.    WIN->next->prev = WIN;
  853.    free(w);
  854.    update_status(0);
  855. }
  856.  
  857. void redraw_display()
  858. {
  859.     Window *w;
  860.     int n,t;
  861.     set_scroll_region(1,SCREEN_HEIGHT);
  862.     cls();
  863.     save_win_flags(WIN);
  864.     w = WIN;
  865.     do
  866.       {
  867.           WIN = WIN->next;
  868.           t = WIN->top;
  869.           goto_rc(t, 1);
  870.           C_POS = WIN->beg_pos;
  871.           C_LINE = WIN->beg_line;
  872.           COLUMN = WIN->col;
  873.           switch_to_buffer(WIN->buf);
  874.           restore_win_flags();
  875.           n = WIN->bot - WIN->top;
  876.           display_line();
  877.           while(n--)
  878.             {
  879.                 tt_putchar('\n');
  880.                 if (forward_line(1)) display_line();
  881.             }
  882.           C_LINE = WIN->beg_line;
  883.           C_POS = WIN->beg_pos;
  884.           update_status1(1);
  885.       }
  886.     while(WIN != w);
  887.     set_window(w);
  888. }
  889.  
  890. void toggle_lock()
  891. {
  892.     WIN->lock = !(WIN->lock);
  893.     update_status(0);
  894. }
  895.  
  896.