home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / TDE120.ZIP / WINDOW.C < prev   
Encoding:
C/C++ Source or Header  |  1991-10-05  |  27.7 KB  |  909 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.  * New editor name:  tde, the Thomson-Davis Editor.
  28.  * Author:           Frank Davis
  29.  * Date:             June 5, 1991
  30.  *
  31.  * This modification of Douglas Thomson's code is released into the
  32.  * public domain, Frank Davis.  You may distribute it freely.
  33.  */
  34.  
  35. #include "tdestr.h"
  36. #include "common.h"
  37. #include "define.h"
  38. #include "tdefunc.h"
  39. #if defined( __MSC__ )
  40.    #include <sys/types.h>
  41.    #include <sys/stat.h>
  42. #endif
  43.  
  44.  
  45. /*
  46.  * Name:    initialize_window
  47.  * Purpose: To open a new window
  48.  * Date:    June 5, 1991
  49.  * Returns: OK if window opened successfully
  50.  *          ERROR if anything went wrong
  51.  * Notes:   If this is first window then set up as normal displayed window
  52.  *          otherwise make the present window invisible and open a new
  53.  *          window in the same screen location as the old one.
  54.  */
  55. int  initialize_window( void )
  56. {
  57. int top;
  58. int bottom;
  59. windows *wp;        /* used for scanning windows */
  60. windows *window;
  61. register file_infos *fp;     /* used for scanning files */
  62. int rc;
  63.  
  64.    rc = OK;
  65.    window = g_status.current_window;
  66.    fp = g_status.current_file;
  67.    if (window == NULL) {
  68.       /*
  69.        * special case if this is the first window on screen.
  70.        */
  71.       top = 0;
  72.       bottom = g_display.nlines;
  73.    } else {
  74.       /*
  75.        * else put the new window in same place as current window.
  76.        * make current window invisible.  new window becomes current window.
  77.        */
  78.       top = window->top_line - 1;
  79.       bottom = window->bottom_line;
  80.    }
  81.  
  82.    if (create_window( &wp, top, bottom, fp ) == ERROR) {
  83.       error( WARNING, bottom, "out of memory" );
  84.  
  85.       /*
  86.        * This is a real nuisance. We had room for the file and the
  87.        *  file structure, but not enough for the window as well.
  88.        * Now we must free all the memory that has already been
  89.        *  allocated.
  90.        */
  91.       if (fp->ref_count == 0) {
  92.          if (fp->prev)
  93.             fp->prev->next = fp->next;
  94.          else
  95.             g_status.file_list = fp->next;
  96.          if (fp->next)
  97.             fp->next->prev = fp->prev;
  98.          g_status.end_mem = fp->start_text;
  99.          free( fp );
  100.       }
  101.       rc = ERROR;
  102.    }
  103.  
  104.    if (rc != ERROR) {
  105.       /*
  106.        * set up the new cursor position as appropriate
  107.        */
  108.       wp->cursor = cpf( fp->start_text );
  109.       wp->ccol = 0;
  110.       wp->rcol = 0;
  111.       wp->bcol = 0;
  112.       wp->rline = 1l;
  113.       wp->visible = TRUE;
  114.       wp->letter = fp->next_window_letter;
  115.       ++fp->next_window_letter;
  116.       if (window != NULL)
  117.          window->visible = FALSE;
  118.  
  119.       /*
  120.        * the new window becomes the current window.
  121.        */
  122.       g_status.current_window = wp;
  123.    }
  124.    return( rc );
  125. }
  126.  
  127.  
  128. /*
  129.  * Name:    next_window
  130.  * Purpose: To select an existing window.
  131.  * Date:    June 5, 1991
  132.  * Passed:  window:   information allowing access to the current window
  133.  * Notes:   Start with current window.  If next window exits then go to
  134.  *          it else go to the first (top) window on screen.
  135.  */
  136. void next_window( windows *window )
  137. {
  138. int change;
  139. register windows *wp;
  140.  
  141.    if (window != NULL) {
  142.       change = FALSE;
  143.       wp = g_status.window_list;
  144.       if (wp->next != NULL) {
  145.          while (wp != NULL && (wp->top_line-2 != window->bottom_line ||
  146.                 !wp->visible))
  147.             wp = wp->next;
  148.          if (wp != NULL)
  149.             change = TRUE;
  150.       }
  151.       if (change != TRUE) {
  152.          wp = g_status.window_list;
  153.          while (wp != NULL && (wp->top_line != 1 || !wp->visible))
  154.             wp = wp->next;
  155.          if (wp != NULL && wp != window)
  156.             change = TRUE;
  157.       }
  158.       if (change == TRUE) {
  159.          un_copy_line( window->cursor, window, TRUE );
  160.          g_status.current_window = wp;
  161.          g_status.current_file = wp->file_info;
  162.       }
  163.    }
  164. }
  165.  
  166.  
  167. /*
  168.  * Name:    prev_window
  169.  * Purpose: To select an existing window.
  170.  * Date:    June 5, 1991
  171.  * Passed:  window:   information allowing access to the current window
  172.  * Notes:   Start with current window.  If previous window exits then go to
  173.  *          it else go to the last (bottom) window on screen.  Opposite of
  174.  *          next_window.
  175.  */
  176. void prev_window( windows *window )
  177. {
  178. int change;
  179. register windows *wp;
  180.  
  181.    if (window != NULL) {
  182.       change = FALSE;
  183.       wp = g_status.window_list;
  184.       if (wp->next != NULL) {
  185.          while (wp != NULL && (wp->bottom_line+2 != window->top_line ||
  186.                 !wp->visible))
  187.             wp = wp->next;
  188.          if (wp != NULL)
  189.             change = TRUE;
  190.       }
  191.       if (change != TRUE) {
  192.          wp = g_status.window_list;
  193.          while (wp != NULL && (wp->bottom_line != g_display.nlines ||
  194.                !wp->visible))
  195.             wp = wp->next;
  196.          if (wp != NULL && wp != window)
  197.             change = TRUE;
  198.       }
  199.  
  200.       if (change == TRUE) {
  201.          un_copy_line( window->cursor, window, TRUE );
  202.          g_status.current_window = wp;
  203.          g_status.current_file = wp->file_info;
  204.       }
  205.    }
  206. }
  207.  
  208.  
  209. /*
  210.  * Name:    split_screen
  211.  * Purpose: To split screen.
  212.  * Date:    June 5, 1991
  213.  * Passed:  window:   information allowing access to the current window
  214.  * Notes:   split the screen at the cursor position.
  215.  */
  216. void split_screen( windows *window )
  217. {
  218. register windows *wp;
  219. windows *temp;
  220. file_infos *file;   /* file structure for file belonging to new window */
  221. int prompt_line;
  222.  
  223.    prompt_line = window->bottom_line;
  224.    /*
  225.     * check that there is room for the window
  226.     */
  227.    if (window->bottom_line - window->cline < 2)
  228.       error( WARNING, prompt_line, "move cursor up first" );
  229.    else {
  230.       file = window->file_info;
  231.       if (create_window( &temp, window->cline+1, window->bottom_line,
  232.                          file ) == ERROR) {
  233.          error( WARNING, prompt_line, "out of memory" );
  234.       } else {
  235.          wp = temp;
  236.          /*
  237.           * record that the current window has lost some lines from
  238.           *  the bottom for the new window, and adjust its page size
  239.           *  etc accordingly.
  240.           */
  241.          window->bottom_line = window->cline;
  242.          setup_window( window );
  243.          display_current_window( window );
  244.  
  245.          /*
  246.           * set up the new cursor position as appropriate
  247.           */
  248.          wp->rcol = window->rcol;
  249.          wp->ccol = window->ccol;
  250.          wp->bcol = window->bcol;
  251.          wp->rline = window->rline;
  252.          wp->cursor = window->cursor;
  253.          wp->visible = TRUE;
  254.          wp->letter = file->next_window_letter;
  255.          ++file->next_window_letter;
  256.  
  257.          /*
  258.           * the new window becomes the current window.
  259.           */
  260.          g_status.current_window = wp;
  261.  
  262.          show_window_header( wp->file_info->file_name, wp );
  263.          show_size_name( wp );
  264.          show_size( wp );
  265.          display_current_window( wp );
  266.  
  267.          /*
  268.           *  adjust any invisible windows
  269.           */
  270.          wp = g_status.window_list;
  271.          while (wp != NULL) {
  272.             if (wp != window ) {
  273.                if (wp->top_line == window->top_line) {
  274.                   wp->bottom_line = window->bottom_line;
  275.                   setup_window( wp );
  276.                   /*
  277.                    * reset cline to some place safe
  278.                    */
  279.                   wp->cline = wp->top_line;
  280.                }
  281.             }
  282.             wp = wp->next;
  283.          }
  284.       }
  285.    }
  286. }
  287.  
  288.  
  289. /*
  290.  * Name:    size_window
  291.  * Purpose: To change the size of the current and one other window.
  292.  * Date:    June 5, 1991
  293.  * Passed:  window:   information allowing access to the current window
  294.  * Notes:   Use the Up and Down arrow keys to make the current window
  295.  *          bigger or smaller.  The window above, if it exists, will
  296.  *          either grow or contract accordingly.
  297.  */
  298. void size_window( windows *window )
  299. {
  300. char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
  301. int func, c, above_change;
  302. register windows *n;
  303. windows *above;
  304. text_ptr p;
  305. int prompt_line;
  306. int resize;
  307. char *file_name;
  308. char *instr =
  309.        "Press Up or Down to change window size.  Press Return when done.";
  310.  
  311.    if (window->top_line != 1) {
  312.       above_change = 0;
  313.       file_name = window->file_info->file_name;
  314.       prompt_line = window->bottom_line;
  315.       save_screen_line( 0, prompt_line, line_buff );
  316.       set_prompt( instr, prompt_line );
  317.  
  318.       /*
  319.        * resizing only affects current window and above visible window
  320.        */
  321.       above = g_status.window_list;
  322.       while (above->bottom_line + 2 != window->top_line || !above->visible)
  323.          above = above->next;
  324.       for (func=0; func != AbortCommand && func != Rturn; ) {
  325.  
  326.          /*
  327.           * If user has redined the ESC and Return keys, make them Rturn and
  328.           * AbortCommand in this function.
  329.           */
  330.          c = getkey( );
  331.          func = getfunc( c );
  332.          if (c == RTURN || func == NextLine || func == BegNextLine)
  333.             func = Rturn;
  334.          else if (c == ESC)
  335.             func == AbortCommand;
  336.          resize = FALSE;
  337.  
  338.          /*
  339.           * if line up make current window top line grow and bottom line
  340.           * of above window shrink.   if window movement covers up current
  341.           * line of window then we must adjust logical line and real line.
  342.           */
  343.          if (func == LineUp) {
  344.             if (above->bottom_line > above->top_line) {
  345.                if (window->rline == (window->cline - (window->top_line-1)))
  346.                   --window->cline;
  347.                --window->top_line;
  348.                if (above->cline == above->bottom_line) {
  349.                   above->cursor = cpb( above->cursor );
  350.                   above->cursor = find_prev( above->cursor );
  351.                   --above->rline;
  352.                   --above->cline;
  353.                   show_line_col( above );
  354.                   --above_change;
  355.                }
  356.                --above->bottom_line;
  357.                resize = TRUE;
  358.                display_current_window( window );
  359.                save_screen_line( 0, prompt_line, line_buff );
  360.             }
  361.  
  362.          /*
  363.           * if line down make current window top line shrink and bottom line
  364.           * of above window grow.   if window movement covers up current
  365.           * line of window then we must adjust logical line and real line.
  366.           */
  367.          } else if (func == LineDown) {
  368.             if (window->bottom_line > window->top_line) {
  369.                if (window->cline == window->top_line) {
  370.                   ++window->cline;
  371.                   window->cursor = cpf( window->cursor );
  372.                   p = find_next( window->cursor );
  373.                   if (p != NULL) {
  374.                      window->cursor = p;
  375.                      ++window->rline;
  376.                   }
  377.                }
  378.                ++window->top_line;
  379.                ++above->bottom_line;
  380.                display_current_window( above );
  381.                ++above_change;
  382.                resize = TRUE;
  383.             }
  384.          }
  385.  
  386.          /*
  387.           * if we resize a window then update window size and current and
  388.           * real lines if needed.
  389.           */
  390.          if (resize == TRUE) {
  391.             setup_window( above );
  392.             setup_window( window );
  393.             show_window_header( file_name, window );
  394.             show_size_name( window );
  395.             show_size( window );
  396.             show_line_col( window );
  397.             set_prompt( instr, prompt_line );
  398.          }
  399.       }
  400.       restore_screen_line( 0, prompt_line, line_buff );
  401.       if (above_change != 0) {
  402.          n = g_status.window_list;
  403.          while (n != NULL) {
  404.             /*
  405.              * check all invisible windows - make sure they have
  406.              * correct top and bottom lines.
  407.              */
  408.             if (n != above  &&  n != window ) {
  409.                if (n->top_line == above->top_line) {
  410.                   n->bottom_line = above->bottom_line;
  411.                   setup_window( n );
  412.                   if (n->cline > n->bottom_line)
  413.                      n->cline = n->bottom_line;
  414.                } else if (n->bottom_line == window->bottom_line) {
  415.                   n->top_line = window->top_line;
  416.                   setup_window( n );
  417.                   if (n->cline < n->top_line)
  418.                      n->cline = n->top_line;
  419.                }
  420.             }
  421.             n = n->next;
  422.          }
  423.       }
  424.    } else
  425.      error( WARNING, window->bottom_line, "can not resize top window" );
  426. }
  427.  
  428.  
  429. /*
  430.  * Name:    zoom_window
  431.  * Purpose: To blow-up current window.
  432.  * Date:    September 1, 1991
  433.  * Passed:  window:   information allowing access to the current window
  434.  * Notes:   Make all windows, visible and hidden, full size.
  435.  */
  436. void zoom_window( windows *window )
  437. {
  438. register windows *wp;
  439.  
  440.    if (window != NULL) {
  441.       if (window->top_line != 1 || window->bottom_line != g_display.nlines) {
  442.          for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  443.             if (wp != window && wp->visible)
  444.                wp->visible = FALSE;
  445.             if (wp->top_line != 1)
  446.                wp->cline = wp->cline - wp->top_line + 1;
  447.             wp->top_line = 1;
  448.             wp->bottom_line = g_display.nlines;
  449.          }
  450.          redraw_screen( window );
  451.       }
  452.    }
  453. }
  454.  
  455.  
  456. /*
  457.  * Name:    next_hidden_window
  458.  * Purpose: To display the window that is "behind" current window.
  459.  * Date:    September 1, 1991
  460.  * Passed:  window:   information allowing access to the current window
  461.  * Notes:   Make all windows, visible and hidden, full size.
  462.  */
  463. void next_hidden_window( windows *window )
  464. {
  465. int found = FALSE;
  466. register windows *wp;
  467.  
  468.    if (window != NULL) {
  469.       wp = window;
  470.       for (wp=window->next; wp != NULL && !found; ) {
  471.          if (!wp->visible)
  472.             found = TRUE;
  473.          else
  474.             wp = wp->next;
  475.       }
  476.       if (!found) {
  477.          for (wp=g_status.window_list; wp != NULL && !found; ) {
  478.             if (!wp->visible)
  479.                found = TRUE;
  480.             else
  481.                wp = wp->next;
  482.          }
  483.       }
  484.       if (found) {
  485.          wp->cline = window->top_line + (wp->cline - wp->top_line);
  486.          wp->top_line = window->top_line;
  487.          wp->bottom_line = window->bottom_line;
  488.          if (wp->cline > wp->bottom_line)
  489.             wp->cline = wp->bottom_line;
  490.          if ((wp->cline+1 - wp->top_line) > wp->rline)
  491.             wp->cline = (int)wp->rline;
  492.          wp->visible = TRUE;
  493.          window->visible = FALSE;
  494.          g_status.current_window = wp;
  495.          redraw_current_window( wp );
  496.       }
  497.    }
  498. }
  499.  
  500.  
  501. /*
  502.  * Name:    setup_window
  503.  * Purpose: To set the page length and the center line of a window, based
  504.  *           on the top and bottom lines.
  505.  * Date:    June 5, 1991
  506.  * Passed:  window: window to be set up
  507.  */
  508. void setup_window( windows *window )
  509. {
  510.    window->page = window->bottom_line - window->top_line -
  511.                   g_status.overlap + 1;
  512.    if (window->page < 1)
  513.       window->page = 1;
  514. }
  515.  
  516.  
  517. /*
  518.  * Name:    finish
  519.  * Purpose: To remove the current window, and terminate the program if no
  520.  *           more windows are left.
  521.  * Date:    June 5, 1991
  522.  * Passed:  window: information allowing access to the current window
  523.  * Notes:   Order of deciding which window becomes current window:
  524.  *          1) If any invisible windows with same top and bottom line then
  525.  *          first invisible one becomes current window.
  526.  *          2) first available invisible window becomes current window.
  527.  *          3) window above if it exists becomes current window
  528.  *          4) window below if it exists becomes current window
  529.  */
  530. void finish( windows *window )
  531. {
  532. register windows *wp;        /* for scanning other windows */
  533. file_infos *file;   /* for scanning other files */
  534. long number;        /* number of bytes removed / copied */
  535. int poof;
  536. int cline;
  537. int top, bottom;
  538.  
  539.    un_copy_line( window->cursor, window, TRUE );
  540.    /*
  541.     * remove old window from list
  542.     */
  543.    top = 1;
  544.    bottom = g_display.nlines;
  545.    if (window->prev == NULL) {
  546.       if (window->next == NULL)
  547.          g_status.stop = TRUE;
  548.       else
  549.          g_status.window_list = window->next;
  550.    } else
  551.       window->prev->next = window->next;
  552.  
  553.  
  554.    /*
  555.     * remove all hidden windows that point to same file
  556.     */
  557.    if (g_status.stop != TRUE) {
  558.       if (window->next)
  559.          window->next->prev = window->prev;
  560.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  561.          if (!wp->visible && wp->file_info == window->file_info) {
  562.             if (wp->prev == NULL) {
  563.                if (wp->next == NULL)
  564.                   g_status.stop = TRUE;
  565.                else
  566.                   g_status.window_list = wp->next;
  567.             } else
  568.                wp->prev->next = wp->next;
  569.             if (wp->next)
  570.                wp->next->prev = wp->prev;
  571.             --wp->file_info->ref_count;
  572.             free( wp );
  573.             --g_status.window_count;
  574.          }
  575.       }
  576.       show_file_count( g_status.file_count );
  577.    }
  578.  
  579.    if (g_status.stop != TRUE) {
  580.       /*
  581.        * see if there are any invisible windows with same top and bottom
  582.        * lines as this window.
  583.        */
  584.       poof = FALSE;
  585.       wp = g_status.window_list;
  586.       while (wp != NULL && poof == FALSE) {
  587.          if (wp->top_line == window->top_line && !wp->visible) {
  588.             poof = TRUE;
  589.             top = window->top_line;
  590.             bottom = window->bottom_line;
  591.          } else
  592.             wp = wp->next;
  593.       }
  594.  
  595.       if (poof == FALSE) {
  596.          /*
  597.           * see if there are any other invisible windows
  598.           */
  599.          wp = g_status.window_list;
  600.          while (wp != NULL && poof == FALSE) {
  601.             if (!wp->visible) {
  602.                poof = TRUE;
  603.                top = window->top_line;
  604.                bottom = window->bottom_line;
  605.             } else
  606.                wp = wp->next;
  607.          }
  608.          if (poof == FALSE) {
  609.             /*
  610.              * see if there are any windows above
  611.              */
  612.             wp = g_status.window_list;
  613.             while (wp != NULL && poof == FALSE) {
  614.                if (wp->bottom_line+2 == window->top_line) {
  615.                   poof = TRUE;
  616.                   top = wp->top_line;
  617.                   bottom = window->bottom_line;
  618.                } else
  619.                   wp = wp->next;
  620.             }
  621.          }
  622.          if (poof == FALSE) {
  623.             /*
  624.              * see if there are any windows below
  625.              */
  626.             wp = g_status.window_list;
  627.             while (wp != NULL && poof == FALSE) {
  628.                if (wp->top_line-2 == window->bottom_line) {
  629.                   poof = TRUE;
  630.                   top = window->top_line;
  631.                   bottom = wp->bottom_line;
  632.                } else
  633.                   wp = wp->next;
  634.             }
  635.             if (wp == NULL)
  636.                wp = g_status.window_list;
  637.          }
  638.       }
  639.       wp->visible = TRUE;
  640.       cline = wp->cline - wp->top_line;
  641.       wp->top_line = top;
  642.       wp->bottom_line = bottom;
  643.       wp->cline = wp->top_line + cline;
  644.       if (wp->cline > wp->bottom_line)
  645.          wp->cline = wp->top_line;
  646.       setup_window( wp );
  647.       show_window_header( wp->file_info->file_name, wp );
  648.       show_size_name( wp );
  649.       show_size( wp );
  650.       show_line_col( wp );
  651.  
  652.       /*
  653.        * The window above, below, or previously invisible becomes the new
  654.        * current window.
  655.        */
  656.       g_status.current_window = wp;
  657.  
  658.       /*
  659.        * free unused file memory if necessary
  660.        */
  661.       file = window->file_info;
  662.       if (--file->ref_count == 0) {
  663.          /*
  664.           * no window now refers to this file, so remove file from the list
  665.           */
  666.          if (file->prev == NULL)
  667.             g_status.file_list = file->next;
  668.          else
  669.             file->prev->next = file->next;
  670.          if (file->next)
  671.             file->next->prev = file->prev;
  672.  
  673.          /*
  674.           * close up the gap in the memory buffer
  675.           */
  676.          number = ptoul( g_status.end_mem ) - ptoul( file->end_text );
  677.          hw_move( file->start_text, file->end_text, number );
  678.          number = ptoul( file->end_text ) - ptoul( file->start_text );
  679.          g_status.end_mem = addltop( -number, g_status.end_mem );
  680.          addorsub_all_cursors( window, -number );
  681.          adjust_start_end( file, -number );
  682.          show_avail_mem( );
  683.  
  684.          /*
  685.           * free the memory taken by the file structure
  686.           */
  687.          free( file );
  688.          --g_status.file_count;
  689.          show_file_count( g_status.file_count );
  690.       }
  691.  
  692.       /*
  693.        * free the memory taken by the window structure
  694.        */
  695.       free( window );
  696.       --g_status.window_count;
  697.       g_status.current_file = wp->file_info;
  698.       wp->file_info->dirty = LOCAL;
  699.       show_window_count( g_status.window_count );
  700.    }
  701. }
  702.  
  703.  
  704. /*
  705.  * Name:    create_window
  706.  * Purpose: To allocate space for a new window structure, and set up some
  707.  *           of the relevant fields.
  708.  * Date:    June 5, 1991
  709.  * Passed:  window: pointer to window pointer
  710.  *          top:    the top line of the new window
  711.  *          bottom: the bottom line of the new window
  712.  *          file:   the file structure to be associated with the new window
  713.  * Returns: OK if window could be created
  714.  *          ERROR if out of memory
  715.  */
  716. int  create_window( windows **window, int top, int bottom, file_infos *file )
  717. {
  718. windows *wp;  /* temporary variable - use it instead of **window */
  719. windows *prev;
  720. int rc;           /* return code */
  721.  
  722.    rc = OK;
  723.    /*
  724.     * allocate space for new window structure
  725.     */
  726.    if ((*window = (windows *)calloc( 1, sizeof(windows) )) == NULL) {
  727.       error( WARNING, g_display.nlines, "out of memory for window" );
  728.       rc = ERROR;
  729.    } else {
  730.  
  731.      /*
  732.       * set up appropriate fields
  733.       */
  734.       wp = *window;
  735.       wp->file_info = file;
  736.       wp->cline = wp->top_line = top+1;
  737.       wp->bottom_line = bottom;
  738.       wp->prev = NULL;
  739.       wp->next = NULL;
  740.       setup_window( wp );
  741.  
  742.       /*
  743.        * add window into window list
  744.        */
  745.       prev = g_status.current_window;
  746.       if (prev) {
  747.          (*window)->prev = prev;
  748.          if (prev->next)
  749.             prev->next->prev = *window;
  750.          (*window)->next = prev->next;
  751.          prev->next = *window;
  752.       }
  753.       if (g_status.window_list == NULL)
  754.          g_status.window_list = *window;
  755.  
  756.       /*
  757.        * record that another window is referencing this file
  758.        */
  759.       ++file->ref_count;
  760.       file->dirty = LOCAL;
  761.       ++g_status.window_count;
  762.       show_window_count( g_status.window_count );
  763.    }
  764.    return( rc );
  765. }
  766.  
  767.  
  768. /*
  769.  * Name:    edit_file
  770.  * Purpose: To allocate space for a new file structure, and set up some
  771.  *           of the relevant fields.
  772.  * Date:    June 5, 1991
  773.  * Passed:  name:  name of the file to edit
  774.  * Returns: OK if file structure could be created
  775.  *          ERROR if out of memory
  776.  */
  777. int  edit_file( char *name )
  778. {
  779. int rc;           /* return code */
  780. int existing;
  781. int line;
  782. register file_infos *file; /* file structure for file belonging to new window */
  783. file_infos *fp;
  784. text_ptr next;      /* text pointer */
  785. long size;
  786. struct stat filestat;  /* struct stat defined in \sys\stat */
  787.  
  788.    rc = OK;
  789.    line = g_display.nlines;
  790.    if (hw_fattrib( name ) != ERROR) {
  791.       existing = TRUE;
  792.       /*
  793.        * g_status.temp_end is set last character read in file
  794.        */
  795.       rc = load_file( name );
  796.    } else {
  797.       /*
  798.        * setup as empty file - make an empty file have a linefeed
  799.        */
  800.       existing = FALSE;
  801.       g_status.temp_end = cpf( g_status.end_mem );
  802.    }
  803.  
  804.    if (rc != ERROR) {
  805.       /*
  806.        * allocate a file structure for the new file
  807.        */
  808.       file = (file_infos *)calloc( 1, sizeof(file_infos) );
  809.       if (file == NULL) {
  810.          error( WARNING, g_display.nlines, "out of memory for file info" );
  811.          rc = ERROR;
  812.       } else {
  813.          /*
  814.           * add file into list
  815.           */
  816.          file->prev = NULL;
  817.          file->next = NULL;
  818.          if (g_status.file_list == NULL)
  819.             g_status.file_list = file;
  820.          else {
  821.             fp = g_status.current_file;
  822.             file->prev = fp;
  823.             if (fp->next)
  824.                fp->next->prev = file;
  825.             file->next = fp->next;
  826.             fp->next = file;
  827.          }
  828.       }
  829.       if (rc != ERROR) {
  830.          /*
  831.           * set up all the info we need to know about a file, and
  832.           *  record that we have used some more memory.
  833.           */
  834.          strcpy( file->file_name, name );
  835.          stat( name, &filestat );
  836.          file->file_attrib = filestat.st_mode;
  837.          file->start_text = g_status.end_mem;
  838.          *g_status.temp_end = CONTROL_Z;
  839.          g_status.temp_end = cpf( g_status.temp_end );
  840.          g_status.end_mem = g_status.temp_end + 1;
  841.          g_status.temp_end = g_status.end_mem;
  842.          file->end_text = g_status.end_mem;
  843.          size = 0l;
  844.          if (existing) {
  845.             next = file->start_text = cpf( file->start_text );
  846.             while ((next = find_next( next )) != NULL)
  847.                size++;
  848.          }
  849.          file->length      = size;
  850.          file->block_end   = file->block_start = NULL;
  851.          file->block_bc    = file->block_ec = 0;
  852.          file->block_br    = file->block_er = 0l;
  853.          file->block_type  = NOTMARKED;
  854.          file->modified    = FALSE;
  855.          file->file_no     = g_status.next_file_number++;
  856.          file->next_window_letter = 'a';
  857.       }
  858.    }
  859.    if (rc != ERROR && !existing)
  860.       file->new_file = TRUE;
  861.    else if (rc != ERROR && existing)
  862.       file->new_file = FALSE;
  863.    if (rc != ERROR) {
  864.       g_status.current_file = file;
  865.       file->ref_count = 0;
  866.       ++g_status.file_count;
  867.    }
  868.    return( rc );
  869. }
  870.  
  871.  
  872. /*
  873.  * Name:    edit_another_file
  874.  * Purpose: Bring in another file to editor.
  875.  * Date:    June 5, 1991
  876.  * Passed:  window: information allowing access to the current window
  877.  * Notes:   New window replaces old window.  Old window becomes invisible.
  878.  */
  879. void edit_another_file( windows *window )
  880. {
  881. char name[MAX_COLS];              /* new name for file */
  882. int prompt_line;
  883. int ok;
  884.  
  885.    un_copy_line( window->cursor, window, TRUE );
  886.    /*
  887.     * read in name, no default
  888.     */
  889.    prompt_line = window->bottom_line;
  890.    name[0] = '\0';
  891.    if (get_name( "File to edit: ", prompt_line, name,
  892.                  g_display.message_color ) == OK) {
  893.       ok = edit_file( name );
  894.       if (ok != ERROR) {
  895.          ok = initialize_window( );
  896.          if (ok != ERROR) {
  897.             window = g_status.current_window;
  898.             show_window_header( window->file_info->file_name, window );
  899.             show_size_name( window );
  900.             show_size( window );
  901.             show_file_count( g_status.file_count );
  902.             show_avail_mem( );
  903.             window->file_info->dirty = LOCAL;
  904.          }
  905.       }
  906.    }
  907. }
  908. 
  909.