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 - miscellaneous utilities
- * Purpose: This file contains miscellaneous functions that were required
- * in more than one of the other files, or were thought to be
- * likely to be used elsewhere in the future.
- * File: utils.c
- * Author: Douglas Thomson
- * System: this file is intended to be system-independent
- * Date: October 1, 1989
- */
- /********************* end of original comments ********************/
-
-
- /*
- * The utility routines have been EXTENSIVELY rewritten. Update screens as
- * needed. Most times, only one line has changed. Just show changed line
- * in all windows if it is on screen.
- *
- * Support routines for text lines longer than screen width have been added.
- * Currently support lines as long as 255 bytes. If longer lines are needed,
- * the assembly routines need to be modified since they use bytes (a byte
- * goes from 255 to 0, unsigned).
- *
- * 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"
- #ifdef __TURBOC__
- #include <dir.h> /* for making temporary file names etc */
- #endif
- #if defined( __MSC__ )
- #include <dos.h>
- #include <io.h>
- #endif
-
-
- /*
- * Name: myisalnum
- * Purpose: To determine whether or not a character is part of a "word",
- * which in languages like Pascal means a letter, digit or
- * underscore.
- * Date: October 1, 1989
- * Passed: c: the character to be tested
- * Returns: TRUE if c is an alphanumeric or '_' character, FALSE otherwise
- */
- int myisalnum( int c )
- {
- register int rc;
-
- rc = FALSE;
- if (isalnum( c ) || (c == '_'))
- rc = TRUE;
- return( rc );
- }
-
-
- /*
- * Name: check_virtual_col
- * Purpose: make sure real column is displayed on screen
- * Date: June 5, 1991
- * Passed: window: current window
- * rcol: real column of cursor
- * ccol: current or logical column of cursor
- */
- void check_virtual_col( windows *window, int rcol, int ccol )
- {
- register int bcol;
- int ncols;
- file_infos *file;
-
- file = window->file_info;
- bcol = window->bcol;
- ncols = g_display.ncols - 1;
-
- /*
- * is logical column past end of screen?
- */
- if (ccol > ncols) {
- ccol = ccol - bcol;
- if (ccol > ncols) {
- ccol = ncols;
- bcol = rcol - ccol;
- file->dirty = LOCAL;
- }
-
- /*
- * is logical column behind start of screen?
- */
- } else if (ccol < 0) {
- if (bcol >= -ccol)
- bcol += ccol;
- ccol = 0;
- file->dirty = LOCAL;
-
- /*
- * is current column < base column?
- */
- } else if (rcol < bcol) {
- ccol = rcol;
- bcol = 0;
- if (ccol > ncols) {
- bcol = rcol - ncols;
- ccol = rcol - bcol;
- }
- file->dirty = LOCAL;
- }
-
- /*
- * current column + base column MUST equal real column
- */
- if (ccol + bcol != rcol) {
- if (bcol < 0) {
- bcol = rcol;
- file->dirty = LOCAL;
- }
- ccol = rcol - bcol;
- if (ccol > ncols) {
- bcol = rcol - ncols;
- ccol = rcol - bcol;
- file->dirty = LOCAL;
- }
- }
- if (rcol < 0) {
- rcol = bcol = ccol = 0;
- file->dirty = LOCAL;
- }
-
- window->bcol = bcol;
- window->ccol = ccol;
- window->rcol = rcol;
- }
-
-
- /*
- * Name: copy_line
- * Purpose: To copy the cursor line, if necessary, into the current line
- * buffer, so that changes can be made efficiently.
- * Date: June 5, 1991
- * Passed: text_line: line to be copied to line buffer
- * line: line to display error message
- * Notes: See un_copy_line, the reverse operation. Terminate text strings
- * with CONTROL_Z. DO NOT use the C library string functions on
- * text in g_status.line_buff.
- */
- void copy_line( text_ptr text_line, int line )
- {
- char *d; /* destination of copy */
- text_ptr s; /* source of copy */
- register int len;
-
- if (g_status.copied == FALSE) {
- g_status.copied = TRUE;
- /*
- * copy the cursor line to the line buffer
- */
- d = g_status.line_buff;
- g_status.buff_line = text_line;
- s = cpf( text_line );
- len = linelen( s );
- if (s[len] == '\n')
- ++len;
- if (len >= g_display.line_length) {
- len = g_display.line_length;
- error( WARNING, line, "line buffer overflow - line truncated!" );
- }
- _fmemcpy( d, s, len );
- d[len] = CONTROL_Z;
- }
- }
-
-
- /*
- * Name: un_copy_line
- * Purpose: To copy the cursor line, if necessary, from the current line
- * buffer, shifting the main text to make the right amount of
- * room.
- * Date: June 5, 1991
- * Passed: test_line: pointer to location in file to copy line buffer
- * window: pointer to current window info
- * del_trailing: delete the trailing blanks at eol? TRUE or FALSE
- * Notes: For some functions, trailing spaces should not be removed when
- * returning the line buffer to the main text. The JoinLine function
- * is a good example. We need to leave trailing space so when we
- * join lines - the current line will extend at least up to
- * the column of the cursor. We allow need to leave trailing space
- * during BOX block operations.
- * See copy_line, the reverse operation.
- */
- void un_copy_line( text_ptr text_line, windows *window, int del_trailing )
- {
- char *source; /* source for block move and for copying buffer line */
- text_ptr dest; /* destination for block move and copy */
- text_ptr p;
- long number; /* length of block move */
- int space;
- int len; /* length of current line buffer text */
- int curs_len; /* length of cursor line */
- int prompt_line;
- int i;
- file_infos *file;
-
- if (g_status.copied == TRUE) {
- /*
- * work out the lengths of the old cursor line (including the \n if any)
- * and the new current line buffer text.
- */
- prompt_line = window->bottom_line;
- text_line = cpf( text_line );
- curs_len = linelen( text_line );
- if (text_line[curs_len] == '\n')
- ++curs_len;
- if (del_trailing) {
- len = linelen( g_status.line_buff );
- i = find_CONTROL_Z( g_status.line_buff ) + 1;
- i -= len;
- for (source=g_status.line_buff+len-1; len > 0; len--, source--) {
- if (*source == ' ')
- memmove( source, source+1, i );
- else
- break;
- }
- }
- len = find_CONTROL_Z( g_status.line_buff );
- space = len - curs_len;
-
- /*
- * if the main text buffer has run out of space, then only part of the
- * current line can be moved back into the main buffer. Warn the user
- * that some of the current line has been lost
- */
- if (ptoul( g_status.end_mem ) + (long)space >= ptoul( g_status.max_mem )) {
- error( WARNING, prompt_line, "buffer full, part line truncated" );
- len = curs_len + (int) (ptoul( g_status.max_mem ) -
- ptoul( g_status.end_mem ));
- }
-
- /*
- * move text to either make room for the extra characters in the new
- * line, or else close up the gap.
- */
- p = text_line + curs_len;
- dest = addltop( (long)space, p );
- number = ptoul( g_status.end_mem ) - ptoul( p );
- hw_move( dest, p, number );
- g_status.end_mem = addltop( (long)space, g_status.end_mem );
-
- /*
- * now copy the line buffer into the space just created
- */
- _fmemcpy( text_line, g_status.line_buff, len );
- g_status.copied = FALSE;
- file = window->file_info;
- file->modified = TRUE;
- adjust_start_end( file, space );
- addorsub_all_cursors( window, space );
- show_avail_mem( );
- }
- }
-
-
- /*
- * Name: load_undo_buffer
- * Purpose: To copy the cursor line to the undo buffer.
- * Date: September 26, 1991
- * Passed: undo_line: pointer to location in file to copy to undo buffer
- * Notes: save the last UNDO_MAX changed lines. save the lines in a stack.
- * when we overflow the stack, dump the oldest line. don't worry
- * about which file the line comes from - just load the stack.
- */
- void load_undo_buffer( text_ptr line_to_undo )
- {
- register char *s; /* char pointer to stack */
- char *d;
- int top; /* top of stack */
- int len;
-
- if (g_status.undo_head < 0)
- g_status.undo_head = 0;
- else if (g_status.undo_head == UNDO_MAX) {
- d = (char *)g_status.undo_buffer;
- s = d + BUFF_SIZE;
- memmove( d, s, (UNDO_MAX * BUFF_SIZE) - BUFF_SIZE );
- }
- len = linelen( line_to_undo );
- if (line_to_undo[len] == '\n')
- ++len;
- top = g_status.undo_head;
- if (top == UNDO_MAX)
- --top;
- s = &g_status.undo_buffer[top][0];
- hw_move( s, line_to_undo, len );
- if (s[len-1] != '\n')
- s[len++] = '\n';
- s[len] = CONTROL_Z;
- if (g_status.undo_head < UNDO_MAX)
- ++g_status.undo_head;
- }
-
-
- /*
- * Name: load_file
- * Purpose: To read in a given file to the end of the main text buffer.
- * Date: June 5, 1991
- * Passed: name: path name of file to be read
- * Returns: OK if file read successfully
- * ERROR if any problem (such as out of buffer space)
- */
- int load_file( char *name )
- {
- int rc;
-
- /*
- * make sure this gets set properly even if there is no file!
- */
- g_status.temp_end = g_status.end_mem;
-
- rc = hw_load( name, g_status.end_mem, g_status.max_mem,
- &g_status.temp_end, g_display.nlines );
- return( rc );
- }
-
- /*
- * Name: set_prompt
- * Purpose: To display a prompt, highlighted, at the bottom of the screen.
- * Date: October 1, 1989
- * Passed: prompt: prompt to be displayed
- * line: line on which to display prompt
- */
- void set_prompt( char *prompt, int line )
- {
- int prompt_col;
-
- /*
- * work out where the answer should go
- */
- prompt_col = strlen( prompt );
-
- /*
- * output the prompt
- */
- s_output( prompt, line, 0, g_display.message_color );
- eol_clear( prompt_col, line, g_display.message_color );
-
- /*
- * ensure the cursor is in the right place
- */
- xygoto( prompt_col, line );
- }
-
- /*
- * Name: get_name
- * Purpose: To prompt the user, and read the string the user enters in
- * response.
- * Date: October 1, 1989
- * Passed: prompt: prompt to offer the user
- * line: no. of lines up from the bottom of the screen
- * name: default answer
- * color: color to display prompt
- * Returns: name: user's answer
- * OK if user entered something
- * ERROR if user aborted the command
- * Notes: Editing of the line is supported.
- */
- int get_name( char *prompt, int line, char *name, int color )
- {
- int col; /* cursor column for answer */
- int c; /* character user just typed */
- char *cp; /* cursor position in answer */
- char *answer; /* user's answer */
- int first = TRUE; /* first character typed */
- register int len; /* length of answer */
- int plen; /* length of prompt */
- int func; /* function of key pressed */
- int stop; /* flag to stop getting characters */
- char *p; /* for copying text in answer */
- char buffer[MAX_COLS+2];/* line on which name is being entered */
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- int normal;
-
- /*
- * set up prompt and default
- */
- strcpy( buffer, prompt );
- plen = strlen( prompt );
- answer = buffer + plen;
- strcpy( answer, name );
-
- /*
- * let user edit default into desired string
- */
- len = strlen( answer );
- col = strlen( buffer );
- g_status.prompt_line = line;
- g_status.prompt_col = col;
- cp = answer + len;
- normal = g_display.text_color;
- save_screen_line( 0, line, line_buff );
- s_output( buffer, line, 0, color );
- eol_clear( col, line, normal );
- for (stop = FALSE; stop == FALSE;) {
- xygoto( col, line );
- c = getkey( );
- func = getfunc( c );
-
- /*
- * User may have redefined the Enter and ESC keys. Make the Enter key
- * perform a Rturn in this function. Make the ESC key do an AbortCommand.
- */
- if (c == RTURN)
- func = Rturn;
- else if (c == ESC)
- func = AbortCommand;
- switch (func) {
- case ToggleSearchCase :
- if (bm.search_case == IGNORE)
- bm.search_case = MATCH;
- else
- bm.search_case = IGNORE;
- show_search_case( );
- break;
- case Rturn :
- case NextLine :
- case BegNextLine :
- answer[len] = '\0';
- strcpy( name, answer );
- /*
- * finished
- */
- stop = TRUE;
- break;
- case BackSpace :
- /*
- * delete to left of cursor
- */
- if (cp > answer) {
- for (p=cp-1; p < answer+len; p++) {
- *p = *(p+1);
- }
- --len;
- --col;
- --cp;
- c_output( ' ', plen+len, line, normal);
- s_output( cp, line, col, color );
- *(answer + len) = '\0';
- }
- break;
- case DeleteChar :
- /*
- * delete char under cursor
- */
- if (*cp) {
- for (p=cp; p < answer+len; p++) {
- *p = *(p+1);
- }
- --len;
- c_output( ' ', plen+len, line, normal);
- s_output( cp, line, col, color );
- *(answer + len) = '\0';
- }
- break;
- case DeleteLine :
- /*
- * delete current line
- */
- col = plen;
- cp = answer;
- *cp = '\0';
- len = 0;
- eol_clear( col, line, normal );
- break;
- case AbortCommand :
- stop = TRUE;
- break;
- case CharLeft :
- /*
- * move cursor left
- */
- if (cp > answer) {
- col--;
- cp--;
- }
- break;
- case CharRight :
- /*
- * move cursor right
- */
- if (*cp) {
- col++;
- cp++;
- }
- break;
- case BegOfLine :
- /*
- * move cursor to start of line
- */
- col = plen;
- cp = answer;
- break;
- case EndOfLine :
- /*
- * move cursor to end of line
- */
- col = plen + len;
- cp = answer + len;
- break;
- default :
- if (c < 0x100) {
- /*
- * insert character at cursor
- */
- if (first) {
- /*
- * delete previous answer
- */
- col = plen;
- cp = answer;
- *cp = '\0';
- len = 0;
- eol_clear( col, line, normal );
- }
-
- /*
- * insert new character
- */
- if (col < g_display.ncols-1) {
- if (*cp == '\0') {
- ++len;
- *(answer + len) = '\0';
- }
- *cp = c;
- c_output( c, col, line, color );
- ++cp;
- ++col;
- }
- }
- break;
- }
- first = FALSE;
- }
- restore_screen_line( 0, line, line_buff );
- if (func == AbortCommand)
- c = ERROR;
- else
- c = OK;
- return( c );
- }
-
-
- /*
- * Name: get_yn
- * Purpose: To input a response of yes or no.
- * Date: October 1, 1989
- * Returns: the user's answer (A_??? - see tdestr.h)
- */
- int get_yn( void )
- {
- int c; /* the user's response */
- register int rc; /* return code */
-
- for (rc=-1; rc<0;) {
- c = getkey( );
- if (getfunc( c ) == AbortCommand || c == ESC)
- rc = A_ABORT;
- else {
- switch ( c ) {
- case 'Y':
- case 'y':
- rc = A_YES;
- break;
- case 'N':
- case 'n':
- rc = A_NO;
- break;
- }
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: get_oa
- * Purpose: To input a response of overwrite or append.
- * Date: October 1, 1989
- * Returns: the user's answer (A_??? - see tdestr.h)
- */
- int get_oa( void )
- {
- int c; /* the user's response */
- int rc; /* return code */
- register int func;
-
- rc = 0;
- while (rc != AbortCommand && rc != A_OVERWRITE && rc != A_APPEND) {
- c = getkey( );
- func = getfunc( c );
- if (func == AbortCommand || c == ESC)
- rc = AbortCommand;
- switch ( c ) {
- case 'O':
- case 'o':
- rc = A_OVERWRITE;
- break;
- case 'A':
- case 'a':
- rc = A_APPEND;
- break;
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: show_eof
- * Purpose: display eof message
- * Date: September 16, 1991
- * Passed: line: line to display "<=== eof ===>"
- */
- void show_eof( int line )
- {
- register int color;
-
- color = g_display.eof_color;
- eol_clear( 0, line, color );
- s_output( mode.eof, line, 0, color );
- }
-
- /*
- * Name: display_current_window
- * Purpose: display text in current window
- * Date: June 5, 1991
- * Passed: window: current window
- * Notes: use a temporary window structure, "w", to do the dirty work.
- */
- void display_current_window( windows *window )
- {
- text_ptr p; /* successive lines above the cursor */
- int count; /* number of lines updated so far */
- int number; /* number of lines visible in window */
- int i;
- windows w;
- long length;
-
- /*
- * work out how many lines need to be displayed
- */
- number = window->bottom_line - (window->top_line - 1);
-
- /*
- * display the required number of lines, starting from the
- * cursor line
- */
- dup_window_info( &w, window );
- w.cursor = cpb( w.cursor );
- count = window->cline - window->top_line;
- length = window->file_info->length + 1;
- for (i=count; i>0; i--) {
- p = find_prev( w.cursor );
- if (p) {
- w.cursor = p;
- --w.cline;
- --w.rline;
- }
- }
- w.cursor = cpf( w.cursor );
- for (i=number; i>0; i--) {
- if (w.cursor) {
- if (w.rline != length && length != 1l)
- update_line( &w );
- else
- show_eof( w.cline );
- w.cursor = find_next( w.cursor );
- } else
- eol_clear( 0, w.cline, COLOR_TEXT );
- ++w.cline;
- ++w.rline;
- }
-
- show_asterisk( w.file_info->modified, w.top_line-1 );
- }
-
-
- /*
- * Name: redraw_screen
- * Purpose: display all visible windows if some change was GLOBAL
- * Date: June 5, 1991
- * Passed: window: current window
- */
- void redraw_screen( windows *window )
- {
- windows *above; /* window above current */
- windows *below; /* window below current */
-
- cls( );
- /*
- * display the current window
- */
- redraw_current_window( window );
-
- /*
- * now update all the other windows
- */
- above = below = window;
- while (above->prev || below->next) {
- if (above->prev) {
- above = above->prev;
- redraw_current_window( above );
- }
- if (below->next) {
- below = below->next;
- redraw_current_window( below );
- }
- }
- window->file_info->dirty = FALSE;
- show_modes( );
- }
-
-
- /*
- * Name: redraw_current_window
- * Purpose: redraw all info in this window
- * Date: July 13, 1991
- * Passed: window: current window
- */
- void redraw_current_window( windows *window )
- {
-
- /*
- * display the current window
- */
- if (window->visible) {
- display_current_window( window );
- show_window_header( window->file_info->file_name, window );
- show_size_name( window );
- show_size( window );
- show_line_col( window );
- }
- }
-
-
- /*
- * Name: show_changed_line
- * Purpose: Only one line was changed in file, just show it
- * Date: June 5, 1991
- * Passed: window: current window
- */
- void show_changed_line( windows *window )
- {
- windows *above; /* window above current */
- windows *below; /* window below current */
- windows w;
- long changed_line;
- long top_line, bottom_line;
- int line_on_screen;
- file_infos *file;
-
- file = window->file_info;
- if (file->dirty == LOCAL || file->dirty == GLOBAL)
- update_line( window );
- changed_line = window->rline;
-
- /*
- * now update the line in all other windows
- */
- if (file->dirty != LOCAL) {
- above = below = window;
- while (above->prev || below->next) {
- if (above->prev) {
- above = above->prev;
- dup_window_info( &w, above );
- } else if (below->next) {
- below = below->next;
- dup_window_info( &w, below );
- }
- if (w.file_info == window->file_info && w.visible) {
- line_on_screen = FALSE;
- top_line = w.rline - (w.cline - w.top_line);
- bottom_line = w.rline + (w.bottom_line - w.cline);
- if (changed_line == w.rline)
- line_on_screen = TRUE;
- else if (changed_line < w.rline && changed_line >= top_line) {
- line_on_screen = TRUE;
- w.cursor = cpb( w.cursor );
- while (w.rline > changed_line) {
- w.cursor = find_prev( w.cursor );
- --w.rline;
- --w.cline;
- }
- } else if (changed_line > w.rline && changed_line <= bottom_line) {
- line_on_screen = TRUE;
- w.cursor = cpf( w.cursor );
- while (w.rline < changed_line) {
- w.cursor = find_next( w.cursor );
- ++w.rline;
- ++w.cline;
- }
- }
- if (line_on_screen)
- update_line( &w );
- }
- }
- }
- file->dirty = FALSE;
- }
-
-
- /*
- * Name: dup_window_info
- * Purpose: Copy window info from one window pointer to another
- * Date: June 5, 1991
- * Passed: dw: destination window
- * sw: source window
- */
- void dup_window_info( windows *dw, windows *sw )
- {
- memcpy( dw, sw, sizeof( windows ) );
- }
-
-
- /*
- * Name: addorsub_all_cursors
- * Purpose: A change has been made - window->cursors in other windows must
- * be changed to reflect adding or subing of characters.
- * Date: June 5, 1991
- * Passed: window: current window
- * net_change: number of bytes added or subtracted from a file
- * Notes: If a file has been changed, all of the memory pointers greater
- * than window->cursor must be adjusted by the number of characters
- * added or subtracted from the file pointed to by window.
- * If a file has been truncated in one window and there is another
- * window open to the same file and its current line is near the
- * end, the current line is reset to the last line of the file.
- */
- void addorsub_all_cursors( windows *window, long net_change )
- {
- windows *next;
- file_infos *file;
- file_infos *next_file;
-
- file = window->file_info;
- next = g_status.window_list;
- while (next != NULL) {
- if (next != window) {
- next_file = next->file_info;
- if (next_file == file) {
- if (next->rline > window->rline)
- next->cursor = addltop( net_change, next->cursor );
- } else {
- if (ptoul( next_file->start_text ) > ptoul( file->start_text ))
- next->cursor = addltop( net_change, next->cursor );
- }
- }
- next = next->next;
- }
- }
-
-
- /*
- * Name: adjust_windows_cursor
- * Purpose: A change has been made - window->cursors in other windows must
- * be changed to reflect adding or subing of characters.
- * Date: June 5, 1991
- * Passed: window: current window
- * line_change: number of lines added or subtracted from a file
- * Notes: If a file has been changed, all of the memory pointers greater
- * than window->cursor must be adjusted by the number of characters
- * added or subtracted from the file pointed to by window.
- * If a file has been truncated in one window and there is another
- * window open to the same file and its current line is near the
- * end, the current line is reset to the last line of the file.
- */
- void adjust_windows_cursor( windows *window, int line_change )
- {
- windows *next;
- register int reset;
- text_ptr p;
- register int i;
- file_infos *file;
- file_infos *next_file;
-
- file = window->file_info;
- next = g_status.window_list;
- while (next != NULL) {
- if (next != window) {
- next_file = next->file_info;
- if (next_file == file) {
- reset = FALSE;
- if (ptoul( next->cursor ) > ptoul( file->end_text ))
- reset = END;
- else if (ptoul( next->cursor ) < ptoul( file->start_text ))
- reset = BEGIN;
- else if (next->rline > window->rline) {
- if (line_change) {
- p = next->cursor;
- if (line_change < 0) {
- p = cpf( p );
- for (i=line_change; i < 0 && p != NULL; i++)
- p = find_next( p );
- if (p != NULL)
- next->cursor = p;
- else
- reset = END;
- } else if (line_change > 0) {
- p = cpb( p );
- for (i=line_change; i > 0 && p != NULL; i--)
- p = find_prev( p );
- if (p != NULL)
- next->cursor = p;
- else
- reset = BEGIN;
- }
- }
- }
- if (reset) {
- if (reset == BEGIN) {
- next->cursor = next_file->start_text;
- next->rline = 1;
- next->cline = next->top_line;
- } else {
- next_file->end_text = cpb( next_file->end_text );
- p = next_file->end_text - 1;
- p = find_prev( p );
- if (p != NULL)
- next->cursor = p;
- else
- next->cursor = next_file->end_text - 1;
- next->rline = next_file->length;
- }
- if (next->rline < (next->cline - (next->top_line - 1)))
- next->cline = (int)next->rline + next->top_line - 1;
- file->dirty = NOT_LOCAL;
- }
- }
- }
- next = next->next;
- }
- }
-
-
- /*
- * Name: adjust_start_end
- * Purpose: a file has been modified - must restore all start and end pointers
- * Date: June 5, 1991
- * Passed: mod: pointer to modified file structure
- * net_mod: net modifications in the source file
- * Notes: Go through the file list and adjust the start_text and end_text
- * file pointers as needed.
- */
- void adjust_start_end( file_infos *mod_file, long net_mod )
- {
- unsigned long mst, ost;
- file_infos *open_file;
-
- mst = ptoul( mod_file->start_text );
- for (open_file=g_status.file_list; open_file != NULL;
- open_file=open_file->next) {
- ost = ptoul( open_file->start_text );
- if (ost == mst)
- mod_file->end_text = addltop( net_mod, mod_file->end_text );
- else if (ost > mst) {
- open_file->start_text = addltop( net_mod, open_file->start_text );
- open_file->end_text = addltop( net_mod, open_file->end_text );
- }
- }
- }
-
-
- /*
- * Name: first_non_blank
- * Purpose: To find the column in which the first non-blank character in
- * the string occurs.
- * Date: June 5, 1991
- * Passed: s: the string to search
- * Returns: the first non-blank column
- */
- int first_non_blank( char far *s )
- {
- register int count = 0;
-
- s = cpf( s );
- while (*s++ == ' ')
- ++count;
- return( count );
- }
-
-
- /*
- * Name: page_up
- * Purpose: To move the cursor one page up the window (probably more
- * intuitive to think of the text being moved down)
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: The cursor line is moved back the required number of lines
- * towards the start of the file.
- * If the start of the file is reached, then the movement stops.
- */
- void page_up( windows *window )
- {
- int i; /* count of lines scanned */
- text_ptr p, q; /* previous lines */
-
- un_copy_line( window->cursor, window, TRUE );
- if (window->rline != (window->cline - (window->top_line-1))) {
- q = cpb( window->cursor );
- i = window->cline - (window->top_line-1);
- if (( window->rline - i) < window->page) {
- i = (int)window->rline - (window->cline - (window->top_line-1));
- for (; i>0; i--) {
- if ((p = find_prev( q )) != NULL)
- q = p;
- }
- window->rline = (window->cline-(window->top_line-1)) + window->page;
- } else {
- for (i=window->page; i>0; i--) {
- if ((p = find_prev( q )) != NULL)
- q = p;
- }
- }
- window->cursor = q;
- window->rline -= window->page;
- window->file_info->dirty = LOCAL;
- }
- }
-
-
- /*
- * Name: page_down
- * Purpose: To move the cursor one page down the window (probably more
- * intuitive to think of the text being moved up)
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: The cursor line is moved forwards the required number of lines
- * towards the end of the file.
- * If the end of the file is reached, then the movement stops.
- */
- void page_down( windows *window )
- {
- int i, k; /* count of lines scanned so far */
- text_ptr p, q; /* lines below cursor */
-
- un_copy_line( window->cursor, window, TRUE );
- q = cpf( window->cursor );
- k = window->cline - window->top_line;
- for (i=0; i < window->page && *q != CONTROL_Z; i++, k++) {
- p = find_next( q );
- if (p != NULL)
- q = p;
- else
- break;
- }
- if (k >= window->page) {
- window->cursor = q;
- window->rline += i;
- window->cline = window->cline + i - window->page;
- window->file_info->dirty = LOCAL;
- }
- }
-
-
- /*
- * Name: scroll_down
- * Purpose: To make the necessary changes after the user has given the
- * command to scroll down the screen.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Normally, we can just delete the top line on the window, and
- * then move the cursor up one line (so the cursor remains at
- * the same position in the file).
- * However, if the cursor was already on the top line of the
- * window, then the cursor must be moved down a line first.
- */
- void scroll_down( windows *window )
- {
- text_ptr next;
-
- un_copy_line( window->cursor, window, TRUE );
- window->cursor = cpf( window->cursor );
- if (window->cline == window->top_line) {
- if ((next = find_next( window->cursor )) != NULL)
- window->cursor = next;
- else
- return;
- ++window->cline;
- ++window->rline;
- }
- --window->cline;
- window->file_info->dirty = LOCAL;
- }
-
-
- /*
- * Name: scroll_up
- * Purpose: To make the necessary changes after the user has given the
- * command to scroll up the screen.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Normally, we can just insert one line at the top of the window,
- * and then move the cursor down one line (so the cursor remains at
- * the same position in the file).
- * However, if the cursor was already on the bottom line of the
- * window, then the cursor must be moved up a line first.
- */
- void scroll_up( windows *window )
- {
- text_ptr prev;
-
- un_copy_line( window->cursor, window, TRUE );
- window->cursor = cpb( window->cursor );
- if (window->rline != 1) {
- if (window->rline == (window->cline - (window->top_line -1))) {
- if ((prev = find_prev( window->cursor )) != NULL)
- window->cursor = prev;
- --window->rline;
- --window->cline;
- } else {
- if (window->cline == window->bottom_line) {
- if ((prev = find_prev( window->cursor )) != NULL)
- window->cursor = prev;
- else
- return;
- --window->cline;
- --window->rline;
- }
- ++window->cline;
- window->file_info->dirty = LOCAL;
- }
- }
- }
-
-
- /*
- * Name: fixed_scroll_up
- * Purpose: To leave cursor on same logical line and scroll up text
- * Date: September 1, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If cursor is one first page then do not scroll.
- */
- void fixed_scroll_up( windows *window )
- {
- text_ptr prev;
-
- un_copy_line( window->cursor, window, TRUE );
- window->cursor = cpb( window->cursor );
- if (window->rline != (window->cline+1 - window->top_line)) {
- if ((prev = find_prev( window->cursor )) != NULL) {
- window->cursor = prev;
- --window->rline;
- window->file_info->dirty = LOCAL;
- }
- }
- }
-
-
- /*
- * Name: fixed_scroll_down
- * Purpose: To leave cursor on same logical line and scroll down text
- * Date: September 1, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If cursor is on last line in file then do not scroll.
- */
- void fixed_scroll_down( windows *window )
- {
- text_ptr next;
-
- un_copy_line( window->cursor, window, TRUE );
- window->cursor = cpf( window->cursor );
- if ((next = find_next( window->cursor )) != NULL) {
- window->cursor = next;
- ++window->rline;
- window->file_info->dirty = LOCAL;
- }
- }
-
-
- /*
- * Name: file_file
- * Purpose: To file the current file to disk.
- * Date: September 17, 1991
- * Passed: window: information allowing access to the current window
- */
- void file_file( windows *window )
- {
- save_file( window );
- finish( window );
- }
-
-
- /*
- * Name: save_file
- * Purpose: To save the current file to disk.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If anything goes wrong, then the modified flag is set.
- * If the file is saved successfully, then modified flag is
- * cleared.
- */
- void save_file( windows *window )
- {
- char name[MAX_COLS]; /* name of file to be saved */
- char status_line[MAX_COLS+2]; /* status line at top of window */
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- register file_infos *file;
- int rc;
- int prompt_line;
-
- un_copy_line( window->cursor, window, TRUE );
- file = window->file_info;
- if (file->modified == FALSE)
- return;
- prompt_line = window->bottom_line;
-
- /*
- * set up file name and location of various flags
- */
- strcpy( name, file->file_name );
-
- /*
- * see if there was a file name - if not, then make the user
- * supply one.
- */
- if (strlen( name ) == 0) {
- save_as_file( window );
- return;
- }
-
- /*
- * save the file
- */
- save_screen_line( 0, prompt_line, line_buff );
- combine_strings( status_line, "Saving '", name, "'" );
- s_output( status_line, prompt_line, 0, g_display.message_color );
- eol_clear( strlen( status_line ), prompt_line, g_display.message_color );
- file->end_text = cpb( file->end_text );
- if ((rc = hw_save( name, file->start_text, file->end_text, NOTMARKED ))
- == ERROR) {
- combine_strings( status_line, "cannot write to '", name, "'" );
- error( WARNING, prompt_line, status_line );
- }
- restore_screen_line( 0, prompt_line, line_buff );
- if (rc != ERROR) {
- file->modified = FALSE;
- file->new_file = FALSE;
- }
- }
-
- /*
- * Name: save_as_file
- * Purpose: To save the current file to disk, but under a new name.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- */
- void save_as_file( windows *window )
- {
- char name[MAX_COLS]; /* new name for file */
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- char status_line[MAX_COLS+2]; /* status line at top of window */
- register file_infos *file;
- int prompt_line;
- int ok;
-
- un_copy_line( window->cursor, window, TRUE );
- /*
- * read in name, no default
- */
- prompt_line = window->bottom_line;
- file = window->file_info;
- save_screen_line( 0, prompt_line, line_buff );
- name[0] = '\0';
- if (get_name( "New file name: ", prompt_line, name,
- g_display.message_color ) == OK) {
-
- /*
- * make sure it is OK to overwrite any existing file
- */
- ok = TRUE;
- if (hw_fattrib( name ) != ERROR) { /* file exists */
- set_prompt( "Overwrite existing file? (y/n): ", prompt_line );
- if (get_yn( ) != A_YES || hw_unlink( name, prompt_line ) == ERROR)
- ok = FALSE;
- }
- if (ok == TRUE) {
- combine_strings( status_line, "Saving '", name, "'" );
- s_output( status_line, prompt_line, 0, g_display.message_color );
- eol_clear( strlen( status_line ), prompt_line,
- g_display.message_color );
- file->end_text = cpb( file->end_text );
- if (hw_save( name, file->start_text, file->end_text, NOTMARKED )
- == ERROR) {
- combine_strings( status_line, "cannot write to '", name, "'" );
- error( WARNING, prompt_line, status_line );
- } else
-
- /*
- * record that file is saved and not yet modified again
- */
- file->modified = FALSE;
- }
- }
- restore_screen_line( 0, prompt_line, line_buff );
- }
-
-
- /*
- * Name: show_window_header
- * Purpose: To save the current file to disk, but under a new name.
- * Date: June 5, 1991
- * Passed: name: name of file being edited
- * window: information allowing access to the current window
- * Notes: Clear line and display file name in a lite bar
- */
- void show_window_header( char *name, windows *window )
- {
- char status_line[MAX_COLS+2]; /* status line at top of window */
- char temp[10];
- char *p, *q; /* for setting up status line */
-
- memset( status_line, ' ', MAX_COLS );
- status_line[MAX_COLS] = '\0';
- q = name;
- p = status_line + 5;
- while (*q)
- *p++ = *q++;
- itoa( window->file_info->file_no, temp, 10 );
- if (strlen( temp ) > 1)
- p = status_line + 0;
- else
- p = status_line + 1;
- q = temp;
- while (*q)
- *p++ = *q++;
- *p = window->letter;
- s_output( status_line, window->top_line-1, 0, g_display.head_color );
- }
-
-
- /*
- * Name: show_size_name
- * Purpose: show 'size' line lite bar header
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- */
- void show_size_name( windows *window )
- {
- char size_line[MAX_COLS+2]; /* status line at top of window */
-
- strcpy( size_line, " size = " );
- s_output( size_line, window->top_line-1, 49, g_display.head_color );
- }
-
-
- /*
- * Name: show_size
- * Purpose: show number of lines in file
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- */
- void show_size( windows *window )
- {
- char size_line[MAX_COLS+2]; /* status line at top of window */
- char csize[20];
- char *p, *q; /* for setting up status line */
-
- strcpy( size_line, " " );
- p = size_line;
- ltoa( window->file_info->length, csize, 10 );
- q = csize;
- while (*q)
- *p++ = *q++;
- *p++ = ' ';
- *p = '\0';
- s_output( size_line, window->top_line-1, 57, g_display.head_color );
- }
-
-
- /*
- * Name: quit
- * Purpose: To close the current window without saving the current file.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If the file has been modified but not saved, then the user is
- * given a second chance before the changes are discarded.
- * Note that this is only necessary if this is the last window
- * that refers to the file. If another window still refers to
- * the file, then the check can be left until later.
- */
- void quit( windows *window )
- {
- int prompt_line;
- char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute */
- register file_infos *file;
- windows *wp;
- int count = 0;
-
- un_copy_line( window->cursor, window, TRUE );
- prompt_line = window->bottom_line;
- file = window->file_info;
- for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
- if (wp->file_info == file && wp->visible)
- ++count;
- }
- if (file->modified && count == 1) {
- save_screen_line( 0, prompt_line, line_buff );
- set_prompt( "Abandon changes? (y/n): ", prompt_line );
- if (get_yn( ) != A_YES) {
- restore_screen_line( 0, prompt_line, line_buff );
- return;
- }
- }
-
- /*
- * remove window, allocate screen lines to other windows etc
- */
- finish( window );
- }
-
-
- /*
- * Name: move_up
- * Purpose: To move the cursor one line up the screen.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If the cursor is at the top of the window, then the file must
- * be scrolled down.
- * If the cursor is already on the first line of the file, then
- * this command can be ignored.
- */
- void move_up( windows *window )
- {
- text_ptr p; /* the previous line on the screen */
-
- un_copy_line( window->cursor, window, TRUE );
- /*
- * if no previous line, give up
- */
- window->cursor = cpb( window->cursor );
- if ((p = find_prev( window->cursor )) != NULL) {
- window->cursor = p;
- --window->rline; /* ALWAYS decrement line counter */
- if (window->cline == window->top_line) {
- window_scroll_down( window->top_line, window->bottom_line );
- update_line( window );
- } else
- --window->cline; /* we aren't at top of screen - so move up */
- }
- }
-
-
- /*
- * Name: move_down
- * Purpose: To move the cursor one line down the screen.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If the cursor is at the bottom of the window, then the file must
- * be scrolled up. If the cursor is at the bottom of the file,
- * then scroll up until cursor is at top of screen.
- */
- void move_down( windows *window )
- {
- text_ptr p;
- register int bottom_line;
-
- un_copy_line( window->cursor, window, TRUE );
- bottom_line = window->bottom_line;
- window->cursor = cpf( window->cursor );
- if ((p = find_next( window->cursor )) != NULL) {
- window->cursor = p;
- ++window->rline; /* ALWAYS increment line counter */
- if (window->cline == bottom_line) {
- window_scroll_up( window->top_line, bottom_line );
- if (window->rline <= window->file_info->length)
- update_line( window );
- else
- show_eof( window->cline );
- } else
- ++window->cline; /* if not at bottom of screen move down */
- } else if (window->cline > window->top_line) {
- --window->cline;
- window_scroll_up_eof( window->top_line, bottom_line );
- }
- }
-
-
- /*
- * Name: move_left
- * Purpose: To move the cursor one character to the left
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If the cursor is already at the left of the screen, then
- * scroll horizontally if we're not at beginning of line.
- */
- void move_left( windows *window )
- {
- if (window->ccol > 0) {
- --window->ccol;
- --window->rcol;
- } else if (window->ccol == 0 && window->rcol > 0) {
- --window->rcol;
- --window->bcol;
- window->file_info->dirty = LOCAL;
- }
- }
-
-
- /*
- * Name: move_right
- * Purpose: To move the cursor one character to the right
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: If the cursor is already at the right of the screen (logical
- * column 80) then scroll horizontally right.
- */
- void move_right( windows *window )
- {
- int max_col;
-
- max_col = g_display.ncols - 1;
- if (window->ccol < max_col) {
- ++window->ccol;
- ++window->rcol;
- } else if (window->ccol == max_col && window->rcol < g_display.line_length) {
- ++window->rcol;
- ++window->bcol;
- window->file_info->dirty = LOCAL;
- }
- }
-
-
- /*
- * Name: word_left
- * Purpose: To move the cursor one word to the left.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Words are considered strings of letters, numbers and underscores,
- * which must be separated by other characters. After every 8000
- * characters, check the pointer.
- */
- void word_left( windows *window )
- {
- text_ptr p; /* text pointer */
- int len; /* length of current line */
- int c; /* character at pointer */
- register int check = 0;
-
- un_copy_line( window->cursor, window, TRUE );
- p = cpf( window->cursor );
- len = linelen( p );
- if (window->rcol > len)
- p += len;
- else
- p += window->rcol;
- p = cpb( p );
-
- for (c=*p;c != CONTROL_Z && myisalnum( c ); check++) {
- c = *--p;
- if (check > 8000) {
- p = cpb( p );
- check = 0;
- }
- }
- if (c == CONTROL_Z)
- return;
- for (; c != CONTROL_Z && !myisalnum( c ); check++) {
- c = *--p;
- if (check > 8000) {
- p = cpb( p );
- check = 0;
- }
- }
- if (c == CONTROL_Z)
- return;
- for (;c != CONTROL_Z && myisalnum( c ); check++) {
- c = *--p;
- if (check > 8000) {
- p = cpb( p );
- check = 0;
- }
- }
- find_adjust( window, ++p );
- }
-
-
- /*
- * Name: word_right
- * Purpose: To move the cursor one word to the right.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Words are considered strings of letters, numbers and underscores,
- * which must be separated by other characters. After every 8000
- * characters, check the pointer.
- */
- void word_right( windows *window )
- {
- int len; /* length of current line */
- text_ptr p; /* text pointer */
- int c; /* character at pointer */
- register int check = 0;
-
- un_copy_line( window->cursor, window, TRUE );
- p = cpf( window->cursor );
- len = linelen( p );
- if (window->rcol > len)
- p += len;
- else
- p += window->rcol;
- for (c=*p;c != CONTROL_Z && myisalnum( c ); check++) {
- c = *++p;
- if (check > 8000) {
- p = cpf( p );
- check = 0;
- }
- }
- for (; c != CONTROL_Z && !myisalnum( c ); check++) {
- c = *++p;
- if (check > 8000) {
- p = cpf( p );
- check = 0;
- }
- }
- if (c != CONTROL_Z)
- find_adjust( window, p );
- }
-
- /*
- * Name: center_window
- * Purpose: To make the current line the center of window.
- * Date: June 5, 1991
- * Passed: window: information allowing access to the current window
- */
- void center_window( windows *window )
- {
- int center;
- int center_line;
- int diff;
- register file_infos *file;
- int i;
-
- file = window->file_info;
- center = (window->bottom_line + 1 - window->top_line) / 2;
- center_line = window->top_line + center;
- diff = center_line - window->cline;
- if (g_status.command == CenterWindow) {
- un_copy_line( window->cursor, window, TRUE );
- if (diff > 0) {
- if (window->rline + diff <= file->length) {
- window->cline += diff;
- window->rline += diff;
- window->cursor = cpf( window->cursor );
- for (i=0; i<diff; i++)
- window->cursor = find_next( window->cursor );
- }
- } else if (diff < 0) {
- window->cline += diff;
- window->rline += diff;
- window->cursor = cpb( window->cursor );
- for (i=diff; i<0; i++)
- window->cursor = find_prev( window->cursor );
- }
- } else if (g_status.command == CenterLine) {
- if (diff > 0) {
- window->cline += diff;
- if ((window->cline+1 - window->top_line) > window->rline)
- window->cline = window->top_line - 1 + (int)window->rline;
- file->dirty = LOCAL;
- } else if (diff < 0) {
- window->cline = window->cline + diff;
- file->dirty = LOCAL;
- }
- }
- }
-
-
- /*
- * Name: horizontal_screen_right
- * Purpose: To move the cursor one screen to the right
- * Date: September 13, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Add 80 columns to the real cursor. If the cursor is past the
- * maximum line length then move it back.
- */
- void horizontal_screen_right( windows *window )
- {
-
- window->rcol += 80;
- if (window->rcol > MAX_LINE_LENGTH)
- window->rcol = MAX_LINE_LENGTH;
- else {
- window->bcol += 80;
- window->file_info->dirty = LOCAL;
- }
- check_virtual_col( window, window->rcol, window->ccol );
- }
-
-
- /*
- * Name: horizontal_screen_left
- * Purpose: To move the cursor one screen to the left
- * Date: September 13, 1991
- * Passed: window: information allowing access to the current window
- * Notes: Subtract 80 columns to the real cursor. If the cursor is less than
- * zero then see if bcol is zero. If bcol is not zero then make
- * bcol zero.
- */
- void horizontal_screen_left( windows *window )
- {
-
- if (window->rcol - 80 < 0) {
- if (window->bcol != 0) {
- window->bcol = 0;
- window->file_info->dirty = LOCAL;
- }
- } else {
- window->rcol -= 80;
- window->bcol -= 80;
- if (window->bcol < 0)
- window->bcol = 0;
- window->file_info->dirty = LOCAL;
- }
- check_virtual_col( window, window->rcol, window->ccol );
- }