home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
EDITORS
/
TDE20.ZIP
/
WINDOW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-05
|
47KB
|
1,474 lines
/******************* 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
* Date: June 5, 1992, version 2.0
*
* 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) {
/*
* out of memory
*/
error( WARNING, bottom, main4 );
/*
* 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: pointer to 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.
*/
int 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 beginning of
* the list 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;
}
}
return( OK );
}
/*
* Name: prev_window
* Purpose: To move to the previous visible window.
* Date: June 5, 1991
* Passed: window: pointer to 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.
*/
int 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;
}
}
return( OK );
}
/*
* Name: split_horizontal
* Purpose: To split screen horizontally at the cursor.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: split the screen horizontally at the cursor position.
*/
int 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 */
int rc;
win = window;
/*
* check that there is room for the window
*/
if (win->bottom_line - win->cline < 2) {
/*
* move cursor up first
*/
error( WARNING, win->bottom_line, win1 );
rc = ERROR;
} else {
file = win->file_info;
if (create_window( &temp, win->cline+1, win->bottom_line,
win->start_col, win->end_col, file ) == ERROR) {
/*
* out of memory
*/
error( WARNING, win->bottom_line, main4 );
rc = ERROR;
} 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 );
rc = OK;
}
}
return( rc );
}
/*
* Name: split_vertical
* Purpose: To split screen vertically at the cursor.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: split the screen vertically at the cursor position.
*/
int 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 */
int rc;
win = window;
/*
* check that there is room for the window
*/
if (win->start_col + 15 > win->ccol) {
/*
* move cursor right first
*/
error( WARNING, win->bottom_line, win2 );
rc = ERROR;
} else if (win->end_col - 15 < win->ccol) {
/*
* move cursor left first
*/
error( WARNING, win->bottom_line, win3 );
rc = ERROR;
} else {
file = win->file_info;
if (create_window( &temp, win->top_line-1, win->bottom_line,
win->ccol+1, win->end_col, file ) == ERROR) {
/*
* out of memory
*/
error( WARNING, win->bottom_line, main4 );
rc = ERROR;
} 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 );
rc = OK;
}
}
return( rc );
}
/*
* Name: show_vertical_separator
* Purpose: To separate vertical screens
* Date: June 5, 1991
* Passed: window: pointer to 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: pointer to 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.
*/
int 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;
int old_bottom_line;
int old_top_line;
int new_bottom_line;
int new_top_line;
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 );
/*
* press up or down to change window size
*/
set_prompt( win4, 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)
/*
* cannot resize vertical window
*/
error( WARNING, win->bottom_line, win5 );
else {
old_top_line = win->top_line;
old_bottom_line = above->bottom_line;
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 );
/*
* press up or down to change window size
*/
set_prompt( win4, win->bottom_line );
}
}
new_top_line = win->top_line;
new_bottom_line = above->bottom_line;
for (above=g_status.window_list; above != NULL; above=above->next) {
if (!above->visible) {
if (above->bottom_line == old_bottom_line) {
above->bottom_line = new_bottom_line;
if (above->cline < new_bottom_line)
above->cline = new_bottom_line;
setup_window( above );
} else if (above->top_line == old_top_line) {
above->top_line = new_top_line;
if (above->cline < new_top_line)
above->cline = new_top_line;
if ((long)(above->cline+1L - (above->top_line+above->ruler)) >
above->rline)
above->cline = (int)above->rline + above->top_line +
above->ruler - 1;
setup_window( above );
}
}
}
}
restore_screen_line( 0, win->bottom_line, line_buff );
} else {
if (win->vertical)
/*
* cannot resize vertical window
*/
error( WARNING, win->bottom_line, win5 );
else
/*
* cannot resize top window
*/
error( WARNING, win->bottom_line, win6 );
}
return( OK );
}
/*
* Name: zoom_window
* Purpose: To blow-up current window.
* Date: September 1, 1991
* Passed: window: pointer to current window
* Notes: Make all windows, visible and hidden, full size.
*/
int zoom_window( WINDOW *window )
{
register WINDOW *wp;
if (window != NULL) {
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 );
}
return( OK );
}
/*
* Name: next_hidden_window
* Purpose: To display the window that is "behind" current window.
* Date: September 1, 1991
* Passed: window: pointer to current window
*/
int 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->top_line + wp->ruler)
wp->cline = wp->top_line + wp->ruler;
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->top_line + wp->ruler - 1;
wp->visible = TRUE;
window->visible = FALSE;
g_status.current_window = wp;
redraw_current_window( wp );
make_ruler( wp );
show_ruler( wp );
}
}
return( OK );
}
/*
* 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: pointer to 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) window above if it exists becomes current window
* 3) window below if it exists becomes current window
* 4) window right if it exists becomes current window
* 5) window left if it exists becomes current window
* 6) first available invisible window 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 │
* │ ├─────┬────┤
* │ │yes1 │yes1│
* │ no ├─────┴────┤
* │ │ 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 );
file = win->file_info;
/*
* 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;
}
}
}
if (win->prev == NULL && win->next == NULL)
g_status.stop = TRUE;
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 == top && wp->bottom_line == bottom &&
wp->start_col == start_col && wp->end_col == end_col &&
!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 && wp->visible) {
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 && wp->visible) {
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 && wp->visible) {
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 && wp->visible) {
poof = TRUE;
start_col = wp->start_col;
} else
wp = wp->next;
}
}
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) {
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)
/*
* cannot close current window
*/
error( WARNING, win->bottom_line, win7 );
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) {
/*
* out of memory
*/
error( WARNING, g_display.nlines, main4 );
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) {
/*
* out of memory
*/
error( WARNING, g_display.nlines, main4 );
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: pointer to current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
int edit_another_file( WINDOW *window )
{
char fname[MAX_COLS]; /* new name for file */
register WINDOW *win; /* put window pointer in a register */
int rc;
win = window;
un_copy_line( win->cursor, win, TRUE );
/*
* read in name, no default
*/
fname[0] = '\0';
/*
* file name to edit
*/
if ((rc = get_name( ed15, win->bottom_line, fname,
g_display.message_color )) == OK)
rc = attempt_edit_display( fname, LOCAL );
return( rc );
}
/*
* Name: edit_next_file
* Purpose: edit next file on command line.
* Date: January 6, 1992
* Passed: window: pointer to 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)
/*
* invalid path or file name
*/
error( WARNING, win->bottom_line, win8 );
}
} 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)
/*
* no more files to load
*/
error( WARNING, win->bottom_line, win9 );
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 );
}
}