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 - main editor module
- * Purpose: This file contains the main editor module, and a number of the
- * smaller miscellaneous editing commands.
- * It also contains the code for dispatching commands.
- * File: ed.c
- * Author: Douglas Thomson
- * System: this file is intended to be system-independent
- * Date: October 1, 1989
- * I/O: file being edited
- * files read or written
- * user commands and prompts
- * Notes: see the file "dte.doc" for general program documentation
- */
- /********************* end of original comments ********************/
-
- /*
- * The basic editor routines have been EXTENSIVELY rewritten. I have added
- * support for lines longer than 80 columns and I have added line number
- * support. I like to know the real line number that editor functions are
- * working on and I like to know the total number of lines in a file.
- *
- * I rewrote the big series of ifs in the dispatch subroutine. It is now
- * an array of pointers to functions. We know what function to call as soon
- * as a key is pressed. It is also makes it easier to implement a configuration
- * utility and macros.
- *
- * I added a few functions that I use quite often and I deleted a few that I
- * rarely use. Added are Split Line, Join Line, and Duplicate Line. Deleted
- * are Goto Marker 0-9 (others?).
- *
- * ************ In TDE 1.3, I put Goto Marker 0-9 back in. ***************
- *
- * I felt that the insert routine should be separated into two routines. One
- * for inserting the various combinations of newlines and one for inserting
- * ASCII and extended ASCII characters.
- *
- * One of Doug's design considerations was keeping screen updates to a minimum.
- * I have expanded upon that idea and added support for updating windows
- * LOCALly, GLOBALly, or NOT_LOCALly. For example, scrolling in one window
- * does not affect the text in another window - LOCAL update. Adding, deleting,
- * or modifying text in one window may affect text in other windows - GLOBAL
- * update. Sometimes, updates to the current window are handled in the task
- * routines so updates to other windows are done NOT_LOCALly.
- *
- * In version 2.2, the big text buffer scheme was replaced by a double
- * linked list.
- *
- * 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
- * Date: October 31, 1992, version 2.1
- * Date: April 1, 1993, version 2.2
- * Date: June 5, 1993, version 3.0
- * Date: August 29, 1993, version 3.1
- * Date: November 13, 1993, version 3.2
- *
- * This modification of Douglas Thomson's code is released into the
- * public domain, Frank Davis. You may distribute it freely.
- */
-
- #include "tdestr.h" /* typedefs for global variables */
- #include "define.h" /* editor function defs */
- #include "tdefunc.h" /* prototypes for all functions in tde */
- #include "global.h" /* global variables */
- #include "prompts.h" /* prompt assignments */
- #include "default.h" /* default function key assignments */
-
-
- /*
- * Name: insert_newline
- * Purpose: insert a newline
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: There a several ways to insert a line into a file: 1) pressing
- * a key, 2) word wrap, 3) any others?
- * When doing word wrap or format paragraph, don't show any changes.
- * Wait until the function finishes then show all changes at once.
- */
- int insert_newline( TDE_WIN *window )
- {
- char *source; /* source for block move to make room for c */
- char *dest; /* destination for block move */
- int len; /* length of current line */
- int split_len;
- int add; /* characters to be added (usually 1 in insert mode) */
- int rcol;
- int rc;
- long length;
- int carriage_return;
- int split_line;
- int wordwrap;
- int dirty;
- int old_bcol;
- register TDE_WIN *win; /* put window pointer in a register */
- file_infos *file; /* pointer to file structure in current window */
- line_list_ptr new_node;
- text_ptr new_line; /* new line */
-
- rc = OK;
- win = window;
- file = win->file_info;
- length = file->length;
- wordwrap = mode.word_wrap;
- switch (g_status.command) {
- case WordWrap :
- carriage_return = TRUE;
- split_line = FALSE;
- break;
- case AddLine :
- split_line = carriage_return = FALSE;
- break;
- case SplitLine :
- split_line = carriage_return = TRUE;
- break;
- case Rturn :
- default :
-
- /*
- * if file is opened in BINARY mode, lets keep the user from
- * unintentially inserting a line feed into the text.
- */
- if (file->crlf == BINARY)
- return( next_line( win ) );
-
- show_ruler_char( win );
- carriage_return = TRUE;
- split_line = FALSE;
- break;
- }
-
- /*
- * make window temporarily invisible to the un_copy_line function
- */
- new_node = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
- new_line = NULL;
- win->visible = FALSE;
- old_bcol = win->bcol;
- if (rc == OK) {
- new_node->line = new_line;
- new_node->len = 0;
- new_node->dirty = FALSE;
-
- if (win->ll->len != EOF) {
- win->file_info->modified = TRUE;
- if (mode.do_backups == TRUE)
- rc = backup_file( win );
- copy_line( win->ll );
- detab_linebuff( );
- len = g_status.line_buff_len;
- split_len = 0;
- if (win->rcol < len)
- win->ll->dirty = TRUE;
-
- source = g_status.line_buff + len;
- if (carriage_return || split_line) {
- if (win->rcol < len) {
- source = g_status.line_buff + win->rcol;
- split_len = len - win->rcol;
- len = win->rcol;
- }
- }
- g_status.line_buff_len = len;
- entab_linebuff( );
- if (un_copy_line( win->ll, win, TRUE ) == OK) {
-
- assert( split_len >= 0 );
- assert( split_len < MAX_LINE_LENGTH );
-
- memmove( g_status.line_buff, source, split_len );
- g_status.line_buff_len = len = split_len;
- g_status.copied = TRUE;
- entab_linebuff( );
- } else
- rc = ERROR;
- } else {
- g_status.line_buff_len = len = 0;
- g_status.copied = TRUE;
- }
-
- if (rc == OK) {
- new_node->line = new_line;
- new_node->len = 0;
- new_node->dirty = TRUE;
-
- /*
- * we are somewhere in the list and we need to insert the new node.
- * if we are anywhere except the EOF node, insert the new node
- * after the current node. if the current node is the EOF node,
- * insert the new node before the EOF node. this keeps the
- * EOF node at the end of the list.
- */
- if (win->ll->next != NULL) {
- win->ll->next->prev = new_node;
- new_node->next = win->ll->next;
- win->ll->next = new_node;
- new_node->prev = win->ll;
- } else {
- new_node->next = win->ll;
- if (win->ll->prev != NULL)
- win->ll->prev->next = new_node;
- new_node->prev = win->ll->prev;
- win->ll->prev = new_node;
- if (new_node->prev == NULL)
- win->file_info->line_list = new_node;
- win->ll = new_node;
- }
-
- ++file->length;
- detab_linebuff( );
- entab_linebuff( );
- rc = un_copy_line( new_node, win, FALSE );
- adjust_windows_cursor( win, 1 );
-
- file->dirty = NOT_LOCAL;
- if (length == 0l || wordwrap || win->cline == win->bottom_line)
- file->dirty = GLOBAL;
- else if (!split_line)
- update_line( win );
-
- /*
- * If the cursor is to move down to the next line, then update
- * the line and column appropriately.
- */
- if (rc == OK && (carriage_return || split_line)) {
- dirty = file->dirty;
- if (win->cline < win->bottom_line)
- win->cline++;
- win->rline++;
- if (win->ll->next != NULL) {
- win->bin_offset += win->ll->len;
- win->ll = win->ll->next;
- }
- rcol = win->rcol;
- old_bcol = win->bcol;
-
- if (win->ll->next != NULL) {
- if (mode.indent || wordwrap) {
- /*
- * autoindentation is required. Match the indentation of
- * the first line above that is not blank.
- */
- add = find_left_margin( wordwrap == FIXED_WRAP ?
- win->ll : win->ll->prev, wordwrap );
-
- assert( add >= 0 );
- assert( add < MAX_LINE_LENGTH );
-
- copy_line( win->ll );
- detab_linebuff( );
- len = g_status.line_buff_len;
- source = g_status.line_buff;
- if (len + add > MAX_LINE_LENGTH)
- add = MAX_LINE_LENGTH - len;
- dest = source + add;
-
- assert( len >= 0);
- assert( len < MAX_LINE_LENGTH );
-
- memmove( dest, source, len );
-
- /*
- * now put in the autoindent characters
- */
-
- assert( add >= 0 );
- assert( add < MAX_LINE_LENGTH );
-
- memset( source, ' ', add );
- win->rcol = add;
- g_status.line_buff_len += add;
- entab_linebuff( );
- rc = un_copy_line( win->ll, win, TRUE );
- } else
- win->rcol = 0;
- }
- if (rc == OK && split_line) {
- win->rline--;
- win->ll = win->ll->prev;
- if (win->cline > win->top_line + window->ruler)
- win->cline--;
- win->rcol = rcol;
- }
- check_virtual_col( win, win->rcol, win->ccol );
- if (dirty == GLOBAL || file->dirty == LOCAL || wordwrap)
- file->dirty = GLOBAL;
- else
- file->dirty = dirty;
- }
- } else {
- if (new_node != NULL)
- my_free( new_node );
- }
- } else {
- if (new_node != NULL)
- my_free( new_node );
- error( WARNING, window->bottom_line, main4 );
- }
-
- /*
- * record that file has been modified
- */
- win->visible = TRUE;
- if (rc == OK) {
- if (file->dirty != GLOBAL)
- my_scroll_down( win );
- restore_marked_block( win, 1 );
- show_size( win );
- show_avail_mem( );
- if (old_bcol != win->bcol) {
- make_ruler( win );
- show_ruler( win );
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: insert_overwrite
- * Purpose: To make the necessary changes after the user has typed a normal
- * printable character
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- */
- int insert_overwrite( TDE_WIN *window )
- {
- char *source; /* source for block move to make room for c */
- char *dest; /* destination for block move */
- int len; /* length of current line */
- int pad; /* padding to add if cursor beyond end of line */
- int add; /* characters to be added (usually 1 in insert mode) */
- register int rcol;
- register TDE_WIN *win; /* put window pointer in a register */
- int rc;
-
- win = window;
- if (win->ll->len == EOF || g_status.key_pressed >= 256)
- rc = OK;
- else {
- rcol = win->rcol;
- /*
- * first check we have room - the editor can not
- * cope with lines wider than MAX_LINE_LENGTH
- */
- if (rcol >= MAX_LINE_LENGTH) {
- /*
- * cannot insert more characters
- */
- error( WARNING, win->bottom_line, ed2 );
- rc = ERROR;
- } else {
- copy_line( win->ll );
- detab_linebuff( );
-
- /*
- * work out how many characters need to be inserted
- */
- len = g_status.line_buff_len;
- pad = rcol > len ? rcol - len : 0;
-
- if (mode.insert || rcol >= len)
- /*
- * inserted characters, or overwritten characters at the end of
- * the line, are inserted.
- */
- add = 1;
- else
- /*
- * and no extra space is required to overwrite existing characters
- */
- add = 0;
-
- /*
- * check that current line would not get too long.
- */
- if (len + pad + add >= MAX_LINE_LENGTH) {
- /*
- * no more room to add
- */
- error( WARNING, win->bottom_line, ed3 );
- rc = ERROR;
- } else {
-
- /*
- * make room for whatever needs to be inserted
- */
- if (pad > 0 || add > 0) {
- source = g_status.line_buff + rcol - pad;
- dest = source + pad + add;
-
- assert( len + pad - rcol >= 0 );
- assert( len + pad - rcol < MAX_LINE_LENGTH );
-
- memmove( dest, source, len + pad - rcol );
-
- /*
- * put in the required padding
- */
-
- assert( pad >= 0 );
- assert( pad < MAX_LINE_LENGTH );
-
- memset( source, ' ', pad );
- }
- g_status.line_buff[rcol] = (char)g_status.key_pressed;
- g_status.line_buff_len += pad + add;
- entab_linebuff( );
-
- /*
- * always increment the real column (rcol) then adjust the
- * logical and base column as needed. show the changed line
- * in all but the LOCAL window. In the LOCAL window, there are
- * two cases: 1) update the line, or 2) redraw the window if
- * cursor goes too far right.
- */
- win->file_info->dirty = NOT_LOCAL;
- win->ll->dirty = TRUE;
- show_changed_line( win );
- if (win->ccol < win->end_col) {
- show_curl_line( win );
- show_ruler_char( win );
- win->ccol++;
- } else {
- win->bcol++;
- win->file_info->dirty = LOCAL;
- make_ruler( win );
- show_ruler( win );
- }
- rcol++;
- }
-
- /*
- * record that file has been modified and adjust cursors,
- * file start and end pointers as needed.
- */
- check_virtual_col( win, rcol, win->ccol );
- win->file_info->modified = TRUE;
- if (mode.word_wrap) {
- add = mode.right_justify;
- mode.right_justify = FALSE;
- g_status.command = FormatText;
- word_wrap( win );
- mode.right_justify = add;
- }
- rc = OK;
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: join_line
- * Purpose: To join current line and line below at cursor
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: trunc the line. then, join with line below, if it exists.
- */
- int join_line( TDE_WIN *window )
- {
- int len; /* length of current line */
- int new_len; /* length of the joined lines */
- int next_len; /* length of the line below current line */
- text_ptr q; /* next line in file */
- text_ptr tab_free; /* next line in file -- with the tabs removed */
- int pad; /* padding spaces required */
- register TDE_WIN *win; /* put window pointer in a register */
- TDE_WIN *wp;
- line_list_ptr next_node;
- int rc;
-
- win = window;
- if (win->ll->len == EOF || win->ll->next->len == EOF)
- return( ERROR );
-
- rc = OK;
-
- assert( win->ll->next != NULL );
-
- next_node = win->ll->next;
- load_undo_buffer( win->file_info, win->ll->line, win->ll->len );
- copy_line( win->ll );
- detab_linebuff( );
-
- /*
- * if cursor is in line before eol, reset len to rcol
- */
- if (win->rcol < (len = g_status.line_buff_len))
- len = win->rcol;
-
- /*
- * calculate needed padding
- */
- pad = win->rcol > len ? win->rcol - len : 0;
-
- assert( pad >= 0 );
- assert( pad < MAX_LINE_LENGTH );
-
- /*
- * if there any tabs in the next line, expand them because we
- * probably have to redo them anyway.
- */
- next_len = next_node->len;
- tab_free = detab_a_line( next_node->line, &next_len );
-
- assert( next_len >= 0 );
- assert( next_len < MAX_LINE_LENGTH );
- assert( len >= 0 );
- assert( len < MAX_LINE_LENGTH );
-
- /*
- * check room to combine lines
- */
- new_len = len + pad + next_len;
- if (new_len >= MAX_LINE_LENGTH) {
- /*
- * cannot combine lines.
- */
- error( WARNING, win->bottom_line, ed4 );
- rc = ERROR;
- } else {
- if (mode.do_backups == TRUE) {
- win->file_info->modified = TRUE;
- rc = backup_file( win );
- }
- q = (text_ptr)(g_status.line_buff + len);
- /*
- * insert padding
- */
- if (pad > 0) {
- while (pad--)
- *q++ = ' ';
- }
- my_memcpy( q, tab_free, next_len );
- g_status.line_buff_len = new_len;
- entab_linebuff( );
-
- if ((rc = un_copy_line( win->ll, win, FALSE )) == OK) {
-
- if (next_node->next != NULL)
- next_node->next->prev = win->ll;
- win->ll->next = next_node->next;
- win->ll->dirty = TRUE;
-
- --win->file_info->length;
- ++win->rline;
- adjust_windows_cursor( win, -1 );
- restore_marked_block( win, -1 );
- --win->rline;
-
- wp = g_status.window_list;
- while (wp != NULL) {
- if (wp->file_info == win->file_info) {
- /*
- * make sure none of the window pointers point to the
- * node we are about to delete.
- */
- if (wp != win) {
- if (wp->ll == next_node)
- wp->ll = win->ll->next;
- }
- }
- wp = wp->next;
- }
-
- /*
- * now, it's safe to delete the next_node line as well as
- * the next node.
- */
- if (next_node->line != NULL)
- my_free( next_node->line );
- my_free( next_node );
-
- show_size( win );
- show_avail_mem( );
- win->file_info->dirty = GLOBAL;
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: word_delete
- * Purpose: To delete from the cursor to the start of the next word.
- * Date: September 1, 1991
- * Passed: window: pointer to current window
- * Notes: If the cursor is at the right of the line, then combine the
- * current line with the next one, leaving the cursor where it
- * is.
- * If the cursor is on an alphanumeric character, then all
- * subsequent alphanumeric characters are deleted.
- * If the cursor is on a space, then all subsequent spaces
- * are deleted.
- * If the cursor is on a punctuation character, then all
- * subsequent punctuation characters are deleted.
- */
- int word_delete( TDE_WIN *window )
- {
- int len; /* length of current line */
- int count; /* number of characters deleted from line */
- register int start; /* column that next word starts in */
- char *source; /* source for block move to delete word */
- char *dest; /* destination for block move */
- text_ptr p;
- register TDE_WIN *win; /* put window pointer in a register */
- int rc;
-
- win = window;
- if (win->rline > win->file_info->length || win->ll->len == EOF)
- return( ERROR );
-
- rc = OK;
- copy_line( win->ll );
- detab_linebuff( );
- if (win->rcol >= (len = g_status.line_buff_len)) {
- rc = join_line( win );
- if (rc == OK) {
- p = win->ll->line;
- if (p != NULL) {
- p += win->rcol;
- if (win->rcol < win->ll->len) {
- len = win->ll->len - win->rcol;
- load_undo_buffer( win->file_info, p, len );
- }
- }
- }
- } else {
-
- assert( len >= 0);
- assert( len < MAX_LINE_LENGTH );
-
- /*
- * normal word delete
- *
- * find the start of the next word
- */
- start = win->rcol;
- if (bj_isspace( g_status.line_buff[start] )) {
- /*
- * the cursor was on a space, so eat all consecutive spaces
- * from the cursor onwards.
- */
- while (start < len && bj_isspace( g_status.line_buff[start] ))
- ++start;
- } else {
- /*
- * eat all consecutive characters in the same class (spaces
- * are considered to be in the same class as the cursor
- * character)
- */
- while (start < len && !bj_isspace( g_status.line_buff[start] ))
- ++start;
- while (start < len && bj_isspace( g_status.line_buff[start] ))
- ++start;
- }
-
- /*
- * move text to delete word
- */
- count = start - win->rcol;
- source = g_status.line_buff + start;
- dest = g_status.line_buff + win->rcol;
-
- assert( len - start >= 0 );
-
- memmove( dest, source, len - start );
- g_status.line_buff_len = len - count;
- entab_linebuff( );
- win->file_info->modified = TRUE;
- win->file_info->dirty = GLOBAL;
- win->ll->dirty = TRUE;
-
- /*
- * word_delete is also called by the word processing functions to get
- * rid of spaces.
- */
- if (g_status.command == WordDelete)
- show_changed_line( win );
- }
- return( rc );
- }
-
-
- /*
- * Name: dup_line
- * Purpose: Duplicate current line
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: cursor stays on current line
- */
- int dup_line( TDE_WIN *window )
- {
- register int len; /* length of current line */
- text_ptr p;
- register TDE_WIN *win; /* put window pointer in a register */
- line_list_ptr next_node;
- int rc;
-
- win = window;
-
- /*
- * don't dup a NULL line
- */
- if (win->rline > win->file_info->length || win->ll->len == EOF)
- return( ERROR );
-
- entab_linebuff( );
- rc = un_copy_line( win->ll, win, TRUE );
- len = win->ll->len;
-
- assert( len >= 0);
- assert( len < MAX_LINE_LENGTH );
-
- p = NULL;
- next_node = NULL;
- if (rc == OK) {
- p = (text_ptr)my_malloc( len, &rc );
- next_node = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
- }
-
- if (rc == OK) {
- win->file_info->modified = TRUE;
- if (mode.do_backups == TRUE)
- rc = backup_file( win );
- ++win->file_info->length;
-
- if (len > 0)
- my_memcpy( p, win->ll->line, len );
-
- next_node->line = p;
- next_node->dirty = TRUE;
- next_node->len = len;
-
- if (win->ll->next != NULL)
- win->ll->next->prev = next_node;
-
- next_node->next = win->ll->next;
- next_node->prev = win->ll;
- win->ll->next = next_node;
-
- adjust_windows_cursor( win, 1 );
-
- /*
- * if current line is the bottom line, we can't see the dup line because
- * cursor doesn't move and dup line is added after current line.
- */
- if (win->cline != win->bottom_line)
- my_scroll_down( win );
- win->file_info->dirty = NOT_LOCAL;
-
- /*
- * record that file has been modified
- */
- restore_marked_block( win, 1 );
- show_size( win );
- show_avail_mem( );
- } else {
- /*
- * cannot duplicate line
- */
- if (p != NULL)
- my_free( p );
- if (next_node != NULL)
- my_free( next_node );
- error( WARNING, win->bottom_line, ed5 );
- }
- return( rc );
- }
-
-
- /*
- * Name: back_space
- * Purpose: To delete the character to the left of the cursor.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: If the cursor is at the left of the line, then combine the
- * current line with the previous one.
- * If in indent mode, and the cursor is on the first non-blank
- * character of the line, then match the indentation of an
- * earlier line.
- */
- int back_space( TDE_WIN *window )
- {
- int rc; /* return code */
- int len; /* length of the current line */
- char *source; /* source of block move to delete character */
- char *dest; /* destination of block move */
- text_ptr p; /* previous line in file */
- int plen; /* length of previous line */
- int del_count; /* number of characters to delete */
- int pos; /* the position of the first non-blank char */
- register int rcol;
- int ccol;
- int old_bcol;
- register TDE_WIN *win; /* put window pointer in a register */
- TDE_WIN *wp;
- line_list_ptr temp_ll;
-
- win = window;
- if (win->rline > win->file_info->length || win->ll->len == EOF)
- return( ERROR );
- rc = OK;
- copy_line( win->ll );
- detab_linebuff( );
- len = g_status.line_buff_len;
- rcol = win->rcol;
- ccol = win->ccol;
- old_bcol = win->bcol;
- if (rcol == 0) {
- if (win->rline > 1) {
- /*
- * combine this line with the previous, if any
- */
-
- assert( win->ll->prev != NULL );
-
- p = win->ll->prev->line;
- plen = win->ll->prev->len;
- if (len + 2 + plen >= MAX_LINE_LENGTH) {
- /*
- * cannot combine lines
- */
- error( WARNING, win->bottom_line, ed4 );
- return( ERROR );
- }
-
- win->file_info->modified = TRUE;
- if ((rc = un_copy_line( win->ll, win, TRUE )) == OK) {
- --win->rline;
- win->ll = win->ll->prev;
- win->bin_offset -= win->ll->len;
- win->ll->dirty = TRUE;
- copy_line( win->ll );
- detab_linebuff( );
- len = g_status.line_buff_len;
- rcol = len;
-
- p = win->ll->next->line;
- plen = win->ll->next->len;
-
- /*
- * copy previous line into new previous line.
- */
- assert( plen >= 0 );
- assert( len >= 0 );
-
- my_memcpy( g_status.line_buff+len, p, plen );
- g_status.line_buff_len = len + plen;
-
- load_undo_buffer( win->file_info, p, plen );
- if (p != NULL)
- my_free( p );
-
- temp_ll = win->ll->next;
-
- if (temp_ll->prev != NULL)
- temp_ll->prev->next = temp_ll->next;
- temp_ll->next->prev = temp_ll->prev;
-
- --win->file_info->length;
- ++win->rline;
- restore_marked_block( win, -1 );
- adjust_windows_cursor( win, -1 );
- --win->rline;
-
- wp = g_status.window_list;
- while (wp != NULL) {
- if (wp->file_info == win->file_info) {
- if (wp != win) {
- if (wp->ll == temp_ll)
- wp->ll = win->ll->next;
- }
- }
- wp = wp->next;
- }
-
- my_free( temp_ll );
-
- if (win->cline > win->top_line + win->ruler)
- --win->cline;
-
- /*
- * make sure cursor stays on the screen, at the end of the
- * previous line
- */
- ccol = rcol - win->bcol;
- show_size( win );
- show_avail_mem( );
- check_virtual_col( win, rcol, ccol );
- win->file_info->dirty = GLOBAL;
- make_ruler( win );
- show_ruler( win );
- }
- } else
- return( ERROR );
- } else {
- /*
- * normal delete
- *
- * find out how much to delete (depends on indent mode)
- */
- del_count = 1; /* the default */
- if (mode.indent) {
- /*
- * indent only happens if the cursor is on the first
- * non-blank character of the line
- */
- pos = first_non_blank( (text_ptr)g_status.line_buff, len );
- if (pos == rcol ||
- is_line_blank( (text_ptr)g_status.line_buff, len )) {
- /*
- * now work out how much to indent
- */
- temp_ll = win->ll->prev;
- for (; temp_ll != NULL; temp_ll=temp_ll->prev) {
- p = temp_ll->line;
- plen = first_non_blank( p, temp_ll->len );
- if (plen < rcol && plen != temp_ll->len) {
- /*
- * found the line to match
- */
- del_count = rcol - plen;
- break;
- }
- }
- }
- }
-
- /*
- * move text to delete char(s), unless no chars actually there
- */
- if (rcol - del_count < len) {
- dest = g_status.line_buff + rcol - del_count;
- if (rcol > len) {
- source = g_status.line_buff + len;
- pos = 0;
- len = (rcol + 1) - del_count;
- } else {
- source = g_status.line_buff + rcol;
- pos = len - rcol;
- len = len - del_count;
- }
-
- assert( pos >= 0 );
- assert( len >= 0 );
- assert( len <= MAX_LINE_LENGTH );
-
- memmove( dest, source, pos );
- g_status.line_buff_len = len;
- entab_linebuff( );
- }
- rcol -= del_count;
- ccol -= del_count;
- win->file_info->dirty = NOT_LOCAL;
- win->ll->dirty = TRUE;
- show_ruler_char( win );
- show_changed_line( win );
- check_virtual_col( win, rcol, ccol );
- if (!win->file_info->dirty)
- show_curl_line( win );
- if (old_bcol != win->bcol) {
- make_ruler( win );
- show_ruler( win );
- }
- }
- win->file_info->modified = TRUE;
- return( rc );
- }
-
-
- /*
- * Name: line_kill
- * Purpose: To delete the line the cursor is on.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: win->ll->s == NULL then do not do a
- * line kill (can't kill a NULL line).
- */
- int line_kill( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
- register TDE_WIN *wp;
- line_list_ptr killed_node;
- int rc;
-
- win = window;
- killed_node = win->ll;
- rc = OK;
- if (killed_node->len != EOF) {
- win->file_info->modified = TRUE;
- if (mode.do_backups == TRUE)
- rc = backup_file( win );
-
- if (rc == OK) {
- load_undo_buffer( win->file_info,
- g_status.copied ? (text_ptr)g_status.line_buff : killed_node->line,
- g_status.copied ? g_status.line_buff_len : killed_node->len );
-
- --win->file_info->length;
-
- win->ll = win->ll->next;
-
- if (killed_node->prev != NULL)
- killed_node->prev->next = killed_node->next;
- else
- win->file_info->line_list = win->ll;
-
- killed_node->next->prev = killed_node->prev;
-
- wp = g_status.window_list;
- while (wp != NULL) {
- if (wp->file_info == win->file_info) {
- if (wp != win) {
- if (wp->ll == killed_node)
- wp->ll = win->ll;
- }
- }
- wp = wp->next;
- }
-
- /*
- * free the line and the node
- */
- if (killed_node->line != NULL)
- my_free( killed_node->line );
- my_free( killed_node );
-
- win->file_info->dirty = NOT_LOCAL;
-
- g_status.copied = FALSE;
- /*
- * move all cursors one according to i, restore begin and end block
- */
- adjust_windows_cursor( win, -1 );
- restore_marked_block( win, -1 );
-
- /*
- * we are not doing a GLOBAL update, so update current window here
- */
- if (win->file_info->dirty == NOT_LOCAL)
- my_scroll_down( win );
- show_size( win );
- show_avail_mem( );
- }
- } else
- rc = ERROR;
- return( rc );
- }
-
-
- /*
- * Name: char_del_under
- * Purpose: To delete the character under the cursor.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: If the cursor is beyond the end of the line, then this
- * command is ignored.
- * DeleteChar and StreamDeleteChar use this function.
- */
- int char_del_under( TDE_WIN *window )
- {
- char *source; /* source of block move to delete character */
- int len;
- register TDE_WIN *win; /* put window pointer in a register */
-
- win = window;
- if (win->rline > win->file_info->length || win->ll->len == EOF)
- return( OK );
- copy_line( win->ll );
- detab_linebuff( );
- if (win->rcol < (len = g_status.line_buff_len)) {
- /*
- * move text to delete using buffer
- */
- source = g_status.line_buff + win->rcol + 1;
-
- assert( len - win->rcol >= 0 );
-
- memmove( source-1, source, len - win->rcol );
- --g_status.line_buff_len;
- entab_linebuff( );
- win->file_info->dirty = GLOBAL;
- win->file_info->modified = TRUE;
- win->ll->dirty = TRUE;
- show_changed_line( win );
- } else if (g_status.command == StreamDeleteChar)
- join_line( win );
- return( OK );
- }
-
-
- /*
- * Name: eol_kill
- * Purpose: To delete everything from the cursor to the end of the line.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: If the cursor is beyond the end of the line, then this
- * command is ignored.
- */
- int eol_kill( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
-
- win = window;
- if (win->rline > win->file_info->length || win->ll->len == EOF)
- return( OK );
- copy_line( win->ll );
- detab_linebuff( );
- load_undo_buffer( win->file_info, (text_ptr)g_status.line_buff,
- g_status.line_buff_len );
- if (win->rcol < g_status.line_buff_len) {
- /*
- * truncate to delete rest of line
- */
- g_status.line_buff_len = win->rcol;
- entab_linebuff( );
- win->file_info->dirty = GLOBAL;
- win->ll->dirty = TRUE;
- show_changed_line( win );
- }
- return( OK );
- }
-
-
- /*
- * Name: undo_line
- * Purpose: To retrieve unaltered line if possible.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: Changes are made to the line buffer so the underlying text has
- * not changed. Put the unchanged line from the file into the
- * line buffer and display it.
- */
- int undo_line( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
-
- win = window;
- if (win->rline <= win->file_info->length && win->ll->len != EOF &&
- g_status.copied) {
- g_status.copied = FALSE;
- copy_line( win->ll );
- detab_linebuff( );
- win->file_info->dirty = GLOBAL;
- show_changed_line( win );
- }
- return( OK );
- }
-
-
- /*
- * Name: undo
- * Purpose: To retrieve (pop) a line from the undo stack
- * Date: September 26, 1991
- * Passed: window: pointer to current window
- * Notes: Insert an empty line into the file then pop the line in the undo
- * stack. When we pop line 0, there are no more lines on the stack.
- * Set the stack pointer to -1 to indicate an empty stack.
- */
- int undo( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
- line_list_ptr node;
-
- win = window;
- if (win->file_info->undo_count > 0) {
- entab_linebuff( );
- if (un_copy_line( win->ll, win, TRUE ) == ERROR)
- return( ERROR );
-
- node = win->file_info->undo_top;
- win->file_info->undo_top = node->next;
- win->file_info->undo_top->prev = NULL;
- --win->file_info->undo_count;
-
- node->next = node->prev = NULL;
-
- ++win->file_info->length;
-
- if (win->ll->prev != NULL)
- win->ll->prev->next = node;
- node->prev = win->ll->prev;
-
- win->ll->prev = node;
- node->next = win->ll;
- win->ll = node;
- win->ll->dirty = TRUE;
-
- if (win->ll->prev == NULL)
- win->file_info->line_list = win->ll;
-
- adjust_windows_cursor( win, 1 );
-
- /*
- * we have now undeleted a line. increment the file length and display
- * it.
- */
- win->file_info->dirty = GLOBAL;
- show_size( win );
- show_avail_mem( );
- }
- return( OK );
- }
-
-
- /*
- * Name: beg_next_line
- * Purpose: To move the cursor to the beginning of the next line.
- * Date: October 4, 1991
- * Passed: window: pointer to current window
- */
- int beg_next_line( TDE_WIN *window )
- {
- int rc;
-
- window->rcol = 0;
- rc = prepare_move_down( window );
- check_virtual_col( window, window->rcol, window->ccol );
- cursor_sync( window );
- make_ruler( window );
- show_ruler( window );
- return( rc );
- }
-
-
- /*
- * Name: next_line
- * Purpose: To move the cursor to the first character of the next line.
- * Date: October 4, 1991
- * Passed: window: pointer to current window
- */
- int next_line( TDE_WIN *window )
- {
- register int rcol;
- register TDE_WIN *win; /* put window pointer in a register */
- int rc;
-
- win = window;
- rc = prepare_move_down( win );
- rcol = first_non_blank( win->ll->line, win->ll->len );
- check_virtual_col( win, rcol, win->ccol );
- cursor_sync( win );
- make_ruler( win );
- show_ruler( win );
- return( rc );
- }
-
-
- /*
- * Name: home
- * Purpose: To move the cursor to the left of the current line.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: this routine is made a little more complicated with cursor sync.
- * if the g_status.copied flag is set we need to see from what file
- * the line_buff was copied.
- */
- int home( TDE_WIN *window )
- {
- register int rcol;
- register TDE_WIN *win; /* put window pointer in a register */
- text_ptr p;
-
- win = window;
- if (g_status.copied && win->file_info == g_status.current_window->file_info){
- rcol = first_non_blank( (text_ptr)g_status.line_buff,
- g_status.line_buff_len );
- if (is_line_blank( (text_ptr)g_status.line_buff, g_status.line_buff_len))
- rcol = 0;
- } else {
- p = win->ll->line;
- if (p == NULL)
- rcol = 0;
- else {
- rcol = first_non_blank( p, win->ll->len );
- if (is_line_blank( p, win->ll->len ))
- rcol = 0;
- }
- }
- if (win->rcol == rcol)
- rcol = 0;
- check_virtual_col( win, rcol, win->ccol );
- cursor_sync( win );
- make_ruler( win );
- show_ruler( win );
- return( OK );
- }
-
-
- /*
- * Name: goto_eol
- * Purpose: To move the cursor to the eol character of the current line.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: this routine is made a little more complicated with cursor sync.
- * if the g_status.copied flag is set we need to see from what file
- * the line_buff was copied.
- */
- int goto_eol( TDE_WIN *window )
- {
- register int rcol;
- register TDE_WIN *win; /* put window pointer in a register */
-
- win = window;
- rcol = find_end( win->ll->line, win->ll->len );
- if (g_status.copied) {
- if (win->file_info == g_status.current_window->file_info)
- rcol = find_end( (text_ptr)g_status.line_buff, g_status.line_buff_len);
- }
- win->ccol = win->start_col + rcol - win->bcol;
- check_virtual_col( win, rcol, win->ccol );
- cursor_sync( win );
- make_ruler( win );
- show_ruler( win );
- return( OK );
- }
-
-
- /*
- * Name: goto_top
- * Purpose: To move the cursor to the top of the current window.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: If the start of the file occurs before the top of the window,
- * then the start of the file is moved to the top of the window.
- */
- int goto_top( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
-
- win = window;
- entab_linebuff( );
- if (un_copy_line( win->ll, win, TRUE ) == ERROR)
- return( ERROR );
- update_line( win );
- for (; win->cline > win->top_line+win->ruler; win->cline--,win->rline--) {
- if (win->rline <= 1L)
- break;
- else {
- win->ll = win->ll->prev;
- win->bin_offset -= win->ll->len;
- }
- }
- show_curl_line( win );
- cursor_sync( win );
- return( OK );
- }
-
-
- /*
- * Name: goto_bottom
- * Purpose: To move the cursor to the bottom of the current window.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- */
- int goto_bottom( TDE_WIN *window )
- {
- register TDE_WIN *win; /* put window pointer in a register */
- int at_top;
-
- win = window;
- entab_linebuff( );
- if (un_copy_line( win->ll, win, TRUE ) == ERROR)
- return( ERROR );
- if (win->ll->len == EOF) {
- if (win->rline > 1) {
- at_top = FALSE;
- if (win->cline == win->top_line + win->ruler) {
- win->file_info->dirty = LOCAL;
- at_top = TRUE;
- }
- if (!at_top)
- update_line( win );
- --win->rline; /* ALWAYS decrement line counter */
- win->ll = win->ll->prev;
- win->bin_offset -= win->ll->len;
- if (!at_top) {
- --win->cline; /* we aren't at top of screen - so move up */
- show_curl_line( win );
- }
- }
- } else {
- update_line( win );
- for (; win->cline < win->bottom_line; win->cline++,win->rline++) {
- if (win->ll == NULL || win->ll->next == NULL || win->ll->next->len == EOF)
- break;
- else {
- win->bin_offset += win->ll->len;
- win->ll = win->ll->next;
- }
- }
- show_curl_line( win );
- }
- cursor_sync( win );
- return( OK );
- }
-
-
- /*
- * Name: set_tabstop
- * Purpose: To set the current interval between tab stops
- * Date: October 1, 1989
- * Notes: Tab interval must be reasonable, and this function will
- * not allow tabs more than g_display.ncols / 2.
- */
- int set_tabstop( TDE_WIN *window )
- {
- int tab; /* new tab interval */
- register int rc;
- register file_infos *file;
- char temp[MAX_COLS+2];
-
- my_ltoa( mode.ltab_size, temp, 10 );
- /*
- * tab interval:
- */
- rc = get_name( ed7a, window->bottom_line, temp, g_display.message_color );
- if (rc == OK && *temp != '\0') {
- tab = atoi( temp );
- if (tab < g_display.ncols / 2) {
- mode.ltab_size = tab;
- if (mode.inflate_tabs) {
- for (file=g_status.file_list; file != NULL; file=file->next)
- file->dirty = GLOBAL;
- }
- } else {
- /*
- * tab size too long
- */
- error( WARNING, window->bottom_line, ed8 );
- rc = ERROR;
- }
- }
-
- my_ltoa( mode.ptab_size, temp, 10 );
- /*
- * tab interval:
- */
- rc = get_name( ed7b, window->bottom_line, temp, g_display.message_color );
- if (rc == OK && *temp != '\0') {
- tab = atoi( temp );
- if (tab < g_display.ncols / 2) {
- mode.ptab_size = tab;
- show_tab_modes( );
- if (mode.inflate_tabs) {
- for (file=g_status.file_list; file != NULL; file=file->next)
- file->dirty = GLOBAL;
- }
- } else {
- /*
- * tab size too long
- */
- error( WARNING, window->bottom_line, ed8 );
- rc = ERROR;
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: show_line_col
- * Purpose: show current real line and column of current cursor position
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: Blank old position and display new position. current line and
- * column may take up to 12 columns, which allows the display of
- * 9,999 columns and 9,999,999 lines.
- */
- void show_line_col( TDE_WIN *window )
- {
- int i;
- register int k;
- char line_col[20], num[10];
- char *hex_digit = "0123456789abcdef";
-
- /*
- * blank out current line:column position.
- */
- memset( line_col, ' ', 13 );
- line_col[13] = '\0';
-
- /*
- * convert column to ascii and store in display buffer.
- */
- my_ltoa( window->rcol+1, num, 10 );
- i = strlen( num ) - 1;
- for (k=12; i>=0; i--, k--)
- line_col[k] = num[i];
-
- /*
- * put in colon to separate line and column
- */
- line_col[k--] = ':';
-
- /*
- * convert line to ascii and store in display buffer.
- */
- my_ltoa( window->rline, num, 10 );
- i = strlen( num ) - 1;
- for (; i>=0; i--, k--)
- line_col[k] = num[i];
-
- /*
- * find line to start line:column display then output
- */
- s_output( line_col, window->top_line-1, window->end_col-12,
- g_display.head_color );
-
- strcpy( line_col, " = " );
- i = window->rcol;
- if (g_status.copied) {
- if (mode.inflate_tabs)
- i = entab_adjust_rcol( (text_ptr)g_status.line_buff,
- g_status.line_buff_len, i );
- if (i < g_status.line_buff_len) {
- k = (int)g_status.line_buff[i];
- line_col[2] = *(hex_digit + (k >> 4));
- line_col[3] = *(hex_digit + (k & 0x000f));
- line_col[4] = 'x';
- i = TRUE;
- } else
- i = FALSE;
- } else {
- if (mode.inflate_tabs && window->ll->len != EOF)
- i = entab_adjust_rcol( window->ll->line, window->ll->len, i );
- if (i < window->ll->len) {
- k = (int)window->ll->line[i];
- line_col[2] = *(hex_digit + (k >> 4));
- line_col[3] = *(hex_digit + (k & 0x000f));
- line_col[4] = 'x';
- i = TRUE;
- } else
- i = FALSE;
- }
- s_output( line_col, g_display.mode_line, 58, g_display.mode_color );
- if (i == TRUE)
- c_output( k, 58, g_display.mode_line, g_display.mode_color );
-
-
- /*
- * if file was opened in binary mode, show offset from beginning of file.
- */
- if (window->file_info->crlf == BINARY && !window->vertical) {
- k = window->ll->line == NULL ? 0 : window->rcol;
- memset( line_col, ' ', 7 );
- line_col[7] = '\0';
- s_output( line_col, window->top_line-1, 61, g_display.head_color );
- my_ltoa( window->bin_offset + k, line_col, 10 );
- s_output( line_col, window->top_line-1, 61, g_display.head_color );
- }
- show_asterisk( window );
- }
-
-
- /*
- * Name: show_asterisk
- * Purpose: give user an indication if file is dirty
- * Date: September 16, 1991
- * Passed: window: pointer to current window
- */
- void show_asterisk( TDE_WIN *window )
- {
- c_output( window->file_info->modified ? '*' : ' ', window->start_col+4,
- window->top_line-1, g_display.head_color );
- }
-
-
- /*
- * Name: toggle_overwrite
- * Purpose: toggle overwrite-insert mode
- * Date: September 16, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_overwrite( TDE_WIN *arg_filler )
- {
- mode.insert = !mode.insert;
- show_insert_mode( );
- set_cursor_size( mode.insert ? g_display.insert_cursor :
- g_display.overw_cursor );
- return( OK );
- }
-
-
- /*
- * Name: toggle_smart_tabs
- * Purpose: toggle smart tab mode
- * Date: June 5, 1992
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_smart_tabs( TDE_WIN *arg_filler )
- {
- mode.smart_tab = !mode.smart_tab;
- show_tab_modes( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_indent
- * Purpose: toggle indent mode
- * Date: September 16, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_indent( TDE_WIN *arg_filler )
- {
- mode.indent = !mode.indent;
- show_indent_mode( );
- return( OK );
- }
-
-
- /*
- * Name: set_left_margin
- * Purpose: set left margin for word wrap
- * Date: November 27, 1991
- * Passed: window
- */
- int set_left_margin( TDE_WIN *window )
- {
- register int rc;
- char temp[MAX_COLS+2];
-
- my_ltoa( mode.left_margin + 1, temp, 10 );
- /*
- * enter left margin
- */
- rc = get_name( ed9, window->bottom_line, temp, g_display.message_color );
- if (rc == OK && *temp != '\0') {
- rc = atoi( temp ) - 1;
- if (rc < 0 || rc >= mode.right_margin) {
- /*
- * left margin out of range
- */
- error( WARNING, window->bottom_line, ed10 );
- rc = ERROR;
- } else {
- mode.left_margin = rc;
- show_all_rulers( );
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: set_right_margin
- * Purpose: set right margin for word wrap
- * Date: November 27, 1991
- * Passed: window
- */
- int set_right_margin( TDE_WIN *window )
- {
- register int rc;
- int prompt_line;
- char temp[MAX_COLS+2];
- #if defined( __UNIX__ )
- chtype display_buff[MAX_COLS+2]; /* chtype is defined in curses.h */
- #else
- char display_buff[(MAX_COLS+2)*2];
- #endif
-
- prompt_line = window->bottom_line;
- save_screen_line( 0, prompt_line, display_buff );
- set_prompt( ed11a, prompt_line );
- rc = get_yn( );
- restore_screen_line( 0, prompt_line, display_buff );
- if (rc != ERROR) {
- mode.right_justify = rc == A_YES ? TRUE : FALSE;
-
- my_ltoa( mode.right_margin + 1, temp, 10 );
- /*
- * enter right margin
- */
- rc = get_name( ed11, prompt_line, temp, g_display.message_color );
- if (rc == OK && *temp != '\0') {
- rc = atoi( temp ) - 1;
- if (rc <= mode.left_margin || rc > MAX_LINE_LENGTH) {
- /*
- * right margin out of range
- */
- error( WARNING, prompt_line, ed12 );
- rc = ERROR;
- } else {
- mode.right_margin = rc;
- show_all_rulers( );
- }
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: set_paragraph_margin
- * Purpose: set column to begin paragraph
- * Date: November 27, 1991
- * Passed: window
- * Notes: paragraph may be indented, flush, or offset.
- */
- int set_paragraph_margin( TDE_WIN *window )
- {
- register int rc;
- char temp[MAX_COLS+2];
-
- my_ltoa( mode.parg_margin + 1, temp, 10 );
- /*
- * enter paragraph margin
- */
- rc = get_name( ed13, window->bottom_line, temp, g_display.message_color );
- if (rc == OK && *temp != '\0') {
- rc = atoi( temp ) - 1;
- if (rc < 0 || rc >= mode.right_margin) {
- /*
- * paragraph margin out of range
- */
- error( WARNING, window->bottom_line, ed14 );
- rc = ERROR;
- } else {
- mode.parg_margin = rc;
- show_all_rulers( );
- }
- }
- return( rc );
- }
-
-
- /*
- * Name: toggle_crlf
- * Purpose: toggle crlf mode
- * Date: November 27, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_crlf( TDE_WIN *window )
- {
- register TDE_WIN *w;
-
- ++window->file_info->crlf;
- if (window->file_info->crlf > BINARY)
- window->file_info->crlf = CRLF;
- w = g_status.window_list;
- while (w != NULL) {
- if (w->file_info == window->file_info && w->visible)
- show_crlf_mode( w );
- w = w->next;
- }
- return( OK );
- }
-
-
- /*
- * Name: toggle_ww
- * Purpose: toggle word wrap mode
- * Date: November 27, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_ww( TDE_WIN *arg_filler )
- {
- ++mode.word_wrap;
- if (mode.word_wrap > DYNAMIC_WRAP)
- mode.word_wrap = NO_WRAP;
- show_wordwrap_mode( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_trailing
- * Purpose: toggle eleminating trainling space at eol
- * Date: November 25, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_trailing( TDE_WIN *arg_filler )
- {
- mode.trailing = !mode.trailing;
- show_trailing( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_z
- * Purpose: toggle writing control z at eof
- * Date: November 25, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_z( TDE_WIN *arg_filler )
- {
- mode.control_z = !mode.control_z;
- show_control_z( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_eol
- * Purpose: toggle writing eol character at eol
- * Date: November 25, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_eol( TDE_WIN *arg_filler )
- {
- register file_infos *file;
-
- mode.show_eol = !mode.show_eol;
- for (file=g_status.file_list; file != NULL; file=file->next)
- file->dirty = GLOBAL;
- return( OK );
- }
-
-
- /*
- * Name: toggle_search_case
- * Purpose: toggle search case
- * Date: September 16, 1991
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_search_case( TDE_WIN *arg_filler )
- {
- mode.search_case = (mode.search_case == IGNORE) ? MATCH : IGNORE;
- show_search_case( );
- build_boyer_array( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_sync
- * Purpose: toggle sync mode
- * Date: January 15, 1992
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_sync( TDE_WIN *arg_filler )
- {
- mode.sync = !mode.sync;
- show_sync_mode( );
- return( OK );
- }
-
-
- /*
- * Name: toggle_ruler
- * Purpose: toggle ruler
- * Date: March 5, 1992
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_ruler( TDE_WIN *arg_filler )
- {
- register TDE_WIN *wp;
-
- mode.ruler = !mode.ruler;
- wp = g_status.window_list;
- while (wp != NULL) {
- if (mode.ruler) {
- /*
- * there has to be more than one line in a window to display a ruler.
- * even if the ruler mode is on, we need to check the num of lines.
- */
- if (wp->bottom_line - wp->top_line >0) {
- if (wp->cline == wp->top_line)
- ++wp->cline;
- if (wp->cline > wp->bottom_line)
- wp->cline = wp->bottom_line;
- wp->ruler = TRUE;
- } else
- wp->ruler = FALSE;
- } else {
-
- /*
- * if this is the first page in a file, then we may need to "pull"
- * the file up before displaying the first page.
- */
- if (wp->rline == ((wp->cline - wp->ruler) - (wp->top_line - 1)))
- --wp->cline;
- if (wp->cline < wp->top_line)
- wp->cline = wp->top_line;
- wp->ruler = FALSE;
- }
- make_ruler( wp );
- setup_window( wp );
- if (wp->visible)
- redraw_current_window( wp );
- wp = wp->next;
- }
- return( OK );
- }
-
-
- /*
- * Name: toggle_tabinflate
- * Purpose: toggle inflating tabs
- * Date: October 31, 1992
- * Passed: arg_filler: argument to satify function prototype
- */
- int toggle_tabinflate( TDE_WIN *arg_filler )
- {
- register file_infos *file;
-
- mode.inflate_tabs = !mode.inflate_tabs;
- for (file=g_status.file_list; file != NULL; file=file->next)
- file->dirty = GLOBAL;
- show_tab_modes( );
- return( OK );
- }
-
-
- /*
- * Name: cursor_sync
- * Purpose: carry out cursor movements in all visible windows
- * Date: January 15, 1992
- * Passed: window
- * Notes: switch sync semaphore when we do this so we don't get into a
- * recursive loop. all cursor movement commands un_copy_line before
- * moving the cursor off the current line. you MUST make certain
- * that the current line is uncopied in the task routines that
- * move the cursor off the current line before calling sync.
- */
- void cursor_sync( TDE_WIN *window )
- {
- register TDE_WIN *wp;
- register file_infos *fp;
-
- if (mode.sync && mode.sync_sem) {
-
- /*
- * these functions must un_copy a line before sync'ing
- */
- #if defined( __MSC__ )
- switch (g_status.command) {
- case NextLine :
- case BegNextLine :
- case LineDown :
- case LineUp :
- case WordRight :
- case WordLeft :
- case ScreenDown :
- case ScreenUp :
- case EndOfFile :
- case TopOfFile :
- case BotOfScreen :
- case TopOfScreen :
- case JumpToLine :
- case CenterWindow :
- case CenterLine :
- case ScrollDnLine :
- case ScrollUpLine :
- case PanUp :
- case PanDn :
- case NextDirtyLine :
- case PrevDirtyLine :
- case ParenBalance :
- assert( g_status.copied == FALSE );
- break;
- default :
- break;
- }
- #endif
-
- mode.sync_sem = FALSE;
- for (wp = g_status.window_list; wp != NULL; wp = wp->next) {
- if (wp->visible && wp != window) {
-
- /*
- * when we sync a command, we need to use the same assertions
- * as those in editor( ).
- *
- * if everything is everything, these core asserts are TRUE.
- */
- #if defined( __MSC__ )
- assert( wp != NULL );
- assert( wp->file_info != NULL );
- assert( wp->file_info->line_list != NULL );
- assert( wp->file_info->line_list_end != NULL );
- assert( wp->file_info->line_list_end->len == EOF );
- assert( wp->visible == TRUE );
- assert( wp->rline >= 0 );
- assert( wp->rline <= wp->file_info->length + 1 );
- assert( wp->rcol >= 0 );
- assert( wp->rcol < MAX_LINE_LENGTH );
- assert( wp->ccol >= wp->start_col );
- assert( wp->ccol <= wp->end_col );
- assert( wp->bcol >= 0 );
- assert( wp->bcol < MAX_LINE_LENGTH );
- assert( wp->bcol == wp->rcol-(wp->ccol - wp->start_col) );
- assert( wp->start_col >= 0 );
- assert( wp->start_col < wp->end_col );
- assert( wp->end_col < g_display.ncols );
- assert( wp->cline >= wp->top_line );
- assert( wp->cline <= wp->bottom_line );
- assert( wp->top_line > 0 );
- assert( wp->top_line <= wp->bottom_line );
- assert( wp->bottom_line <= g_display.nlines );
- assert( wp->bin_offset >= 0 );
- if (wp->ll->next == NULL)
- assert( wp->ll->len == EOF );
- else
- assert( wp->ll->len >= 0 );
- assert( wp->ll->len < MAX_LINE_LENGTH );
- #endif
-
- (*do_it[g_status.command])( wp );
- show_line_col( wp );
- show_ruler_pointer( wp );
- }
- }
- mode.sync_sem = TRUE;
- for (fp = g_status.file_list; fp != NULL; fp = fp->next)
- if (fp->dirty != FALSE)
- fp->dirty = GLOBAL;
- }
- }
-
-
- /*
- * Name: editor
- * Purpose: Set up the editor structures and display changes as needed.
- * Date: June 5, 1991
- * Notes: Master editor routine.
- */
- void editor( )
- {
- char *name; /* name of file to start editing */
- register TDE_WIN *window; /* current active window */
- int c;
-
- /*
- * initialize search and seize
- */
- g_status.sas_defined = FALSE;
- for (c=0; c<SAS_P; c++)
- g_status.sas_arg_pointers[c] = NULL;
-
- g_status.file_mode = TEXT;
- /*
- * Check that user specified file to edit, if not offer help
- */
- if (g_status.argc > 1) {
- c = *g_status.argv[1];
- if (c == '/' || c == '-') {
- c = *(g_status.argv[1] + 1);
- if (c == 'f' || c == 'F' || c == 'g' || c == 'G') {
- /*
- * with search and seize their has to be at least 4 arg's, e.g.
- * tde -f findme *.c
- */
- if (c == 'F' || c == 'G') {
- mode.search_case = MATCH;
- c = bj_tolower( c );
- }
-
- if (g_status.argc >= 4) {
-
- assert( strlen( g_status.argv[2] ) < (size_t)g_display.ncols );
-
- if (c == 'f') {
- g_status.command = DefineGrep;
- strcpy( (char *)sas_bm.pattern, g_status.argv[2] );
- } else {
- g_status.command = DefineRegXGrep;
- strcpy( (char *)regx.pattern, g_status.argv[2] );
- }
-
- for (c=3; c <= g_status.argc; c++)
- g_status.sas_arg_pointers[c-3] = g_status.argv[c];
- g_status.sas_argc = g_status.argc - 3;
- g_status.sas_arg = 0;
- g_status.sas_argv = g_status.sas_arg_pointers;
- g_status.sas_found_first = FALSE;
- if (g_status.command == DefineGrep) {
- g_status.sas_defined = TRUE;
- g_status.sas_search_type = BOYER_MOORE;
- bm.search_defined = sas_bm.search_defined = OK;
- build_boyer_array( );
- c = OK;
- } else {
- c = build_nfa( );
- if (c == OK) {
- g_status.sas_defined = TRUE;
- g_status.sas_search_type = REG_EXPRESSION;
- regx.search_defined = sas_regx.search_defined = OK;
- } else
- g_status.sas_defined = FALSE;
- }
- if (c != ERROR)
- c = search_and_seize( g_status.current_window );
- } else
- c = ERROR;
- } else if (c == 'b' || c == 'B') {
- c = atoi( g_status.argv[1] + 2 );
- if (c <= 0 || c >= MAX_LINE_LENGTH)
- c = DEFAULT_BIN_LENGTH;
- ++g_status.arg;
- g_status.file_mode = BINARY;
- g_status.file_chunk = c;
- c = edit_next_file( g_status.current_window );
- } else
- c = ERROR;
- } else
- c = edit_next_file( g_status.current_window );
- } else {
- name = g_status.rw_name;
- *name = '\0';
- /*
- * file name to edit
- */
- c = get_name( ed15, g_display.nlines, name, g_display.text_color );
-
- assert( strlen( name ) < (size_t)g_display.ncols );
-
- if (c == OK) {
- if (*name != '\0')
- c = attempt_edit_display( name, GLOBAL, TEXT, 0 );
- else
- c = dir_help( (TDE_WIN *)NULL );
- }
- }
-
- g_status.stop = c == OK ? FALSE : TRUE;
- if (c == OK)
- set_cursor_size( mode.insert ? g_display.insert_cursor :
- g_display.overw_cursor );
-
- /*
- * main loop - keep updating the display and processing any commands
- * while user has not pressed the stop key
- */
- for (; g_status.stop != TRUE;) {
- window = g_status.current_window;
-
-
- /*
- * before we do any editor commands, we start out with some basic
- * assumptions.
- *
- * if everything is everything, these core asserts are TRUE.
- */
- assert( window != NULL );
- assert( window->file_info != NULL );
- assert( window->file_info->line_list != NULL );
- assert( window->file_info->line_list_end != NULL );
- assert( window->file_info->line_list_end->len == EOF );
- assert( window->visible == TRUE );
- assert( window->rline >= 0 );
- assert( window->rline <= window->file_info->length + 1 );
- assert( window->rcol >= 0 );
- assert( window->rcol < MAX_LINE_LENGTH );
- assert( window->ccol >= window->start_col );
- assert( window->ccol <= window->end_col );
- assert( window->bcol >= 0 );
- assert( window->bcol < MAX_LINE_LENGTH );
- assert( window->bcol == window->rcol-(window->ccol - window->start_col) );
- assert( window->start_col >= 0 );
- assert( window->start_col < window->end_col );
- assert( window->end_col < g_display.ncols );
- assert( window->cline >= window->top_line );
- assert( window->cline <= window->bottom_line );
- assert( window->top_line > 0 );
- assert( window->top_line <= window->bottom_line );
- assert( window->bottom_line <= g_display.nlines );
- assert( window->bin_offset >= 0 );
- if (window->ll->next == NULL)
- assert( window->ll->len == EOF );
- else
- assert( window->ll->len >= 0 );
- assert( window->ll->len < MAX_LINE_LENGTH );
-
- display_dirty_windows( window );
-
- /*
- * set the critical error handler flag to a known state before we
- * do each editor command.
- */
- ceh.flag = OK;
-
- /*
- * this code is used during testing to check the amount of memory
- * in the near heap.
- *
- * ultoa( _fmsize( window->ll ), buff, 10 );
- * s_output( "s= ", g_display.mode_line, 15, g_display.mode_color );
- * s_output( buff, g_display.mode_line, 17, g_display.mode_color );
- */
-
- /*
- * Get a key from the user. Look up the function assigned to that key.
- * All regular text keys are assigned to function 0. Text characters
- * are less than 0x100, decimal 256, which includes the ASCII and
- * extended ASCII character set.
- */
- #if defined( __UNIX__ )
- xygoto( window->ccol, window->cline );
- refresh( );
- #endif
-
- g_status.key_pressed = getkey( );
- g_status.command = getfunc( g_status.key_pressed );
- if (g_status.wrapped || g_status.key_pending) {
- g_status.key_pending = FALSE;
- g_status.wrapped = FALSE;
- show_search_message( CLR_SEARCH, g_display.mode_color );
- }
- g_status.control_break = FALSE;
- if (g_status.command >= 0 && g_status.command < NUM_FUNCS) {
- record_keys( window->bottom_line );
- (*do_it[g_status.command])( window );
- }
- }
-
-
- #if !defined( __UNIX__ )
- cls( );
- xygoto( 0, 0 );
- #endif
-
- #if defined( __UNIX__ )
- refresh( );
- #endif
- }
-
-
- /*
- * Name: display_dirty_windows
- * Purpose: Set up the editor structures and display changes as needed.
- * Date: June 5, 1991
- * Notes: Display all windows with dirty files.
- */
- void display_dirty_windows( TDE_WIN *window )
- {
- register TDE_WIN *below; /* window below current */
- register TDE_WIN *above; /* window above current */
- file_infos *file; /* temporary file structure */
-
- /*
- * update all windows that point to any file that has been changed
- */
- above = below = window;
- while (above->prev || below->next) {
- if (above->prev) {
- above = above->prev;
- show_dirty_window( above );
- }
- if (below->next) {
- below = below->next;
- show_dirty_window( below );
- }
- }
- file = window->file_info;
- if (file->dirty == LOCAL || file->dirty == GLOBAL)
- display_current_window( window );
- for (file=g_status.file_list; file != NULL; file=file->next)
- file->dirty = FALSE;
-
- /*
- * Set the cursor position at window->ccol, window->cline. Show the
- * user where in the file the cursor is positioned.
- */
- xygoto( window->ccol, window->cline );
- show_line_col( window );
- show_ruler_pointer( window );
- }
-
-
-
- /*
- * Name: show_dirty_window
- * Purpose: show changes in non-current window
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- */
- void show_dirty_window( TDE_WIN *window )
- {
- register TDE_WIN *win; /* register window pointer */
- int dirty;
-
- win = window;
- if (win->visible) {
- dirty = win->file_info->dirty;
- if (dirty == GLOBAL || dirty == NOT_LOCAL) {
- display_current_window( win );
- show_size( win );
- }
- show_asterisk( win );
- }
- }
-