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.
- *
- * New editor name: tde, the Thomson-Davis Editor.
- * Author: Frank Davis
- * Date: June 5, 1991
- *
- * 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"
- #if defined( __MSC__ )
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
-
-
- /*
- * 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;
- windows *wp; /* used for scanning windows */
- windows *window;
- register file_infos *fp; /* used for scanning files */
- 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 = 0;
- bottom = g_display.nlines;
- } 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;
- }
-
- if (create_window( &wp, top, bottom, 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 );
- }
- rc = ERROR;
- }
-
- if (rc != ERROR) {
- /*
- * set up the new cursor position as appropriate
- */
- wp->cursor = cpf( fp->start_text );
- wp->ccol = 0;
- wp->rcol = 0;
- wp->bcol = 0;
- wp->rline = 1l;
- wp->visible = TRUE;
- wp->letter = fp->next_window_letter;
- ++fp->next_window_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 select an existing window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Start with current window. If next window exits then go to
- * it else go to the first (top) window on screen.
- */
- void next_window( windows *window )
- {
- int change;
- register windows *wp;
-
- if (window != NULL) {
- change = FALSE;
- wp = g_status.window_list;
- if (wp->next != NULL) {
- while (wp != NULL && (wp->top_line-2 != window->bottom_line ||
- !wp->visible))
- wp = wp->next;
- if (wp != NULL)
- change = TRUE;
- }
- if (change != TRUE) {
- wp = g_status.window_list;
- while (wp != NULL && (wp->top_line != 1 || !wp->visible))
- wp = wp->next;
- if (wp != NULL && wp != window)
- change = TRUE;
- }
- 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 select an existing window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Start with current window. If previous window exits then go to
- * it else go to the last (bottom) window on screen. Opposite of
- * next_window.
- */
- void prev_window( windows *window )
- {
- int change;
- register windows *wp;
-
- if (window != NULL) {
- change = FALSE;
- wp = g_status.window_list;
- if (wp->next != NULL) {
- while (wp != NULL && (wp->bottom_line+2 != window->top_line ||
- !wp->visible))
- wp = wp->next;
- if (wp != NULL)
- change = TRUE;
- }
- if (change != TRUE) {
- wp = g_status.window_list;
- while (wp != NULL && (wp->bottom_line != g_display.nlines ||
- !wp->visible))
- wp = wp->next;
- if (wp != NULL && wp != window)
- change = TRUE;
- }
-
- if (change == TRUE) {
- un_copy_line( window->cursor, window, TRUE );
- g_status.current_window = wp;
- g_status.current_file = wp->file_info;
- }
- }
- }
-
-
- /*
- * Name: split_screen
- * Purpose: To split screen.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: split the screen at the cursor position.
- */
- void split_screen( windows *window )
- {
- register windows *wp;
- windows *temp;
- file_infos *file; /* file structure for file belonging to new window */
- int prompt_line;
-
- prompt_line = window->bottom_line;
- /*
- * check that there is room for the window
- */
- if (window->bottom_line - window->cline < 2)
- error( WARNING, prompt_line, "move cursor up first" );
- else {
- file = window->file_info;
- if (create_window( &temp, window->cline+1, window->bottom_line,
- file ) == ERROR) {
- error( WARNING, prompt_line, "out of memory" );
- } else {
- 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.
- */
- window->bottom_line = window->cline;
- setup_window( window );
- display_current_window( window );
-
- /*
- * set up the new cursor position as appropriate
- */
- wp->rcol = window->rcol;
- wp->ccol = window->ccol;
- wp->bcol = window->bcol;
- wp->rline = window->rline;
- wp->cursor = window->cursor;
- wp->visible = TRUE;
- wp->letter = file->next_window_letter;
- ++file->next_window_letter;
-
- /*
- * the new window becomes the current window.
- */
- g_status.current_window = wp;
-
- show_window_header( wp->file_info->file_name, wp );
- show_size_name( wp );
- show_size( wp );
- display_current_window( wp );
-
- /*
- * adjust any invisible windows
- */
- wp = g_status.window_list;
- while (wp != NULL) {
- if (wp != window ) {
- if (wp->top_line == window->top_line) {
- wp->bottom_line = window->bottom_line;
- setup_window( wp );
- /*
- * reset cline to some place safe
- */
- wp->cline = wp->top_line;
- }
- }
- wp = wp->next;
- }
- }
- }
- }
-
-
- /*
- * 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, if it exists, will
- * either grow or contract accordingly.
- */
- void size_window( windows *window )
- {
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- int func, c, above_change;
- register windows *n;
- windows *above;
- text_ptr p;
- int prompt_line;
- int resize;
- char *file_name;
- char *instr =
- "Press Up or Down to change window size. Press Return when done.";
-
- if (window->top_line != 1) {
- above_change = 0;
- file_name = window->file_info->file_name;
- prompt_line = window->bottom_line;
- save_screen_line( 0, prompt_line, line_buff );
- set_prompt( instr, prompt_line );
-
- /*
- * resizing only affects current window and above visible window
- */
- above = g_status.window_list;
- while (above->bottom_line + 2 != window->top_line || !above->visible)
- above = above->next;
- 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 line up 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) {
- if (window->rline == (window->cline - (window->top_line-1)))
- --window->cline;
- --window->top_line;
- if (above->cline == above->bottom_line) {
- above->cursor = cpb( above->cursor );
- above->cursor = find_prev( above->cursor );
- --above->rline;
- --above->cline;
- show_line_col( above );
- --above_change;
- }
- --above->bottom_line;
- resize = TRUE;
- display_current_window( window );
- save_screen_line( 0, prompt_line, line_buff );
- }
-
- /*
- * if line down 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 (window->bottom_line > window->top_line) {
- if (window->cline == window->top_line) {
- ++window->cline;
- window->cursor = cpf( window->cursor );
- p = find_next( window->cursor );
- if (p != NULL) {
- window->cursor = p;
- ++window->rline;
- }
- }
- ++window->top_line;
- ++above->bottom_line;
- display_current_window( above );
- ++above_change;
- resize = TRUE;
- }
- }
-
- /*
- * if we resize a window then update window size and current and
- * real lines if needed.
- */
- if (resize == TRUE) {
- setup_window( above );
- setup_window( window );
- show_window_header( file_name, window );
- show_size_name( window );
- show_size( window );
- show_line_col( window );
- set_prompt( instr, prompt_line );
- }
- }
- restore_screen_line( 0, prompt_line, line_buff );
- if (above_change != 0) {
- n = g_status.window_list;
- while (n != NULL) {
- /*
- * check all invisible windows - make sure they have
- * correct top and bottom lines.
- */
- if (n != above && n != window ) {
- if (n->top_line == above->top_line) {
- n->bottom_line = above->bottom_line;
- setup_window( n );
- if (n->cline > n->bottom_line)
- n->cline = n->bottom_line;
- } else if (n->bottom_line == window->bottom_line) {
- n->top_line = window->top_line;
- setup_window( n );
- if (n->cline < n->top_line)
- n->cline = n->top_line;
- }
- }
- n = n->next;
- }
- }
- } else
- error( WARNING, window->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( windows *window )
- {
- register windows *wp;
-
- if (window != NULL) {
- if (window->top_line != 1 || window->bottom_line != g_display.nlines) {
- 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 + 1;
- wp->top_line = 1;
- wp->bottom_line = g_display.nlines;
- }
- redraw_screen( 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
- * Notes: Make all windows, visible and hidden, full size.
- */
- void next_hidden_window( windows *window )
- {
- int found = FALSE;
- register windows *wp;
-
- if (window != NULL) {
- wp = window;
- for (wp=window->next; wp != NULL && !found; ) {
- if (!wp->visible)
- found = TRUE;
- else
- wp = wp->next;
- }
- if (!found) {
- for (wp=g_status.window_list; wp != NULL && !found; ) {
- if (!wp->visible)
- found = TRUE;
- else
- wp = wp->next;
- }
- }
- if (found) {
- wp->cline = window->top_line + (wp->cline - wp->top_line);
- wp->top_line = window->top_line;
- wp->bottom_line = window->bottom_line;
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->bottom_line;
- if ((wp->cline+1 - wp->top_line) > wp->rline)
- wp->cline = (int)wp->rline;
- wp->visible = TRUE;
- window->visible = FALSE;
- g_status.current_window = wp;
- redraw_current_window( 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( windows *window )
- {
- window->page = window->bottom_line - window->top_line -
- 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 windows with same top and bottom line 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
- */
- void finish( windows *window )
- {
- register windows *wp; /* for scanning other windows */
- file_infos *file; /* for scanning other files */
- long number; /* number of bytes removed / copied */
- int poof;
- int cline;
- int top, bottom;
-
- un_copy_line( window->cursor, window, TRUE );
- /*
- * remove old window from list
- */
- top = 1;
- bottom = g_display.nlines;
- if (window->prev == NULL) {
- if (window->next == NULL)
- g_status.stop = TRUE;
- else
- g_status.window_list = window->next;
- } else
- window->prev->next = window->next;
-
-
- /*
- * remove all hidden windows that point to same file
- */
- if (g_status.stop != TRUE) {
- if (window->next)
- window->next->prev = window->prev;
- for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
- if (!wp->visible && wp->file_info == window->file_info) {
- 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;
- }
- }
- show_file_count( g_status.file_count );
- }
-
- if (g_status.stop != TRUE) {
- /*
- * see if there are any invisible windows with same top and bottom
- * lines as this window.
- */
- poof = FALSE;
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (wp->top_line == window->top_line && !wp->visible) {
- poof = TRUE;
- top = window->top_line;
- bottom = window->bottom_line;
- } else
- wp = wp->next;
- }
-
- if (poof == FALSE) {
- /*
- * see if there are any other invisible windows
- */
- wp = g_status.window_list;
- while (wp != NULL && poof == FALSE) {
- if (!wp->visible) {
- poof = TRUE;
- top = window->top_line;
- bottom = window->bottom_line;
- } else
- wp = wp->next;
- }
- 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 == window->top_line) {
- poof = TRUE;
- top = wp->top_line;
- bottom = window->bottom_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 == window->bottom_line) {
- poof = TRUE;
- top = window->top_line;
- bottom = wp->bottom_line;
- } else
- wp = wp->next;
- }
- if (wp == NULL)
- wp = g_status.window_list;
- }
- }
- wp->visible = TRUE;
- cline = wp->cline - wp->top_line;
- wp->top_line = top;
- wp->bottom_line = bottom;
- wp->cline = wp->top_line + cline;
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->top_line;
- setup_window( wp );
- show_window_header( wp->file_info->file_name, wp );
- show_size_name( wp );
- show_size( wp );
- show_line_col( wp );
-
- /*
- * The window above, below, or previously invisible becomes the new
- * current window.
- */
- g_status.current_window = wp;
-
- /*
- * free unused file memory if necessary
- */
- file = window->file_info;
- if (--file->ref_count == 0) {
- /*
- * 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( window, -number );
- adjust_start_end( file, -number );
- show_avail_mem( );
-
- /*
- * free the memory taken by the file structure
- */
- free( file );
- --g_status.file_count;
- show_file_count( g_status.file_count );
- }
-
- /*
- * free the memory taken by the window structure
- */
- free( window );
- --g_status.window_count;
- g_status.current_file = wp->file_info;
- wp->file_info->dirty = LOCAL;
- show_window_count( g_status.window_count );
- }
- }
-
-
- /*
- * 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( windows **window, int top, int bottom, file_infos *file )
- {
- windows *wp; /* temporary variable - use it instead of **window */
- windows *prev;
- int rc; /* return code */
-
- rc = OK;
- /*
- * allocate space for new window structure
- */
- if ((*window = (windows *)calloc( 1, sizeof(windows) )) == 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->cline = wp->top_line = top+1;
- wp->bottom_line = bottom;
- 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;
- show_window_count( 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;
- struct stat filestat; /* struct stat defined in \sys\stat */
-
- rc = OK;
- line = g_display.nlines;
- if (hw_fattrib( name ) != ERROR) {
- existing = TRUE;
- /*
- * g_status.temp_end is set last character read in file
- */
- rc = load_file( name );
- } else {
- /*
- * setup as empty file - make an empty file have a linefeed
- */
- 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 );
- stat( name, &filestat );
- file->file_attrib = filestat.st_mode;
- 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_end = file->block_start = NULL;
- file->block_bc = file->block_ec = 0;
- file->block_br = file->block_er = 0l;
- file->block_type = NOTMARKED;
- file->modified = FALSE;
- file->file_no = g_status.next_file_number++;
- file->next_window_letter = 'a';
- }
- }
- if (rc != ERROR && !existing)
- file->new_file = TRUE;
- else if (rc != ERROR && existing)
- file->new_file = FALSE;
- if (rc != ERROR) {
- g_status.current_file = file;
- file->ref_count = 0;
- ++g_status.file_count;
- }
- 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( windows *window )
- {
- char name[MAX_COLS]; /* new name for file */
- int prompt_line;
- int ok;
-
- un_copy_line( window->cursor, window, TRUE );
- /*
- * read in name, no default
- */
- prompt_line = window->bottom_line;
- name[0] = '\0';
- if (get_name( "File to edit: ", prompt_line, name,
- g_display.message_color ) == OK) {
- ok = edit_file( name );
- if (ok != ERROR) {
- ok = initialize_window( );
- if (ok != ERROR) {
- window = g_status.current_window;
- show_window_header( window->file_info->file_name, window );
- show_size_name( window );
- show_size( window );
- show_file_count( g_status.file_count );
- show_avail_mem( );
- window->file_info->dirty = LOCAL;
- }
- }
- }
- }
-