home *** CD-ROM | disk | FTP | other *** search
- /******************* start of original comments ********************/
- /*
- * Written by Douglas Thomson (1989/1990)
- *
- * This source code is released into the public domain.
- */
-
- /*
- * Name: dte - Doug's Text Editor program - window module
- * Purpose: This file contains the code associated with opening and sizing
- * windows, and also displaying the help window.
- * File: window.c
- * Author: Douglas Thomson
- * System: this file is intended to be system-independent
- * Date: October 12, 1989
- */
- /********************* end of original comments ********************/
-
-
- /*
- * The window routines have been EXTENSIVELY rewritten. Some routines were
- * changed so only one logical function is carried out, eg. 'initialize_window'.
- * I like the Microsoft way of resizing windows - just press the up and down
- * arrows to adjust the window to desired size. I also like pressing one key
- * to change windows. All of which are implemented.
- *
- * In tde, version 1.4, I added support for vertical windows.
- *
- * New editor name: tde, the Thomson-Davis Editor.
- * Author: Frank Davis
- * Date: June 5, 1991, version 1.0
- * Date: July 29, 1991, version 1.1
- * Date: October 5, 1991, version 1.2
- * Date: January 20, 1992, version 1.3
- * Date: February 17, 1992, version 1.4
- * Date: April 1, 1992, version 1.5
- *
- * This modification of Douglas Thomson's code is released into the
- * public domain, Frank Davis. You may distribute it freely.
- */
-
- #include "tdestr.h"
- #include "common.h"
- #include "define.h"
- #include "tdefunc.h"
-
-
- /*
- * Name: initialize_window
- * Purpose: To open a new window
- * Date: June 5, 1991
- * Returns: OK if window opened successfully
- * ERROR if anything went wrong
- * Notes: If this is first window then set up as normal displayed window
- * otherwise make the present window invisible and open a new
- * window in the same screen location as the old one.
- */
- int initialize_window( void )
- {
- int top;
- int bottom;
- int start_col;
- int end_col;
- WINDOW *wp; /* used for scanning windows */
- WINDOW *window;
- register file_infos *fp; /* used for scanning files */
- register int rc;
-
- rc = OK;
- window = g_status.current_window;
- fp = g_status.current_file;
- if (window == NULL) {
- /*
- * special case if this is the first window on screen.
- */
- top = start_col = 0;
- bottom = g_display.nlines;
- end_col = g_display.ncols - 1;
- } else {
- /*
- * else put the new window in same place as current window.
- * make current window invisible. new window becomes current window.
- */
- top = window->top_line - 1;
- bottom = window->bottom_line;
- start_col = window->start_col;
- end_col = window->end_col;
- }
-
- if (create_window( &wp, top, bottom, start_col, end_col, fp ) == ERROR) {
- error( WARNING, bottom, "out of memory" );
-
- /*
- * This is a real nuisance. We had room for the file and the
- * file structure, but not enough for the window as well.
- * Now we must free all the memory that has already been
- * allocated.
- */
- if (fp->ref_count == 0) {
- if (fp->prev)
- fp->prev->next = fp->next;
- else
- g_status.file_list = fp->next;
- if (fp->next)
- fp->next->prev = fp->prev;
- g_status.end_mem = fp->start_text;
- free( fp );
- wp = g_status.current_window;
- if (wp != NULL && wp->visible)
- g_status.current_file = wp->file_info;
- else
- g_status.stop = TRUE;
- }
- rc = ERROR;
- }
-
- if (rc != ERROR) {
- /*
- * set up the new cursor position as appropriate
- */
- wp->cursor = cpf( fp->start_text );
- wp->ccol = wp->start_col;
- wp->rcol = wp->bcol = 0;
- wp->rline = 1l;
- wp->visible = TRUE;
- wp->letter = fp->next_letter++;
- if (window != NULL)
- window->visible = FALSE;
-
- /*
- * the new window becomes the current window.
- */
- g_status.current_window = wp;
- }
- return( rc );
- }
-
-
- /*
- * Name: next_window
- * Purpose: To move to the next visible window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Start with current window. If next window exists then go to
- * it else go to the first (top) window on screen.
- * When I added vertical windows, finding the "correct" next
- * window became extremely, unnecessarily, unmanageably complicated.
- * let's just use a simple procedure to find the first available,
- * visible, next window.
- */
- void next_window( WINDOW *window )
- {
- register WINDOW *wp;
- int change;
-
- if (window != NULL) {
- change = FALSE;
- /*
- * start with current window and look for first next
- * visible window
- */
- wp = window->next;
- while (wp != NULL) {
- if (wp->visible) {
- change = TRUE;
- break;
- }
- wp = wp->next;
- }
-
- /*
- * if we haven't found a visible window yet, go to the end of
- * the list and work backwards until we find a visible window.
- */
- if (!change) {
- wp = g_status.window_list;
- while (wp != window) {
- if (wp->visible) {
- change = TRUE;
- break;
- }
- wp = wp->next;
- }
- }
- if (change == TRUE) {
- un_copy_line( window->cursor, window, TRUE );
- g_status.current_window = wp;
- g_status.current_file = wp->file_info;
- }
- }
- }
-
-
- /*
- * Name: prev_window
- * Purpose: To move to the previous visible window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Start with current window. If previous window exists then go to
- * it else go to the last (bottom) window on screen. Opposite of
- * next_window.
- * when I added vertical windows, finding the "correct" previous
- * window became extremely, unnecessarily, unmanageably complicated.
- * let's just use a simple procedure to find the first available,
- * visible, previous window.
- */
- void prev_window( WINDOW *window )
- {
- register WINDOW *wp;
- int change;
-
- if (window != NULL) {
- change = FALSE;
-
- /*
- * start with current window and look for first previous
- * visible window
- */
- wp = window->prev;
- while (wp != NULL) {
- if (wp->visible) {
- change = TRUE;
- break;
- }
- wp = wp->prev;
- }
-
- /*
- * if we haven't found a visible window yet, go to the end of
- * the list and work backwards until we find a visible window.
- */
- if (!change) {
- wp = window->next;
- if (wp != NULL) {
- while (wp->next != NULL)
- wp = wp->next;
- while (wp != window) {
- if (wp->visible) {
- change = TRUE;
- break;
- }
- wp = wp->prev;
- }
- }
- }
- if (change == TRUE) {
- un_copy_line( window->cursor, window, TRUE );
- g_status.current_window = wp;
- g_status.current_file = wp->file_info;
- }
- }
- }
-
-
- /*
- * Name: split_horizontal
- * Purpose: To split screen horizontally at the cursor.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: split the screen horizontally at the cursor position.
- */
- void split_horizontal( WINDOW *window )
- {
- register WINDOW *wp;
- register WINDOW *win; /* register pointer for window */
- WINDOW *temp;
- file_infos *file; /* file structure for file belonging to new window */
-
- win = window;
- /*
- * check that there is room for the window
- */
- if (win->bottom_line - win->cline < 2)
- error( WARNING, win->bottom_line, "move cursor up first" );
- else {
- file = win->file_info;
- if (create_window( &temp, win->cline+1, win->bottom_line,
- win->start_col, win->end_col, file ) == ERROR) {
- error( WARNING, win->bottom_line, "out of memory" );
- } else {
- un_copy_line( win->cursor, win, TRUE );
- wp = temp;
- /*
- * record that the current window has lost some lines from
- * the bottom for the new window, and adjust its page size
- * etc accordingly.
- */
- win->bottom_line = win->cline;
- setup_window( win );
- display_current_window( win );
-
- /*
- * set up the new cursor position as appropriate
- */
- wp->rcol = win->rcol;
- wp->ccol = win->ccol;
- wp->bcol = win->bcol;
- wp->rline = win->rline;
- wp->cline = wp->cline + win->cline - (win->top_line + win->ruler);
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->bottom_line;
- wp->cursor = win->cursor;
- wp->visible = TRUE;
- wp->vertical = win->vertical;
- wp->letter = file->next_letter++;
- wp->ruler = mode.ruler;
-
- /*
- * the new window becomes the current window.
- */
- g_status.current_window = wp;
-
- show_window_count( g_status.window_count );
- show_window_header( wp );
- display_current_window( wp );
- if (wp->vertical)
- show_vertical_separator( wp );
- make_ruler( wp );
- show_ruler( wp );
- }
- }
- }
-
-
- /*
- * Name: split_vertical
- * Purpose: To split screen vertically at the cursor.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: split the screen vertically at the cursor position.
- */
- void split_vertical( WINDOW *window )
- {
- register WINDOW *wp;
- register WINDOW *win; /* register pointer for window */
- WINDOW *temp;
- file_infos *file; /* file structure for file belonging to new window */
-
- win = window;
- /*
- * check that there is room for the window
- */
- if (win->start_col + 15 > win->ccol)
- error( WARNING, win->bottom_line, "move cursor right first" );
- else if (win->end_col - 15 < win->ccol)
- error( WARNING, win->bottom_line, "move cursor left first" );
- else {
- file = win->file_info;
- if (create_window( &temp, win->top_line-1, win->bottom_line,
- win->ccol+1, win->end_col, file ) == ERROR) {
- error( WARNING, win->bottom_line, "out of memory" );
- } else {
- un_copy_line( win->cursor, win, TRUE );
- wp = temp;
- /*
- * record that the current window has lost some columns from
- * the window to the left for the new window
- */
- win->ccol = win->end_col = win->ccol - 1;
- win->rcol--;
- win->vertical = TRUE;
- show_window_header( win );
- show_vertical_separator( win );
- display_current_window( win );
- make_ruler( win );
- show_ruler( win );
- show_ruler_pointer( win );
-
- /*
- * set up the new cursor position as appropriate
- */
- wp->rcol = win->rcol;
- wp->ccol = wp->start_col + win->ccol - win->start_col;
- if (wp->ccol > wp->end_col)
- wp->ccol = wp->end_col;
- wp->bcol = win->bcol;
- wp->rline = win->rline;
- wp->cline = win->cline;
- wp->cursor = win->cursor;
- wp->visible = TRUE;
- wp->vertical = TRUE;
- wp->letter = file->next_letter++;
- wp->ruler = mode.ruler;
-
- /*
- * the new window becomes the current window.
- */
- g_status.current_window = wp;
-
- check_virtual_col( wp, wp->rcol, wp->ccol );
- wp->file_info->dirty = FALSE;
- show_window_count( g_status.window_count );
- show_window_header( wp );
- display_current_window( wp );
- make_ruler( wp );
- show_ruler( wp );
- }
- }
- }
-
-
- /*
- * Name: show_vertical_separator
- * Purpose: To separate vertical screens
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- */
- void show_vertical_separator( WINDOW *window )
- {
- int i;
- int line;
- int col;
-
- line = window->top_line - 1;
- col = window->end_col + 1;
- if (col < g_display.ncols - 1) {
- i = window->bottom_line + 1 - line;
- while (i-- > 0)
- c_output( VERTICAL_CHAR, col, line++, g_display.head_color );
- }
- }
-
-
- /*
- * Name: size_window
- * Purpose: To change the size of the current and one other window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Use the Up and Down arrow keys to make the current window
- * bigger or smaller. The window above will either grow
- * or contract accordingly.
- */
- void size_window( WINDOW *window )
- {
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- int func, c;
- register WINDOW *above;
- register WINDOW *win;
- int resize;
- int show_above_ruler;
- char *instr =
- "Press Up or Down to change window size. Press Return when done.";
-
- win = window;
- if (win->top_line != 1 && !win->vertical) {
- un_copy_line( win->cursor, win, TRUE );
- save_screen_line( 0, win->bottom_line, line_buff );
- set_prompt( instr, win->bottom_line );
-
- /*
- * resizing only affects current window and above visible window
- */
- above = g_status.window_list;
- while (above->bottom_line + 2 != win->top_line || !above->visible)
- above = above->next;
- if (above->vertical)
- error( WARNING, win->bottom_line, "can not resize vertical window" );
- else {
- show_above_ruler = FALSE;
- for (func=0; func != AbortCommand && func != Rturn; ) {
-
- /*
- * If user has redined the ESC and Return keys, make them Rturn and
- * AbortCommand in this function.
- */
- c = getkey( );
- func = getfunc( c );
- if (c == RTURN || func == NextLine || func == BegNextLine)
- func = Rturn;
- else if (c == ESC)
- func = AbortCommand;
- resize = FALSE;
-
- /*
- * if LineUp, make current window top line grow and bottom line
- * of above window shrink. if window movement covers up current
- * line of window then we must adjust logical line and real line.
- */
- if (func == LineUp) {
- if (above->bottom_line > above->top_line + above->ruler) {
- if (win->rline == (win->cline - (win->top_line+win->ruler-1)))
- --win->cline;
- --win->top_line;
- if (above->cline == above->bottom_line)
- --above->cline;
- --above->bottom_line;
- resize = TRUE;
- if (mode.ruler) {
- if (win->ruler == FALSE) {
- if (win->cline == win->top_line)
- ++win->cline;
- if (win->cline > win->bottom_line)
- win->cline = win->bottom_line;
- win->ruler = TRUE;
- }
- }
- }
-
- /*
- * if LineDown, make current window top line shrink and bottom line
- * of above window grow. if window movement covers up current
- * line of window then we must adjust logical line and real line.
- */
- } else if (func == LineDown) {
- if (win->bottom_line > win->top_line + win->ruler) {
- if (win->cline == win->top_line + win->ruler)
- ++win->cline;
- ++win->top_line;
- ++above->bottom_line;
- resize = TRUE;
- if (mode.ruler) {
- if (above->ruler == FALSE) {
- if (above->cline == above->top_line)
- ++above->cline;
- if (above->cline > above->bottom_line)
- above->cline = above->bottom_line;
- above->ruler = TRUE;
- make_ruler( above );
- show_above_ruler = TRUE;
- }
- }
- }
- }
-
- /*
- * if we resize a window then update window size and current and
- * real lines if needed.
- */
- if (resize == TRUE) {
- setup_window( above );
- display_current_window( above );
- if (show_above_ruler) {
- show_ruler( above );
- show_ruler_pointer( above );
- show_above_ruler = FALSE;
- }
- setup_window( win );
- show_window_header( win );
- win->ruler = mode.ruler;
- make_ruler( win );
- show_ruler( win );
- show_ruler_pointer( win );
- display_current_window( win );
- save_screen_line( 0, win->bottom_line, line_buff );
- set_prompt( instr, win->bottom_line );
- }
- }
- }
- restore_screen_line( 0, win->bottom_line, line_buff );
- } else {
- if (win->vertical)
- error( WARNING, win->bottom_line, "can not resize vertical window" );
- else
- error( WARNING, win->bottom_line, "can not resize top window" );
- }
- }
-
-
- /*
- * Name: zoom_window
- * Purpose: To blow-up current window.
- * Date: September 1, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Make all windows, visible and hidden, full size.
- */
- void zoom_window( WINDOW *window )
- {
- register WINDOW *wp;
-
- if (window != NULL) {
- if (window->top_line != 1 || window->bottom_line != g_display.nlines) {
- un_copy_line( window->cursor, window, TRUE );
- for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
- if (wp != window && wp->visible)
- wp->visible = FALSE;
- if (wp->top_line != 1)
- wp->cline = wp->cline - (wp->top_line+wp->ruler) + 1;
- wp->top_line = 1;
- wp->bottom_line = g_display.nlines;
- wp->end_col = g_display.ncols - 1;
- wp->start_col = 0;
- wp->vertical = FALSE;
- make_ruler( wp );
- }
- redraw_screen( window );
- show_ruler( window );
- }
- }
- }
-
-
- /*
- * Name: next_hidden_window
- * Purpose: To display the window that is "behind" current window.
- * Date: September 1, 1991
- * Passed: window: information allowing access to the current window
- */
- void next_hidden_window( WINDOW *window )
- {
- int poof = FALSE;
- register WINDOW *wp;
-
- if (window != NULL) {
-
- /*
- * look for next hidden window starting with current window.
- */
- wp = window;
- for (wp=window->next; wp != NULL && !poof; ) {
- if (!wp->visible)
- poof = TRUE;
- else
- wp = wp->next;
- }
-
- /*
- * if we haven't found an invisible window yet, start looking
- * for a hidden window from the beginning of the window list.
- */
- if (!poof) {
- for (wp=g_status.window_list; wp != NULL && !poof; ) {
- if (!wp->visible)
- poof = TRUE;
- else
- wp = wp->next;
- }
- }
-
- if (poof) {
- un_copy_line( window->cursor, window, TRUE );
- wp->cline = window->top_line + window->ruler +
- (wp->cline - (wp->top_line + wp->ruler));
- wp->top_line = window->top_line;
- wp->bottom_line = window->bottom_line;
- wp->start_col = window->start_col;
- wp->end_col = window->end_col;
- wp->vertical = window->vertical;
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->bottom_line;
- if ((wp->cline+1L - (wp->top_line+wp->ruler)) > wp->rline)
- wp->cline = (int)wp->rline;
- wp->visible = TRUE;
- window->visible = FALSE;
- g_status.current_window = wp;
- redraw_current_window( wp );
- make_ruler( wp );
- show_ruler( wp );
- }
- }
- }
-
-
- /*
- * Name: setup_window
- * Purpose: To set the page length and the center line of a window, based
- * on the top and bottom lines.
- * Date: June 5, 1991
- * Passed: window: window to be set up
- */
- void setup_window( WINDOW *window )
- {
- window->page = window->bottom_line - (window->top_line + window->ruler) -
- g_status.overlap + 1;
- if (window->page < 1)
- window->page = 1;
- }
-
-
- /*
- * Name: finish
- * Purpose: To remove the current window and terminate the program if no
- * more windows are left.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Order of deciding which window becomes current window:
- * 1) If any invisible window with same top and bottom line,
- * and start_col and end_col, then first invisible one becomes
- * current window.
- * 2) first available invisible window becomes current window.
- * 3) window above if it exists becomes current window
- * 4) window below if it exists becomes current window
- * 5) window right if it exists becomes current window
- * 6) window left if it exists becomes current window
- * When I added vertical windows, this routine became a LOT
- * more complicated. To keep things reasonably sane, let's
- * only close windows that have three common edges, eg.
- *
- * ┌────┬──────────┐
- * │ │ no │
- * │ ├─────┬────┤
- * │ no │yes1 │yes1│
- * │ ├────┬┴────┤
- * │ │yes2│yes2 │
- * └────┴────┴─────┘
- *
- * Windows with 'no' cannot be closed. Windows with 'yes' can
- * be combined with windows that have the same yes number.
- */
- void finish( WINDOW *window )
- {
- register WINDOW *wp; /* for scanning other windows */
- register WINDOW *win; /* register pointer for window */
- file_infos *file, *fp; /* for scanning other files */
- long number; /* number of bytes removed / copied */
- int poof;
- int cline;
- int top, bottom;
- int start_col, end_col;
- int max_letter;
- int file_change = FALSE;
-
- win = window;
- un_copy_line( win->cursor, win, TRUE );
- /*
- * remove old window from list
- */
- top = 1;
- bottom = g_display.nlines;
- if (win->prev == NULL && win->next == NULL)
- g_status.stop = TRUE;
-
- /*
- * remove all hidden windows that point to same file
- */
- file = win->file_info;
- for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
- if (wp->file_info == file) {
- if (!wp->visible) {
- if (wp->prev == NULL) {
- if (wp->next == NULL)
- g_status.stop = TRUE;
- else
- g_status.window_list = wp->next;
- } else
- wp->prev->next = wp->next;
- if (wp->next)
- wp->next->prev = wp->prev;
- --wp->file_info->ref_count;
- free( wp );
- --g_status.window_count;
- }
- }
- }
-
- poof = FALSE;
- if (g_status.stop != TRUE) {
- /*
- * see if there are any invisible windows with same top and bottom,
- * lines, and start_col and end_col as this window. start looking at
- * end of window list.
- */
- top = win->top_line;
- bottom = win->bottom_line;
- start_col = win->start_col;
- end_col = win->end_col;
- wp = g_status.window_list;
- if (wp != NULL) {
- while (wp->next != NULL)
- wp = wp->next;
- }
- while (wp != NULL && poof == FALSE) {
- if (wp->top_line == win->top_line && !wp->visible)
- poof = TRUE;
- else
- wp = wp->prev;
- }
-
- if (poof == FALSE) {
- /*
- * see if there are any other invisible windows. start looking
- * at the end of the window list.
- */
- wp = g_status.window_list;
- if (wp != NULL) {
- while (wp->next != NULL)
- wp = wp->next;
- }
- while (wp != NULL && poof == FALSE) {
- if (!wp->visible)
- poof = TRUE;
- else
- wp = wp->prev;
- }
- if (poof == FALSE) {
- /*
- * see if there are any windows above
- */
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (wp->bottom_line+2 == win->top_line &&
- wp->start_col == win->start_col &&
- wp->end_col == win->end_col) {
- poof = TRUE;
- top = wp->top_line;
- } else
- wp = wp->next;
- }
- }
- if (poof == FALSE) {
- /*
- * see if there are any windows below
- */
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (wp->top_line-2 == win->bottom_line &&
- wp->start_col == win->start_col &&
- wp->end_col == win->end_col) {
- poof = TRUE;
- bottom = wp->bottom_line;
- } else
- wp = wp->next;
- }
- }
- if (poof == FALSE) {
- /*
- * see if there are any windows right
- */
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (wp->top_line == win->top_line &&
- wp->bottom_line == win->bottom_line &&
- wp->start_col-2 == win->end_col) {
- poof = TRUE;
- end_col = wp->end_col;
- } else
- wp = wp->next;
- }
- }
- if (poof == FALSE) {
- /*
- * see if there are any windows left
- */
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (wp->top_line == win->top_line &&
- wp->bottom_line == win->bottom_line &&
- wp->end_col+2 == win->start_col) {
- poof = TRUE;
- start_col = wp->start_col;
- } else
- wp = wp->next;
- }
- }
- }
- if (poof) {
- wp->visible = TRUE;
- cline = wp->cline - (wp->top_line+wp->ruler);
- wp->top_line = top;
- wp->bottom_line = bottom;
- wp->cline = (wp->top_line+wp->ruler) + cline;
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->top_line+wp->ruler;
- wp->start_col = start_col;
- wp->end_col = end_col;
- if (start_col == 0 && end_col == g_display.ncols - 1)
- wp->vertical = FALSE;
- else
- wp->vertical = TRUE;
- check_virtual_col( wp, wp->rcol, wp->ccol );
- setup_window( wp );
- show_window_header( wp );
- if (wp->vertical)
- show_vertical_separator( wp );
-
- /*
- * The window above, below, or previously invisible becomes the new
- * current window.
- */
- g_status.current_window = wp;
- }
- }
-
- if (!poof && g_status.stop != TRUE)
- error( WARNING, win->bottom_line, "cannot close current window" );
- else {
-
- /*
- * free unused file memory if necessary
- */
- if (--file->ref_count == 0) {
-
- /*
- * if a block is marked, unmark it
- */
- if (file == g_status.marked_file) {
- g_status.marked = FALSE;
- g_status.marked_file = NULL;
- }
-
- for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
- if (fp->file_no > file->file_no)
- fp->file_no--;
- }
- file_change = file->file_no;
-
- /*
- * no window now refers to this file, so remove file from the list
- */
- if (file->prev == NULL)
- g_status.file_list = file->next;
- else
- file->prev->next = file->next;
- if (file->next)
- file->next->prev = file->prev;
-
- /*
- * close up the gap in the memory buffer
- */
- number = ptoul( g_status.end_mem ) - ptoul( file->end_text );
- hw_move( file->start_text, file->end_text, number );
- number = ptoul( file->end_text ) - ptoul( file->start_text );
- g_status.end_mem = addltop( -number, g_status.end_mem );
- addorsub_all_cursors( win, -number );
- adjust_start_end( file, -number );
-
- /*
- * free the memory taken by the file structure
- */
- free( file );
- if (--g_status.file_count) {
- show_file_count( g_status.file_count );
- show_avail_mem( );
- }
- }
-
- /*
- * remove the current window from the window list
- */
- if (win->prev == NULL) {
- if (win->next != NULL)
- g_status.window_list = win->next;
- } else
- win->prev->next = win->next;
-
- if (win->next)
- win->next->prev = win->prev;
-
- /*
- * free the memory taken by the window structure
- */
- free( win );
- --g_status.window_count;
-
- if (g_status.stop == FALSE) {
- g_status.current_file = wp->file_info;
- wp->file_info->dirty = LOCAL;
- make_ruler( wp );
- show_ruler( wp );
- show_window_count( g_status.window_count );
- if (file_change) {
- for (wp=g_status.window_list; wp!=NULL; wp=wp->next)
- if (wp->visible)
- show_window_number_letter( wp );
- } else {
- max_letter = 'a';
- for (wp=g_status.window_list; wp!=NULL; wp=wp->next) {
- if (wp->file_info == file && wp->letter > max_letter)
- max_letter = wp->letter;
- }
- if (max_letter < file->next_letter - 1)
- file->next_letter = max_letter + 1;
- }
- }
- }
- }
-
-
- /*
- * Name: create_window
- * Purpose: To allocate space for a new window structure and set up some
- * of the relevant fields.
- * Date: June 5, 1991
- * Passed: window: pointer to window pointer
- * top: the top line of the new window
- * bottom: the bottom line of the new window
- * file: the file structure to be associated with the new window
- * Returns: OK if window could be created
- * ERROR if out of memory
- */
- int create_window( WINDOW **window, int top, int bottom, int start_col,
- int end_col, file_infos *file )
- {
- WINDOW *wp; /* temporary variable - use it instead of **window */
- register WINDOW *prev;
- int rc; /* return code */
-
- rc = OK;
- /*
- * allocate space for new window structure
- */
- if ((*window = (WINDOW *)calloc( 1, sizeof(WINDOW) )) == NULL) {
- error( WARNING, g_display.nlines, "out of memory for window" );
- rc = ERROR;
- } else {
-
- /*
- * set up appropriate fields
- */
- wp = *window;
- wp->file_info = file;
- wp->top_line = top+1;
- wp->bottom_line = bottom;
- wp->start_col = start_col;
- wp->end_col = end_col;
- wp->ruler = mode.ruler;
- make_ruler( wp );
- wp->cline = wp->top_line + wp->ruler;
- if (start_col == 0 && end_col == g_display.ncols-1)
- wp->vertical = FALSE;
- else
- wp->vertical = TRUE;
- wp->prev = NULL;
- wp->next = NULL;
-
- setup_window( wp );
-
- /*
- * add window into window list
- */
- prev = g_status.current_window;
- if (prev) {
- (*window)->prev = prev;
- if (prev->next)
- prev->next->prev = *window;
- (*window)->next = prev->next;
- prev->next = *window;
- }
- if (g_status.window_list == NULL)
- g_status.window_list = *window;
-
-
- /*
- * record that another window is referencing this file
- */
- ++file->ref_count;
- file->dirty = LOCAL;
- ++g_status.window_count;
- }
- return( rc );
- }
-
-
- /*
- * Name: edit_file
- * Purpose: To allocate space for a new file structure and set up some
- * of the relevant fields.
- * Date: June 5, 1991
- * Passed: name: name of the file to edit
- * Returns: OK if file structure could be created
- * ERROR if out of memory
- */
- int edit_file( char *name )
- {
- int rc; /* return code */
- int existing;
- int line;
- register file_infos *file; /* file structure for file belonging to new window */
- file_infos *fp;
- text_ptr next; /* text pointer */
- long size;
-
- rc = OK;
- line = g_display.nlines;
- if (hw_fattrib( name ) == OK) {
- existing = TRUE;
- /*
- * g_status.temp_end is set last character read in file
- */
- rc = load_file( name );
- } else {
- if (ceh.flag == ERROR)
- rc = ERROR;
- else {
- existing = FALSE;
- g_status.temp_end = cpf( g_status.end_mem );
- }
- }
-
- if (rc != ERROR) {
- /*
- * allocate a file structure for the new file
- */
- file = (file_infos *)calloc( 1, sizeof(file_infos) );
- if (file == NULL) {
- error( WARNING, g_display.nlines, "out of memory for file info" );
- rc = ERROR;
- } else {
- /*
- * add file into list
- */
- file->prev = NULL;
- file->next = NULL;
- if (g_status.file_list == NULL)
- g_status.file_list = file;
- else {
- fp = g_status.current_file;
- file->prev = fp;
- if (fp->next)
- fp->next->prev = file;
- file->next = fp->next;
- fp->next = file;
- }
- }
- if (rc != ERROR) {
- /*
- * set up all the info we need to know about a file, and
- * record that we have used some more memory.
- */
- strcpy( file->file_name, name );
- get_fattr( name, &file->file_attrib );
- file->start_text = g_status.end_mem;
- *g_status.temp_end = CONTROL_Z;
- g_status.temp_end = cpf( g_status.temp_end );
- g_status.end_mem = g_status.temp_end + 1;
- g_status.temp_end = g_status.end_mem;
- file->end_text = g_status.end_mem;
- size = 0l;
- if (existing) {
- next = file->start_text = cpf( file->start_text );
- while ((next = find_next( next )) != NULL)
- size++;
- }
- file->length = size;
- file->block_type = NOTMARKED;
- file->block_end = file->block_start = NULL;
- file->block_br = file->block_er = 0l;
- file->block_bc = file->block_ec = 0;
- file->ref_count = 0;
- file->modified = FALSE;
- file->backed_up = FALSE;
- file->new_file = !existing;
- file->next_letter = 'a';
- file->file_no = ++g_status.file_count;
- g_status.current_file = file;
- make_backup_fname( file );
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: edit_another_file
- * Purpose: Bring in another file to editor.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: New window replaces old window. Old window becomes invisible.
- */
- void edit_another_file( WINDOW *window )
- {
- char fname[MAX_COLS]; /* new name for file */
- register WINDOW *win; /* put window pointer in a register */
-
- win = window;
- un_copy_line( win->cursor, win, TRUE );
- /*
- * read in name, no default
- */
- fname[0] = '\0';
- if (get_name( "File to edit: ", win->bottom_line, fname,
- g_display.message_color ) == OK)
- attempt_edit_display( fname, LOCAL );
- }
-
-
- /*
- * Name: edit_next_file
- * Purpose: edit next file on command line.
- * Date: January 6, 1992
- * Passed: window: information allowing access to the current window
- * Notes: New window replaces old window. Old window becomes invisible.
- */
- int edit_next_file( WINDOW *window )
- {
- char name[MAX_COLS]; /* new name for file */
- int i;
- int update_type;
- register int rc = ERROR;
- register WINDOW *win; /* put window pointer in a register */
-
- win = window;
- update_type = win == NULL ? GLOBAL : LOCAL;
- if (g_status.arg < g_status.argc) {
- if (win != NULL)
- un_copy_line( win->cursor, win, TRUE );
-
- /*
- * while we haven't found a valid file, search thru the command
- * line path.
- * we may have an invalid file name when we finish matching all
- * files according to a pattern. then, we need to go to the next
- * command line argument if it exists.
- */
- while (rc == ERROR && g_status.arg < g_status.argc) {
-
- /*
- * if we haven't starting searching for a file, check to see if
- * the file is a valid file name. if no file is found, then let's
- * see if we can find according to a search pattern.
- */
- if (g_status.found_first == FALSE) {
- strcpy( name, g_status.argv[g_status.arg] );
- rc = get_fattr( name, &i );
-
- /*
- * a new or blank file generates a return code of 2.
- * a pattern with wild cards generates a return code of 3.
- */
- if (rc == OK || rc == 2) {
- ++g_status.arg;
- rc = OK;
-
- /*
- * if we get this far, we got an invalid path name.
- * let's try to find a matching file name using pattern.
- */
- } else if (rc != ERROR) {
- rc = findfirst( &g_status.dta, name, NORMAL | READ_ONLY |
- HIDDEN | SYSTEM | ARCHIVE );
-
- /*
- * if we found a file using wildcard characters,
- * set the g_status.found_first flag to true so we can
- * find the next matching file. we need to save the
- * pathname stem so we know which directory we are working in.
- */
- if (rc == OK) {
- g_status.found_first = TRUE;
- i = strlen( name ) - 1;
- while (i >= 0) {
- if (name[i] == ':' || name[i] == '\\')
- break;
- --i;
- }
- name[++i] = '\0';
- strcpy( g_status.path, name );
- strcpy( name, g_status.path );
- strcat( name, g_status.dta.name );
- } else {
- ++g_status.arg;
- if (win != NULL)
- error( WARNING, win->bottom_line,
- "Invalid path or file name " );
- }
- } else if (rc == ERROR)
- ++g_status.arg;
- } else {
-
- /*
- * we already found one file with wild card characters,
- * find the next matching file.
- */
- rc = findnext( &g_status.dta );
- if (rc == OK) {
- strcpy( name, g_status.path );
- strcat( name, g_status.dta.name );
- } else {
- g_status.found_first = FALSE;
- ++g_status.arg;
- }
- }
-
- /*
- * if everything is everything so far, set up the file
- * and window structures and bring the file into the editor.
- */
- if (rc == OK)
- rc = attempt_edit_display( name, update_type );
-
- /*
- * either there are no more matching files or we had an
- * invalid file name, set rc to ERROR and let's look at the
- * next file name or pattern on the command line.
- */
- else
- rc = ERROR;
- }
- }
- if (rc == ERROR && g_status.arg >= g_status.argc && win != NULL)
- error( WARNING, win->bottom_line, "No more files to load " );
- return( rc );
- }
-
-
- /*
- * Name: attempt_edit_display
- * Purpose: try to load then display a file
- * Date: June 5, 1991
- * Passed: fname: file name to load
- * update_type: update current window or entire screen
- * Notes: When we first start the editor, we need to update the entire
- * screen. When we load in a new file, we only need to update
- * the current window.
- */
- int attempt_edit_display( char *fname, int update_type )
- {
- register int rc;
- WINDOW *win;
-
- rc = edit_file( fname );
- if (rc != ERROR) {
- rc = initialize_window( );
- if (rc != ERROR) {
- win = g_status.current_window;
- if (update_type == LOCAL) {
- redraw_current_window( win );
- show_file_count( g_status.file_count );
- show_window_count( g_status.window_count );
- show_avail_mem( );
- } else if (update_type == GLOBAL)
- redraw_screen( win );
- if (win->file_info->new_file) {
- g_status.command = AddLine;
- insert_newline( win );
- win->file_info->modified = FALSE;
- }
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: make_backup_fname
- * Purpose: add .bak to file name
- * Date: January 6, 1992
- * Passed: file: information allowing access to the current file
- */
- void make_backup_fname( file_infos *file )
- {
- char name[MAX_COLS]; /* new name for file */
- char *p;
- int i;
- int len;
-
- /*
- * if this is a new file then don't create a backup - can't backup
- * a nonexisting file.
- */
- if (file->new_file)
- file->backed_up = TRUE;
-
- /*
- * find the file name extension if it exists
- */
- else {
- strcpy( name, file->file_name );
- len = strlen( name );
- for (i=len,p=name+len; i>=0; i--) {
-
- /*
- * we found the '.' extension character. get out
- */
- if (*p == '.')
- break;
-
- /*
- * we found the drive or directory character. no extension so
- * set the pointer to the end of file name string.
- */
- else if (*p == '\\' || *p == ':') {
- p = name + len;
- break;
-
- /*
- * we're at the beginning of the string - no '.', drive, or directory
- * char was found. set the pointer to the end of file name string.
- */
- } else if (i == 0) {
- p = name + len;
- break;
- }
- --p;
- }
- strcpy( p, ".bak" );
- strcpy( file->backup_fname, name );
- }
- }
-