home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / EDITORS / TDE20.ZIP / WINDOW.C < prev    next >
C/C++ Source or Header  |  1992-06-05  |  47KB  |  1,474 lines

  1. /*******************  start of original comments  ********************/
  2. /*
  3.  * Written by Douglas Thomson (1989/1990)
  4.  *
  5.  * This source code is released into the public domain.
  6.  */
  7.  
  8. /*
  9.  * Name:    dte - Doug's Text Editor program - window module
  10.  * Purpose: This file contains the code associated with opening and sizing
  11.  *           windows, and also displaying the help window.
  12.  * File:    window.c
  13.  * Author:  Douglas Thomson
  14.  * System:  this file is intended to be system-independent
  15.  * Date:    October 12, 1989
  16.  */
  17. /*********************  end of original comments   ********************/
  18.  
  19.  
  20. /*
  21.  * The window routines have been EXTENSIVELY rewritten.  Some routines were
  22.  * changed so only one logical function is carried out, eg. 'initialize_window'.
  23.  * I like the Microsoft way of resizing windows - just press the up and down
  24.  * arrows to adjust the window to desired size.  I also like pressing one key
  25.  * to change windows.  All of which are implemented.
  26.  *
  27.  * In tde, version 1.4, I added support for vertical windows.
  28.  *
  29.  * New editor name:  tde, the Thomson-Davis Editor.
  30.  * Author:           Frank Davis
  31.  * Date:             June 5, 1991, version 1.0
  32.  * Date:             July 29, 1991, version 1.1
  33.  * Date:             October 5, 1991, version 1.2
  34.  * Date:             January 20, 1992, version 1.3
  35.  * Date:             February 17, 1992, version 1.4
  36.  * Date:             April 1, 1992, version 1.5
  37.  * Date:             June 5, 1992, version 2.0
  38.  *
  39.  * This modification of Douglas Thomson's code is released into the
  40.  * public domain, Frank Davis.  You may distribute it freely.
  41.  */
  42.  
  43. #include "tdestr.h"
  44. #include "common.h"
  45. #include "define.h"
  46. #include "tdefunc.h"
  47.  
  48.  
  49. /*
  50.  * Name:    initialize_window
  51.  * Purpose: To open a new window
  52.  * Date:    June 5, 1991
  53.  * Returns: OK if window opened successfully
  54.  *          ERROR if anything went wrong
  55.  * Notes:   If this is first window then set up as normal displayed window
  56.  *          otherwise make the present window invisible and open a new
  57.  *          window in the same screen location as the old one.
  58.  */
  59. int  initialize_window( void )
  60. {
  61. int top;
  62. int bottom;
  63. int start_col;
  64. int end_col;
  65. WINDOW *wp;        /* used for scanning windows */
  66. WINDOW *window;
  67. register file_infos *fp;     /* used for scanning files */
  68. register int rc;
  69.  
  70.    rc = OK;
  71.    window = g_status.current_window;
  72.    fp = g_status.current_file;
  73.    if (window == NULL) {
  74.       /*
  75.        * special case if this is the first window on screen.
  76.        */
  77.       top = start_col = 0;
  78.       bottom  = g_display.nlines;
  79.       end_col = g_display.ncols - 1;
  80.    } else {
  81.       /*
  82.        * else put the new window in same place as current window.
  83.        * make current window invisible.  new window becomes current window.
  84.        */
  85.       top       = window->top_line - 1;
  86.       bottom    = window->bottom_line;
  87.       start_col = window->start_col;
  88.       end_col   = window->end_col;
  89.    }
  90.  
  91.    if (create_window( &wp, top, bottom, start_col, end_col, fp ) == ERROR) {
  92.       /*
  93.        * out of memory
  94.        */
  95.       error( WARNING, bottom, main4 );
  96.  
  97.       /*
  98.        * This is a real nuisance. We had room for the file and the
  99.        *  file structure, but not enough for the window as well.
  100.        * Now we must free all the memory that has already been
  101.        *  allocated.
  102.        */
  103.       if (fp->ref_count == 0) {
  104.          if (fp->prev)
  105.             fp->prev->next = fp->next;
  106.          else
  107.             g_status.file_list = fp->next;
  108.          if (fp->next)
  109.             fp->next->prev = fp->prev;
  110.          g_status.end_mem = fp->start_text;
  111.          free( fp );
  112.          wp = g_status.current_window;
  113.          if (wp != NULL && wp->visible)
  114.             g_status.current_file = wp->file_info;
  115.          else
  116.             g_status.stop = TRUE;
  117.       }
  118.       rc = ERROR;
  119.    }
  120.  
  121.    if (rc != ERROR) {
  122.       /*
  123.        * set up the new cursor position as appropriate
  124.        */
  125.       wp->cursor = cpf( fp->start_text );
  126.       wp->ccol = wp->start_col;
  127.       wp->rcol = wp->bcol = 0;
  128.       wp->rline = 1l;
  129.       wp->visible = TRUE;
  130.       wp->letter = fp->next_letter++;
  131.       if (window != NULL)
  132.          window->visible = FALSE;
  133.  
  134.       /*
  135.        * the new window becomes the current window.
  136.        */
  137.       g_status.current_window = wp;
  138.    }
  139.    return( rc );
  140. }
  141.  
  142.  
  143. /*
  144.  * Name:    next_window
  145.  * Purpose: To move to the next visible window.
  146.  * Date:    June 5, 1991
  147.  * Passed:  window:  pointer to current window
  148.  * Notes:   Start with current window.  If next window exists then go to
  149.  *          it else go to the first (top) window on screen.
  150.  *          When I added vertical windows, finding the "correct" next
  151.  *          window became extremely, unnecessarily, unmanageably complicated.
  152.  *          let's just use a simple procedure to find the first available,
  153.  *          visible, next window.
  154.  */
  155. int  next_window( WINDOW *window )
  156. {
  157. register WINDOW *wp;
  158. int change;
  159.  
  160.    if (window != NULL) {
  161.       change = FALSE;
  162.       /*
  163.        * start with current window and look for first next
  164.        * visible window
  165.        */
  166.       wp = window->next;
  167.       while (wp != NULL) {
  168.          if (wp->visible) {
  169.             change = TRUE;
  170.             break;
  171.          }
  172.          wp = wp->next;
  173.       }
  174.  
  175.       /*
  176.        * if we haven't found a visible window yet, go to the beginning of
  177.        * the list until we find a visible window.
  178.        */
  179.       if (!change) {
  180.          wp = g_status.window_list;
  181.          while (wp != window) {
  182.             if (wp->visible) {
  183.                change = TRUE;
  184.                break;
  185.             }
  186.             wp = wp->next;
  187.          }
  188.       }
  189.       if (change == TRUE) {
  190.          un_copy_line( window->cursor, window, TRUE );
  191.          g_status.current_window = wp;
  192.          g_status.current_file = wp->file_info;
  193.       }
  194.    }
  195.    return( OK );
  196. }
  197.  
  198.  
  199. /*
  200.  * Name:    prev_window
  201.  * Purpose: To move to the previous visible window.
  202.  * Date:    June 5, 1991
  203.  * Passed:  window:  pointer to current window
  204.  * Notes:   Start with current window.  If previous window exists then go to
  205.  *          it else go to the last (bottom) window on screen.  Opposite of
  206.  *          next_window.
  207.  *          when I added vertical windows, finding the "correct" previous
  208.  *          window became extremely, unnecessarily, unmanageably complicated.
  209.  *          let's just use a simple procedure to find the first available,
  210.  *          visible, previous window.
  211.  */
  212. int  prev_window( WINDOW *window )
  213. {
  214. register WINDOW *wp;
  215. int change;
  216.  
  217.    if (window != NULL) {
  218.       change = FALSE;
  219.  
  220.       /*
  221.        * start with current window and look for first previous
  222.        * visible window
  223.        */
  224.       wp = window->prev;
  225.       while (wp != NULL) {
  226.          if (wp->visible) {
  227.             change = TRUE;
  228.             break;
  229.          }
  230.          wp = wp->prev;
  231.       }
  232.  
  233.       /*
  234.        * if we haven't found a visible window yet, go to the end of
  235.        * the list and work backwards until we find a visible window.
  236.        */
  237.       if (!change) {
  238.          wp = window->next;
  239.          if (wp != NULL) {
  240.             while (wp->next != NULL)
  241.                wp = wp->next;
  242.             while (wp != window) {
  243.                if (wp->visible) {
  244.                   change = TRUE;
  245.                   break;
  246.                }
  247.                wp = wp->prev;
  248.             }
  249.          }
  250.       }
  251.       if (change == TRUE) {
  252.          un_copy_line( window->cursor, window, TRUE );
  253.          g_status.current_window = wp;
  254.          g_status.current_file = wp->file_info;
  255.       }
  256.    }
  257.    return( OK );
  258. }
  259.  
  260.  
  261. /*
  262.  * Name:    split_horizontal
  263.  * Purpose: To split screen horizontally at the cursor.
  264.  * Date:    June 5, 1991
  265.  * Passed:  window:  pointer to current window
  266.  * Notes:   split the screen horizontally at the cursor position.
  267.  */
  268. int  split_horizontal( WINDOW *window )
  269. {
  270. register WINDOW *wp;
  271. register WINDOW *win;  /* register pointer for window */
  272. WINDOW *temp;
  273. file_infos *file;       /* file structure for file belonging to new window */
  274. int rc;
  275.  
  276.    win = window;
  277.    /*
  278.     * check that there is room for the window
  279.     */
  280.    if (win->bottom_line - win->cline < 2) {
  281.       /*
  282.        * move cursor up first
  283.        */
  284.       error( WARNING, win->bottom_line, win1 );
  285.       rc = ERROR;
  286.    } else {
  287.       file = win->file_info;
  288.       if (create_window( &temp, win->cline+1, win->bottom_line,
  289.                          win->start_col, win->end_col, file ) == ERROR) {
  290.          /*
  291.           * out of memory
  292.           */
  293.          error( WARNING, win->bottom_line, main4 );
  294.          rc = ERROR;
  295.       } else {
  296.          un_copy_line( win->cursor, win, TRUE );
  297.          wp = temp;
  298.          /*
  299.           * record that the current window has lost some lines from
  300.           *  the bottom for the new window, and adjust its page size
  301.           *  etc accordingly.
  302.           */
  303.          win->bottom_line = win->cline;
  304.          setup_window( win );
  305.          display_current_window( win );
  306.  
  307.          /*
  308.           * set up the new cursor position as appropriate
  309.           */
  310.          wp->rcol = win->rcol;
  311.          wp->ccol = win->ccol;
  312.          wp->bcol = win->bcol;
  313.          wp->rline = win->rline;
  314.          wp->cline = wp->cline + win->cline - (win->top_line + win->ruler);
  315.          if (wp->cline > wp->bottom_line)
  316.             wp->cline = wp->bottom_line;
  317.          wp->cursor = win->cursor;
  318.          wp->visible = TRUE;
  319.          wp->vertical = win->vertical;
  320.          wp->letter = file->next_letter++;
  321.          wp->ruler  = mode.ruler;
  322.  
  323.          /*
  324.           * the new window becomes the current window.
  325.           */
  326.          g_status.current_window = wp;
  327.  
  328.          show_window_count( g_status.window_count );
  329.          show_window_header( wp );
  330.          display_current_window( wp );
  331.          if (wp->vertical)
  332.             show_vertical_separator( wp );
  333.          make_ruler( wp );
  334.          show_ruler( wp );
  335.          rc = OK;
  336.       }
  337.    }
  338.    return( rc );
  339. }
  340.  
  341.  
  342. /*
  343.  * Name:    split_vertical
  344.  * Purpose: To split screen vertically at the cursor.
  345.  * Date:    June 5, 1991
  346.  * Passed:  window:  pointer to current window
  347.  * Notes:   split the screen vertically at the cursor position.
  348.  */
  349. int  split_vertical( WINDOW *window )
  350. {
  351. register WINDOW *wp;
  352. register WINDOW *win;  /* register pointer for window */
  353. WINDOW *temp;
  354. file_infos *file;       /* file structure for file belonging to new window */
  355. int rc;
  356.  
  357.    win = window;
  358.    /*
  359.     * check that there is room for the window
  360.     */
  361.    if (win->start_col + 15 > win->ccol) {
  362.       /*
  363.        * move cursor right first
  364.        */
  365.       error( WARNING, win->bottom_line, win2 );
  366.       rc = ERROR;
  367.    } else if (win->end_col - 15 < win->ccol) {
  368.       /*
  369.        * move cursor left first
  370.        */
  371.       error( WARNING, win->bottom_line, win3 );
  372.       rc = ERROR;
  373.    } else {
  374.       file = win->file_info;
  375.       if (create_window( &temp, win->top_line-1, win->bottom_line,
  376.                          win->ccol+1, win->end_col, file ) == ERROR) {
  377.          /*
  378.           * out of memory
  379.           */
  380.          error( WARNING, win->bottom_line, main4 );
  381.          rc = ERROR;
  382.       } else {
  383.          un_copy_line( win->cursor, win, TRUE );
  384.          wp = temp;
  385.          /*
  386.           * record that the current window has lost some columns from
  387.           *  the window to the left for the new window
  388.           */
  389.          win->ccol = win->end_col = win->ccol - 1;
  390.          win->rcol--;
  391.          win->vertical = TRUE;
  392.          show_window_header( win );
  393.          show_vertical_separator( win );
  394.          display_current_window( win );
  395.          make_ruler( win );
  396.          show_ruler( win );
  397.          show_ruler_pointer( win );
  398.  
  399.          /*
  400.           * set up the new cursor position as appropriate
  401.           */
  402.          wp->rcol = win->rcol;
  403.          wp->ccol = wp->start_col + win->ccol - win->start_col;
  404.          if (wp->ccol > wp->end_col)
  405.             wp->ccol = wp->end_col;
  406.          wp->bcol = win->bcol;
  407.          wp->rline = win->rline;
  408.          wp->cline = win->cline;
  409.          wp->cursor = win->cursor;
  410.          wp->visible = TRUE;
  411.          wp->vertical = TRUE;
  412.          wp->letter = file->next_letter++;
  413.          wp->ruler  = mode.ruler;
  414.  
  415.          /*
  416.           * the new window becomes the current window.
  417.           */
  418.          g_status.current_window = wp;
  419.  
  420.          check_virtual_col( wp, wp->rcol, wp->ccol );
  421.          wp->file_info->dirty = FALSE;
  422.          show_window_count( g_status.window_count );
  423.          show_window_header( wp );
  424.          display_current_window( wp );
  425.          make_ruler( wp );
  426.          show_ruler( wp );
  427.          rc = OK;
  428.       }
  429.    }
  430.    return( rc );
  431. }
  432.  
  433.  
  434. /*
  435.  * Name:    show_vertical_separator
  436.  * Purpose: To separate vertical screens
  437.  * Date:    June 5, 1991
  438.  * Passed:  window:  pointer to current window
  439.  */
  440. void show_vertical_separator( WINDOW *window )
  441. {
  442. int i;
  443. int line;
  444. int col;
  445.  
  446.    line = window->top_line - 1;
  447.    col  = window->end_col + 1;
  448.    if (col < g_display.ncols - 1) {
  449.       i = window->bottom_line + 1 - line;
  450.       while (i-- > 0)
  451.          c_output( VERTICAL_CHAR, col, line++, g_display.head_color );
  452.    }
  453. }
  454.  
  455.  
  456. /*
  457.  * Name:    size_window
  458.  * Purpose: To change the size of the current and one other window.
  459.  * Date:    June 5, 1991
  460.  * Passed:  window:  pointer to current window
  461.  * Notes:   Use the Up and Down arrow keys to make the current window
  462.  *          bigger or smaller.  The window above will either grow
  463.  *          or contract accordingly.
  464.  */
  465. int  size_window( WINDOW *window )
  466. {
  467. char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
  468. int func, c;
  469. register WINDOW *above;
  470. register WINDOW *win;
  471. int resize;
  472. int show_above_ruler;
  473. int old_bottom_line;
  474. int old_top_line;
  475. int new_bottom_line;
  476. int new_top_line;
  477.  
  478.    win = window;
  479.    if (win->top_line != 1 && !win->vertical) {
  480.       un_copy_line( win->cursor, win, TRUE );
  481.       save_screen_line( 0, win->bottom_line, line_buff );
  482.       /*
  483.        * press up or down to change window size
  484.        */
  485.       set_prompt( win4, win->bottom_line );
  486.  
  487.       /*
  488.        * resizing only affects current window and above visible window
  489.        */
  490.       above = g_status.window_list;
  491.       while (above->bottom_line + 2 != win->top_line || !above->visible)
  492.          above = above->next;
  493.       if (above->vertical)
  494.          /*
  495.           * cannot resize vertical window
  496.           */
  497.          error( WARNING, win->bottom_line, win5 );
  498.       else {
  499.          old_top_line = win->top_line;
  500.          old_bottom_line = above->bottom_line;
  501.          show_above_ruler = FALSE;
  502.          for (func=0; func != AbortCommand && func != Rturn; ) {
  503.  
  504.             /*
  505.              * If user has redined the ESC and Return keys, make them Rturn and
  506.              * AbortCommand in this function.
  507.              */
  508.             c = getkey( );
  509.             func = getfunc( c );
  510.             if (c == RTURN || func == NextLine || func == BegNextLine)
  511.                func = Rturn;
  512.             else if (c == ESC)
  513.                func = AbortCommand;
  514.             resize = FALSE;
  515.  
  516.             /*
  517.              * if LineUp, make current window top line grow and bottom line
  518.              * of above window shrink.   if window movement covers up current
  519.              * line of window then we must adjust logical line and real line.
  520.              */
  521.             if (func == LineUp) {
  522.                if (above->bottom_line > above->top_line + above->ruler) {
  523.                   if (win->rline == (win->cline - (win->top_line+win->ruler-1)))
  524.                      --win->cline;
  525.                   --win->top_line;
  526.                   if (above->cline == above->bottom_line)
  527.                      --above->cline;
  528.                   --above->bottom_line;
  529.                   resize = TRUE;
  530.                   if (mode.ruler) {
  531.                      if (win->ruler == FALSE) {
  532.                         if (win->cline == win->top_line)
  533.                            ++win->cline;
  534.                         if (win->cline > win->bottom_line)
  535.                            win->cline = win->bottom_line;
  536.                         win->ruler = TRUE;
  537.                      }
  538.                   }
  539.                }
  540.  
  541.             /*
  542.              * if LineDown, make current window top line shrink and bottom line
  543.              * of above window grow.   if window movement covers up current
  544.              * line of window then we must adjust logical line and real line.
  545.              */
  546.             } else if (func == LineDown) {
  547.                if (win->bottom_line > win->top_line + win->ruler) {
  548.                   if (win->cline == win->top_line + win->ruler)
  549.                      ++win->cline;
  550.                   ++win->top_line;
  551.                   ++above->bottom_line;
  552.                   resize = TRUE;
  553.                   if (mode.ruler) {
  554.                      if (above->ruler == FALSE) {
  555.                         if (above->cline == above->top_line)
  556.                            ++above->cline;
  557.                         if (above->cline > above->bottom_line)
  558.                            above->cline = above->bottom_line;
  559.                         above->ruler = TRUE;
  560.                         make_ruler( above );
  561.                         show_above_ruler = TRUE;
  562.                      }
  563.                   }
  564.                }
  565.             }
  566.  
  567.             /*
  568.              * if we resize a window then update window size and current and
  569.              * real lines if needed.
  570.              */
  571.             if (resize == TRUE) {
  572.                setup_window( above );
  573.                display_current_window( above );
  574.                if (show_above_ruler) {
  575.                   show_ruler( above );
  576.                   show_ruler_pointer( above );
  577.                   show_above_ruler = FALSE;
  578.                }
  579.                setup_window( win );
  580.                show_window_header( win );
  581.                win->ruler = mode.ruler;
  582.                make_ruler( win );
  583.                show_ruler( win );
  584.                show_ruler_pointer( win );
  585.                display_current_window( win );
  586.                save_screen_line( 0, win->bottom_line, line_buff );
  587.                /*
  588.                 * press up or down to change window size
  589.                 */
  590.                set_prompt( win4, win->bottom_line );
  591.             }
  592.          }
  593.          new_top_line = win->top_line;
  594.          new_bottom_line = above->bottom_line;
  595.          for (above=g_status.window_list; above != NULL; above=above->next) {
  596.             if (!above->visible) {
  597.                if (above->bottom_line == old_bottom_line) {
  598.                   above->bottom_line = new_bottom_line;
  599.                   if (above->cline < new_bottom_line)
  600.                      above->cline = new_bottom_line;
  601.                   setup_window( above );
  602.                } else if (above->top_line == old_top_line) {
  603.                   above->top_line = new_top_line;
  604.                   if (above->cline < new_top_line)
  605.                      above->cline = new_top_line;
  606.                   if ((long)(above->cline+1L - (above->top_line+above->ruler)) >
  607.                                                                 above->rline)
  608.                      above->cline = (int)above->rline + above->top_line +
  609.                                      above->ruler - 1;
  610.                   setup_window( above );
  611.                }
  612.             }
  613.          }
  614.       }
  615.       restore_screen_line( 0, win->bottom_line, line_buff );
  616.    } else {
  617.      if (win->vertical)
  618.         /*
  619.          * cannot resize vertical window
  620.          */
  621.         error( WARNING, win->bottom_line, win5 );
  622.      else
  623.         /*
  624.          * cannot resize top window
  625.          */
  626.         error( WARNING, win->bottom_line, win6 );
  627.    }
  628.    return( OK );
  629. }
  630.  
  631.  
  632. /*
  633.  * Name:    zoom_window
  634.  * Purpose: To blow-up current window.
  635.  * Date:    September 1, 1991
  636.  * Passed:  window:  pointer to current window
  637.  * Notes:   Make all windows, visible and hidden, full size.
  638.  */
  639. int  zoom_window( WINDOW *window )
  640. {
  641. register WINDOW *wp;
  642.  
  643.    if (window != NULL) {
  644.       un_copy_line( window->cursor, window, TRUE );
  645.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  646.          if (wp != window && wp->visible)
  647.             wp->visible = FALSE;
  648.          if (wp->top_line != 1)
  649.             wp->cline = wp->cline - (wp->top_line+wp->ruler) + 1;
  650.          wp->top_line = 1;
  651.          wp->bottom_line = g_display.nlines;
  652.          wp->end_col   = g_display.ncols - 1;
  653.          wp->start_col = 0;
  654.          wp->vertical = FALSE;
  655.          make_ruler( wp );
  656.       }
  657.       redraw_screen( window );
  658.       show_ruler( window );
  659.    }
  660.    return( OK );
  661. }
  662.  
  663.  
  664. /*
  665.  * Name:    next_hidden_window
  666.  * Purpose: To display the window that is "behind" current window.
  667.  * Date:    September 1, 1991
  668.  * Passed:  window:  pointer to current window
  669.  */
  670. int  next_hidden_window( WINDOW *window )
  671. {
  672. int poof = FALSE;
  673. register WINDOW *wp;
  674.  
  675.    if (window != NULL) {
  676.  
  677.       /*
  678.        * look for next hidden window starting with current window.
  679.        */
  680.       wp = window;
  681.       for (wp=window->next; wp != NULL && !poof; ) {
  682.          if (!wp->visible)
  683.             poof = TRUE;
  684.          else
  685.             wp = wp->next;
  686.       }
  687.  
  688.       /*
  689.        * if we haven't found an invisible window yet, start looking
  690.        * for a hidden window from the beginning of the window list.
  691.        */
  692.       if (!poof) {
  693.          for (wp=g_status.window_list; wp != NULL && !poof; ) {
  694.             if (!wp->visible)
  695.                poof = TRUE;
  696.             else
  697.                wp = wp->next;
  698.          }
  699.       }
  700.  
  701.       if (poof) {
  702.          un_copy_line( window->cursor, window, TRUE );
  703.          wp->cline = window->top_line + window->ruler +
  704.                        (wp->cline - (wp->top_line + wp->ruler));
  705.          wp->top_line = window->top_line;
  706.          wp->bottom_line = window->bottom_line;
  707.          wp->start_col = window->start_col;
  708.          wp->end_col   = window->end_col;
  709.          wp->vertical  = window->vertical;
  710.          if (wp->cline < wp->top_line + wp->ruler)
  711.             wp->cline = wp->top_line + wp->ruler;
  712.          if (wp->cline > wp->bottom_line)
  713.             wp->cline = wp->bottom_line;
  714.          if ((wp->cline+1L - (wp->top_line+wp->ruler)) > wp->rline)
  715.             wp->cline = (int)wp->rline + wp->top_line + wp->ruler - 1;
  716.          wp->visible = TRUE;
  717.          window->visible = FALSE;
  718.          g_status.current_window = wp;
  719.          redraw_current_window( wp );
  720.          make_ruler( wp );
  721.          show_ruler( wp );
  722.       }
  723.    }
  724.    return( OK );
  725. }
  726.  
  727.  
  728. /*
  729.  * Name:    setup_window
  730.  * Purpose: To set the page length and the center line of a window, based
  731.  *           on the top and bottom lines.
  732.  * Date:    June 5, 1991
  733.  * Passed:  window: window to be set up
  734.  */
  735. void setup_window( WINDOW *window )
  736. {
  737.    window->page = window->bottom_line - (window->top_line + window->ruler) -
  738.                   g_status.overlap + 1;
  739.    if (window->page < 1)
  740.       window->page = 1;
  741. }
  742.  
  743.  
  744. /*
  745.  * Name:    finish
  746.  * Purpose: To remove the current window and terminate the program if no
  747.  *           more windows are left.
  748.  * Date:    June 5, 1991
  749.  * Passed:  window:  pointer to current window
  750.  * Notes:   Order of deciding which window becomes current window:
  751.  *          1) If any invisible window with same top and bottom line,
  752.  *          and start_col and end_col, then first invisible one becomes
  753.  *          current window.
  754.  *          2) window above if it exists becomes current window
  755.  *          3) window below if it exists becomes current window
  756.  *          4) window right if it exists becomes current window
  757.  *          5) window left  if it exists becomes current window
  758.  *          6) first available invisible window becomes current window.
  759.  *          When I added vertical windows, this routine became a LOT
  760.  *          more complicated.  To keep things reasonably sane, let's
  761.  *          only close windows that have three common edges, eg.
  762.  *
  763.  *                    ┌──────┬──────────┐
  764.  *                    │      │    no    │
  765.  *                    │      ├─────┬────┤
  766.  *                    │      │yes1 │yes1│
  767.  *                    │  no  ├─────┴────┤
  768.  *                    │      │   yes2   │
  769.  *                    │      ├──────────┤
  770.  *                    │      │   yes2   │
  771.  *                    └──────┴──────────┘
  772.  *
  773.  *          Windows with 'no' cannot be closed.  Windows with 'yes' can
  774.  *          be combined with windows that have the same yes number.
  775.  */
  776. void finish( WINDOW *window )
  777. {
  778. register WINDOW *wp;   /* for scanning other windows */
  779. register WINDOW *win;  /* register pointer for window */
  780. file_infos *file, *fp;  /* for scanning other files */
  781. long number;            /* number of bytes removed / copied */
  782. int poof;
  783. int cline;
  784. int top, bottom;
  785. int start_col, end_col;
  786. int max_letter;
  787. int file_change = FALSE;
  788.  
  789.    win = window;
  790.    un_copy_line( win->cursor, win, TRUE );
  791.  
  792.    file = win->file_info;
  793.    /*
  794.     * remove all hidden windows that point to same file
  795.     */
  796.    file = win->file_info;
  797.    for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  798.       if (wp->file_info == file) {
  799.          if (!wp->visible) {
  800.             if (wp->prev == NULL) {
  801.                if (wp->next == NULL)
  802.                   g_status.stop = TRUE;
  803.                else
  804.                   g_status.window_list = wp->next;
  805.             } else
  806.                wp->prev->next = wp->next;
  807.             if (wp->next)
  808.                wp->next->prev = wp->prev;
  809.             --wp->file_info->ref_count;
  810.             free( wp );
  811.             --g_status.window_count;
  812.          }
  813.       }
  814.    }
  815.  
  816.    if (win->prev == NULL && win->next == NULL)
  817.       g_status.stop = TRUE;
  818.    poof = FALSE;
  819.  
  820.    if (g_status.stop != TRUE) {
  821.       /*
  822.        * see if there are any invisible windows with same top and bottom,
  823.        * lines, and start_col and end_col as this window.  start looking at
  824.        * end of window list.
  825.        */
  826.       top       = win->top_line;
  827.       bottom    = win->bottom_line;
  828.       start_col = win->start_col;
  829.       end_col   = win->end_col;
  830.       wp = g_status.window_list;
  831.       if (wp != NULL) {
  832.          while (wp->next != NULL)
  833.             wp = wp->next;
  834.       }
  835.       while (wp != NULL && poof == FALSE) {
  836.          if (wp->top_line == top         &&  wp->bottom_line == bottom  &&
  837.              wp->start_col == start_col  &&  wp->end_col == end_col     &&
  838.              !wp->visible)
  839.             poof = TRUE;
  840.          else
  841.             wp = wp->prev;
  842.       }
  843.  
  844.       if (poof == FALSE) {
  845.          /*
  846.           * see if there are any windows above
  847.           */
  848.          wp = g_status.window_list;
  849.          while (wp != NULL && poof == FALSE) {
  850.             if (wp->bottom_line+2 == win->top_line &&
  851.                 wp->start_col     == win->start_col &&
  852.                 wp->end_col       == win->end_col   && wp->visible) {
  853.                poof = TRUE;
  854.                top  = wp->top_line;
  855.             } else
  856.                wp = wp->next;
  857.          }
  858.          if (poof == FALSE) {
  859.             /*
  860.              * see if there are any windows below
  861.              */
  862.             wp = g_status.window_list;
  863.             while (wp != NULL && poof == FALSE) {
  864.                if (wp->top_line-2 == win->bottom_line  &&
  865.                    wp->start_col     == win->start_col &&
  866.                    wp->end_col       == win->end_col   && wp->visible) {
  867.                   poof = TRUE;
  868.                   bottom = wp->bottom_line;
  869.                } else
  870.                   wp = wp->next;
  871.             }
  872.          }
  873.          if (poof == FALSE) {
  874.             /*
  875.              * see if there are any windows right
  876.              */
  877.             wp = g_status.window_list;
  878.             while (wp != NULL && poof == FALSE) {
  879.                if (wp->top_line    == win->top_line  &&
  880.                    wp->bottom_line == win->bottom_line &&
  881.                    wp->start_col-2 == win->end_col     && wp->visible) {
  882.                   poof = TRUE;
  883.                   end_col = wp->end_col;
  884.                } else
  885.                   wp = wp->next;
  886.             }
  887.          }
  888.          if (poof == FALSE) {
  889.             /*
  890.              * see if there are any windows left
  891.              */
  892.             wp = g_status.window_list;
  893.             while (wp != NULL && poof == FALSE) {
  894.                if (wp->top_line    == win->top_line  &&
  895.                    wp->bottom_line == win->bottom_line &&
  896.                    wp->end_col+2   == win->start_col   && wp->visible) {
  897.                   poof = TRUE;
  898.                   start_col = wp->start_col;
  899.                } else
  900.                   wp = wp->next;
  901.             }
  902.          }
  903.          if (poof == FALSE) {
  904.             /*
  905.              * see if there are any other invisible windows.  start looking
  906.              * at the end of the window list.
  907.              */
  908.             wp = g_status.window_list;
  909.             if (wp != NULL) {
  910.                while (wp->next != NULL)
  911.                   wp = wp->next;
  912.             }
  913.             while (wp != NULL && poof == FALSE) {
  914.                if (!wp->visible)
  915.                   poof = TRUE;
  916.                else
  917.                   wp = wp->prev;
  918.             }
  919.          }
  920.       }
  921.       if (poof) {
  922.          wp->visible = TRUE;
  923.          cline = wp->cline - (wp->top_line+wp->ruler);
  924.          wp->top_line = top;
  925.          wp->bottom_line = bottom;
  926.          wp->cline = (wp->top_line+wp->ruler) + cline;
  927.          if (wp->cline > wp->bottom_line)
  928.             wp->cline = wp->top_line+wp->ruler;
  929.          wp->start_col = start_col;
  930.          wp->end_col   = end_col;
  931.          if (start_col == 0 && end_col == g_display.ncols - 1)
  932.             wp->vertical = FALSE;
  933.          else
  934.             wp->vertical = TRUE;
  935.          check_virtual_col( wp, wp->rcol, wp->ccol );
  936.          setup_window( wp );
  937.          show_window_header( wp );
  938.          if (wp->vertical)
  939.             show_vertical_separator( wp );
  940.  
  941.          /*
  942.           * The window above, below, or previously invisible becomes the new
  943.           * current window.
  944.           */
  945.          g_status.current_window = wp;
  946.       }
  947.    }
  948.  
  949.    if (!poof && g_status.stop != TRUE)
  950.       /*
  951.        * cannot close current window
  952.        */
  953.       error( WARNING, win->bottom_line, win7 );
  954.    else {
  955.  
  956.       /*
  957.        * free unused file memory if necessary
  958.        */
  959.       if (--file->ref_count == 0) {
  960.  
  961.          /*
  962.           * if a block is marked, unmark it
  963.           */
  964.          if (file == g_status.marked_file) {
  965.             g_status.marked      = FALSE;
  966.             g_status.marked_file = NULL;
  967.          }
  968.  
  969.          for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  970.             if (fp->file_no > file->file_no)
  971.                fp->file_no--;
  972.          }
  973.          file_change = file->file_no;
  974.  
  975.          /*
  976.           * no window now refers to this file, so remove file from the list
  977.           */
  978.          if (file->prev == NULL)
  979.             g_status.file_list = file->next;
  980.          else
  981.             file->prev->next = file->next;
  982.          if (file->next)
  983.             file->next->prev = file->prev;
  984.  
  985.          /*
  986.           * close up the gap in the memory buffer
  987.           */
  988.          number = ptoul( g_status.end_mem ) - ptoul( file->end_text );
  989.          hw_move( file->start_text, file->end_text, number );
  990.          number = ptoul( file->end_text ) - ptoul( file->start_text );
  991.          g_status.end_mem = addltop( -number, g_status.end_mem );
  992.          addorsub_all_cursors( win, -number );
  993.          adjust_start_end( file, -number );
  994.  
  995.          /*
  996.           * free the memory taken by the file structure
  997.           */
  998.          free( file );
  999.          if (--g_status.file_count) {
  1000.             show_file_count( g_status.file_count );
  1001.             show_avail_mem( );
  1002.          }
  1003.       }
  1004.  
  1005.       /*
  1006.        * remove the current window from the window list
  1007.        */
  1008.       if (win->prev == NULL) {
  1009.          if (win->next != NULL)
  1010.             g_status.window_list = win->next;
  1011.       } else
  1012.          win->prev->next = win->next;
  1013.  
  1014.       if (win->next)
  1015.          win->next->prev = win->prev;
  1016.  
  1017.       /*
  1018.        * free the memory taken by the window structure
  1019.        */
  1020.       free( win );
  1021.       --g_status.window_count;
  1022.  
  1023.       if (g_status.stop == FALSE) {
  1024.          g_status.current_file = wp->file_info;
  1025.          wp->file_info->dirty = LOCAL;
  1026.          make_ruler( wp );
  1027.          show_ruler( wp );
  1028.          show_window_count( g_status.window_count );
  1029.          if (file_change) {
  1030.             for (wp=g_status.window_list; wp!=NULL; wp=wp->next)
  1031.                if (wp->visible)
  1032.                   show_window_number_letter( wp );
  1033.          } else {
  1034.             max_letter = 'a';
  1035.             for (wp=g_status.window_list; wp!=NULL; wp=wp->next) {
  1036.                if (wp->file_info == file && wp->letter > max_letter)
  1037.                   max_letter = wp->letter;
  1038.             }
  1039.             if (max_letter < file->next_letter - 1)
  1040.                file->next_letter = max_letter + 1;
  1041.          }
  1042.       }
  1043.    }
  1044. }
  1045.  
  1046.  
  1047. /*
  1048.  * Name:    create_window
  1049.  * Purpose: To allocate space for a new window structure and set up some
  1050.  *           of the relevant fields.
  1051.  * Date:    June 5, 1991
  1052.  * Passed:  window: pointer to window pointer
  1053.  *          top:    the top line of the new window
  1054.  *          bottom: the bottom line of the new window
  1055.  *          file:   the file structure to be associated with the new window
  1056.  * Returns: OK if window could be created
  1057.  *          ERROR if out of memory
  1058.  */
  1059. int  create_window( WINDOW **window, int top, int bottom, int start_col,
  1060.                     int end_col, file_infos *file )
  1061. {
  1062. WINDOW *wp;            /* temporary variable - use it instead of **window */
  1063. register WINDOW *prev;
  1064. int rc;                 /* return code */
  1065.  
  1066.    rc = OK;
  1067.    /*
  1068.     * allocate space for new window structure
  1069.     */
  1070.    if ((*window = (WINDOW *)calloc( 1, sizeof(WINDOW) )) == NULL) {
  1071.       /*
  1072.        * out of memory
  1073.        */
  1074.       error( WARNING, g_display.nlines, main4 );
  1075.       rc = ERROR;
  1076.    } else {
  1077.  
  1078.      /*
  1079.       * set up appropriate fields
  1080.       */
  1081.       wp              = *window;
  1082.       wp->file_info   = file;
  1083.       wp->top_line    = top+1;
  1084.       wp->bottom_line = bottom;
  1085.       wp->start_col   = start_col;
  1086.       wp->end_col     = end_col;
  1087.       wp->ruler       = mode.ruler;
  1088.       make_ruler( wp );
  1089.       wp->cline       = wp->top_line + wp->ruler;
  1090.       if (start_col == 0 && end_col == g_display.ncols-1)
  1091.          wp->vertical = FALSE;
  1092.       else
  1093.          wp->vertical = TRUE;
  1094.       wp->prev        = NULL;
  1095.       wp->next        = NULL;
  1096.  
  1097.       setup_window( wp );
  1098.  
  1099.       /*
  1100.        * add window into window list
  1101.        */
  1102.       prev = g_status.current_window;
  1103.       if (prev) {
  1104.          (*window)->prev = prev;
  1105.          if (prev->next)
  1106.             prev->next->prev = *window;
  1107.          (*window)->next = prev->next;
  1108.          prev->next = *window;
  1109.       }
  1110.       if (g_status.window_list == NULL)
  1111.          g_status.window_list = *window;
  1112.  
  1113.  
  1114.       /*
  1115.        * record that another window is referencing this file
  1116.        */
  1117.       ++file->ref_count;
  1118.       file->dirty = LOCAL;
  1119.       ++g_status.window_count;
  1120.    }
  1121.    return( rc );
  1122. }
  1123.  
  1124.  
  1125. /*
  1126.  * Name:    edit_file
  1127.  * Purpose: To allocate space for a new file structure and set up some
  1128.  *           of the relevant fields.
  1129.  * Date:    June 5, 1991
  1130.  * Passed:  name:  name of the file to edit
  1131.  * Returns: OK if file structure could be created
  1132.  *          ERROR if out of memory
  1133.  */
  1134. int  edit_file( char *name )
  1135. {
  1136. int rc;           /* return code */
  1137. int existing;
  1138. int line;
  1139. register file_infos *file; /* file structure for file belonging to new window */
  1140. file_infos *fp;
  1141. text_ptr next;      /* text pointer */
  1142. long size;
  1143.  
  1144.    rc = OK;
  1145.    line = g_display.nlines;
  1146.    if (hw_fattrib( name ) == OK) {
  1147.       existing = TRUE;
  1148.       /*
  1149.        * g_status.temp_end is set last character read in file
  1150.        */
  1151.       rc = load_file( name );
  1152.    } else {
  1153.       if (ceh.flag == ERROR)
  1154.          rc = ERROR;
  1155.       else {
  1156.          existing = FALSE;
  1157.          g_status.temp_end = cpf( g_status.end_mem );
  1158.       }
  1159.    }
  1160.  
  1161.    if (rc != ERROR) {
  1162.       /*
  1163.        * allocate a file structure for the new file
  1164.        */
  1165.       file = (file_infos *)calloc( 1, sizeof(file_infos) );
  1166.       if (file == NULL) {
  1167.          /*
  1168.           * out of memory
  1169.           */
  1170.          error( WARNING, g_display.nlines, main4 );
  1171.          rc = ERROR;
  1172.       } else {
  1173.          /*
  1174.           * add file into list
  1175.           */
  1176.          file->prev = NULL;
  1177.          file->next = NULL;
  1178.          if (g_status.file_list == NULL)
  1179.             g_status.file_list = file;
  1180.          else {
  1181.             fp = g_status.current_file;
  1182.             file->prev = fp;
  1183.             if (fp->next)
  1184.                fp->next->prev = file;
  1185.             file->next = fp->next;
  1186.             fp->next = file;
  1187.          }
  1188.       }
  1189.       if (rc != ERROR) {
  1190.          /*
  1191.           * set up all the info we need to know about a file, and
  1192.           *  record that we have used some more memory.
  1193.           */
  1194.          strcpy( file->file_name, name );
  1195.          get_fattr( name, &file->file_attrib );
  1196.          file->start_text = g_status.end_mem;
  1197.          *g_status.temp_end = CONTROL_Z;
  1198.          g_status.temp_end = cpf( g_status.temp_end );
  1199.          g_status.end_mem = g_status.temp_end + 1;
  1200.          g_status.temp_end = g_status.end_mem;
  1201.          file->end_text = g_status.end_mem;
  1202.          size = 0l;
  1203.          if (existing) {
  1204.             next = file->start_text = cpf( file->start_text );
  1205.             while ((next = find_next( next )) != NULL)
  1206.                size++;
  1207.          }
  1208.          file->length      = size;
  1209.          file->block_type  = NOTMARKED;
  1210.          file->block_end   = file->block_start = NULL;
  1211.          file->block_br    = file->block_er = 0l;
  1212.          file->block_bc    = file->block_ec = 0;
  1213.          file->ref_count   = 0;
  1214.          file->modified    = FALSE;
  1215.          file->backed_up   = FALSE;
  1216.          file->new_file    = !existing;
  1217.          file->next_letter = 'a';
  1218.          file->file_no     = ++g_status.file_count;
  1219.          g_status.current_file = file;
  1220.          make_backup_fname( file );
  1221.       }
  1222.    }
  1223.    return( rc );
  1224. }
  1225.  
  1226.  
  1227. /*
  1228.  * Name:    edit_another_file
  1229.  * Purpose: Bring in another file to editor.
  1230.  * Date:    June 5, 1991
  1231.  * Passed:  window:  pointer to current window
  1232.  * Notes:   New window replaces old window.  Old window becomes invisible.
  1233.  */
  1234. int  edit_another_file( WINDOW *window )
  1235. {
  1236. char fname[MAX_COLS];            /* new name for file */
  1237. register WINDOW *win;           /* put window pointer in a register */
  1238. int rc;
  1239.  
  1240.    win = window;
  1241.    un_copy_line( win->cursor, win, TRUE );
  1242.    /*
  1243.     * read in name, no default
  1244.     */
  1245.    fname[0] = '\0';
  1246.    /*
  1247.     * file name to edit
  1248.     */
  1249.    if ((rc = get_name( ed15, win->bottom_line, fname,
  1250.                  g_display.message_color )) == OK)
  1251.       rc = attempt_edit_display( fname, LOCAL );
  1252.    return( rc );
  1253. }
  1254.  
  1255.  
  1256. /*
  1257.  * Name:    edit_next_file
  1258.  * Purpose: edit next file on command line.
  1259.  * Date:    January 6, 1992
  1260.  * Passed:  window:  pointer to current window
  1261.  * Notes:   New window replaces old window.  Old window becomes invisible.
  1262.  */
  1263. int  edit_next_file( WINDOW *window )
  1264. {
  1265. char name[MAX_COLS];            /* new name for file */
  1266. int i;
  1267. int update_type;
  1268. register int rc = ERROR;
  1269. register WINDOW *win;           /* put window pointer in a register */
  1270.  
  1271.    win = window;
  1272.    update_type = win == NULL ? GLOBAL : LOCAL;
  1273.    if (g_status.arg < g_status.argc) {
  1274.       if (win != NULL)
  1275.          un_copy_line( win->cursor, win, TRUE );
  1276.  
  1277.       /*
  1278.        * while we haven't found a valid file, search thru the command
  1279.        * line path.
  1280.        * we may have an invalid file name when we finish matching all
  1281.        * files according to a pattern.  then, we need to go to the next
  1282.        * command line argument if it exists.
  1283.        */
  1284.       while (rc == ERROR && g_status.arg < g_status.argc) {
  1285.  
  1286.          /*
  1287.           * if we haven't starting searching for a file, check to see if
  1288.           * the file is a valid file name.  if no file is found, then let's
  1289.           * see if we can find according to a search pattern.
  1290.           */
  1291.          if (g_status.found_first == FALSE) {
  1292.             strcpy( name, g_status.argv[g_status.arg] );
  1293.             rc = get_fattr( name, &i );
  1294.  
  1295.             /*
  1296.              * a new or blank file generates a return code of 2.
  1297.              * a pattern with wild cards generates a return code of 3.
  1298.              */
  1299.             if (rc == OK || rc == 2) {
  1300.                ++g_status.arg;
  1301.                rc = OK;
  1302.  
  1303.             /*
  1304.              * if we get this far, we got an invalid path name.
  1305.              *  let's try to find a matching file name using pattern.
  1306.              */
  1307.             } else if (rc != ERROR) {
  1308.                rc = findfirst( &g_status.dta, name, NORMAL | READ_ONLY |
  1309.                                HIDDEN | SYSTEM | ARCHIVE );
  1310.  
  1311.                /*
  1312.                 * if we found a file using wildcard characters,
  1313.                 * set the g_status.found_first flag to true so we can
  1314.                 * find the next matching file.  we need to save the
  1315.                 * pathname stem so we know which directory we are working in.
  1316.                 */
  1317.                if (rc == OK) {
  1318.                   g_status.found_first = TRUE;
  1319.                   i = strlen( name ) - 1;
  1320.                   while (i >= 0) {
  1321.                      if (name[i] == ':' || name[i] == '\\')
  1322.                         break;
  1323.                      --i;
  1324.                   }
  1325.                   name[++i] = '\0';
  1326.                   strcpy( g_status.path, name );
  1327.                   strcpy( name, g_status.path );
  1328.                   strcat( name, g_status.dta.name );
  1329.                } else {
  1330.                   ++g_status.arg;
  1331.                   if (win != NULL)
  1332.                      /*
  1333.                       * invalid path or file name
  1334.                       */
  1335.                      error( WARNING, win->bottom_line, win8 );
  1336.                }
  1337.             } else if (rc == ERROR)
  1338.                ++g_status.arg;
  1339.          } else {
  1340.  
  1341.             /*
  1342.              * we already found one file with wild card characters,
  1343.              * find the next matching file.
  1344.              */
  1345.             rc = findnext( &g_status.dta );
  1346.             if (rc == OK) {
  1347.                strcpy( name, g_status.path );
  1348.                strcat( name, g_status.dta.name );
  1349.             } else {
  1350.                g_status.found_first = FALSE;
  1351.                ++g_status.arg;
  1352.             }
  1353.          }
  1354.  
  1355.          /*
  1356.           * if everything is everything so far, set up the file
  1357.           * and window structures and bring the file into the editor.
  1358.           */
  1359.          if (rc == OK)
  1360.             rc = attempt_edit_display( name, update_type );
  1361.  
  1362.          /*
  1363.           * either there are no more matching files or we had an
  1364.           * invalid file name, set rc to ERROR and let's look at the
  1365.           * next file name or pattern on the command line.
  1366.           */
  1367.          else
  1368.             rc = ERROR;
  1369.       }
  1370.    }
  1371.    if (rc == ERROR  &&  g_status.arg >= g_status.argc  &&  win != NULL)
  1372.       /*
  1373.        * no more files to load
  1374.        */
  1375.       error( WARNING, win->bottom_line, win9 );
  1376.    return( rc );
  1377. }
  1378.  
  1379.  
  1380. /*
  1381.  * Name:    attempt_edit_display
  1382.  * Purpose: try to load then display a file
  1383.  * Date:    June 5, 1991
  1384.  * Passed:  fname:       file name to load
  1385.  *          update_type: update current window or entire screen
  1386.  * Notes:   When we first start the editor, we need to update the entire
  1387.  *          screen.  When we load in a new file, we only need to update
  1388.  *          the current window.
  1389.  */
  1390. int  attempt_edit_display( char *fname, int update_type )
  1391. {
  1392. register int rc;
  1393. WINDOW *win;
  1394.  
  1395.    rc = edit_file( fname );
  1396.    if (rc != ERROR) {
  1397.       rc = initialize_window( );
  1398.       if (rc != ERROR) {
  1399.          win = g_status.current_window;
  1400.          if (update_type == LOCAL) {
  1401.             redraw_current_window( win );
  1402.             show_file_count( g_status.file_count );
  1403.             show_window_count( g_status.window_count );
  1404.             show_avail_mem( );
  1405.          } else if (update_type == GLOBAL)
  1406.             redraw_screen( win );
  1407.          if (win->file_info->new_file) {
  1408.             g_status.command = AddLine;
  1409.             insert_newline( win );
  1410.             win->file_info->modified = FALSE;
  1411.          }
  1412.       }
  1413.    }
  1414.    return( rc );
  1415. }
  1416.  
  1417.  
  1418. /*
  1419.  * Name:    make_backup_fname
  1420.  * Purpose: add .bak to file name
  1421.  * Date:    January 6, 1992
  1422.  * Passed:  file: information allowing access to the current file
  1423.  */
  1424. void make_backup_fname( file_infos *file )
  1425. {
  1426. char name[MAX_COLS];            /* new name for file */
  1427. char *p;
  1428. int i;
  1429. int len;
  1430.  
  1431.    /*
  1432.     * if this is a new file then don't create a backup - can't backup
  1433.     *   a nonexisting file.
  1434.     */
  1435.    if (file->new_file)
  1436.       file->backed_up = TRUE;
  1437.  
  1438.    /*
  1439.     * find the file name extension if it exists
  1440.     */
  1441.    else {
  1442.       strcpy( name, file->file_name );
  1443.       len = strlen( name );
  1444.       for (i=len,p=name+len; i>=0; i--) {
  1445.  
  1446.          /*
  1447.           * we found the '.' extension character.  get out
  1448.           */
  1449.          if (*p == '.')
  1450.             break;
  1451.  
  1452.          /*
  1453.           * we found the drive or directory character.  no extension so
  1454.           *  set the pointer to the end of file name string.
  1455.           */
  1456.          else if (*p == '\\' || *p == ':') {
  1457.             p = name + len;
  1458.             break;
  1459.  
  1460.          /*
  1461.           * we're at the beginning of the string - no '.', drive, or directory
  1462.           *  char was found.  set the pointer to the end of file name string.
  1463.           */
  1464.          } else if (i == 0) {
  1465.             p = name + len;
  1466.             break;
  1467.          }
  1468.          --p;
  1469.       }
  1470.       strcpy( p, ".bak" );
  1471.       strcpy( file->backup_fname, name );
  1472.    }
  1473. }
  1474.