/******************* 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 1040 characters. * * New editor name: tde, the Thomson-Davis Editor. * Author: Frank Davis * Date: June 5, 1991, version 1.0 * Date: July 29, 1991, version 1.1 * Date: October 5, 1991, version 1.2 * Date: January 20, 1992, version 1.3 * Date: February 17, 1992, version 1.4 * Date: April 1, 1992, version 1.5 * Date: June 5, 1992, version 2.0 * * This modification of Douglas Thomson's code is released into the * public domain, Frank Davis. You may distribute it freely. */ #include "tdestr.h" #include "common.h" #include "define.h" #include "tdefunc.h" #ifdef __TURBOC__ #include /* for making temporary file names etc */ #endif #if defined( __MSC__ ) #include #include #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 ) { return( isalnum( c ) || (c == '_') ); } /* * Name: check_virtual_col * Purpose: ensure integrity of rcol, ccol, and bcol * Date: June 5, 1991 * Passed: window: pointer to current window * rcol: real column of cursor * ccol: current or logical column of cursor */ void check_virtual_col( WINDOW *window, int rcol, int ccol ) { register int bcol; int start_col; int end_col; file_infos *file; file = window->file_info; bcol = window->bcol; start_col = window->start_col; end_col = window->end_col; /* * is logical column past end of screen? */ if (ccol > end_col) { /* ccol = start_col + (end_col + 1 - start_col) / 2; */ ccol = end_col; bcol = rcol - (ccol - start_col); file->dirty = LOCAL; } /* * is logical column behind start of screen? */ if (ccol < start_col) { if (bcol >= (start_col - ccol)) bcol -= (start_col - ccol); ccol = start_col; file->dirty = LOCAL; } /* * is real column < base column? */ if (rcol < bcol) { ccol = rcol + start_col; bcol = 0; if (ccol > end_col) { bcol = rcol; ccol = start_col; } file->dirty = LOCAL; } /* * current column + base column MUST equal real column */ if ((ccol - start_col) + bcol != rcol) { if (bcol < 0 || bcol > rcol) { bcol = rcol; file->dirty = LOCAL; } ccol = rcol - bcol + start_col; if (ccol > end_col) { bcol = rcol; ccol = start_col; file->dirty = LOCAL; } } /* * rcol CANNOT be negative */ if (rcol < 0) { rcol = bcol = 0; ccol = start_col; file->dirty = LOCAL; } if (rcol >= MAX_LINE_LENGTH) { rcol = MAX_LINE_LENGTH - 1; bcol = rcol - (ccol - start_col); } 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, because Null characters are * allowed as normal text in the file. */ 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; /* * line buffer overflow - rest of line ignored */ error( WARNING, line, utils1 ); } _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 * 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 need to leave trailing space * during BOX block operations. * See copy_line, the reverse operation. */ void un_copy_line( text_ptr text_line, WINDOW *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; int rc; file_infos *file; if (g_status.copied == TRUE) { file = window->file_info; /* * file has changed. lets create the back_up if needed */ if (mode.do_backups == TRUE) { if (file->backed_up == FALSE) { if ((rc = save_backup( window )) != ERROR) file->backed_up = TRUE; } } /* * if we are deleting the entire line, don't worry about the * deleting the trailing space, since we're deleting entire line. */ if (g_status.command == DeleteLine) del_trailing = FALSE; /* * 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 (curs_len > MAX_LINE_LENGTH) { curs_len = MAX_LINE_LENGTH; del_trailing = FALSE; } if (del_trailing && mode.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; } if (g_status.command != WordWrap) { file->dirty = GLOBAL; show_changed_line( window ); } } 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 )) { /* * buffer full, part line truncated */ error( WARNING, prompt_line, utils3 ); 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->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: line_to_undo: pointer to line in file to save * Notes: save the last 10k (1040 x 10 == 10k) of deleted text 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 unsigned int len; unsigned long max; int lf = 0; /* * find out the length of the line to save. if the line is longer * than max_line_length, then lets save only the first part of line. */ len = linelen( line_to_undo ); if (len > MAX_LINE_LENGTH) len = MAX_LINE_LENGTH; /* * increment the line length if last char is '\n'. if the last * character is not a '\n', then lets put a '\n' at the end of * line when we save it on the stack. */ if (line_to_undo[len] == '\n') ++len; else ++lf; /* * make room on the stack for the line. new lines are pushed at the * top of stack and the oldest lines are at the bottom of stack. * if the stack overflows, push the old lines off the bottom * until we have room. */ max = ptoul( g_status.max_stack ); g_status.bot_stack = cpb( g_status.bot_stack ); while (g_status.bot_stack != NULL && max - ptoul( g_status.bot_stack ) < len) g_status.bot_stack = find_prev( g_status.bot_stack ); /* * if bot_stack is NULL, then we searched past the top of the stack. * make bottom of stack point to top of stack. */ if (g_status.bot_stack == NULL) g_status.bot_stack = g_status.top_stack; /* * now slide the top of the stack towards the bottom to make room * for the line being pushed on the top of stack. */ max = ptoul( g_status.bot_stack ) - ptoul( g_status.top_stack ); hw_move( g_status.top_stack+len+lf, g_status.top_stack, max ); _fmemcpy( g_status.top_stack, line_to_undo, len ); /* * if there was no line feed at end of undo line, add one at end * of line on the stack. */ if (lf) g_status.top_stack[len+lf] = '\n'; g_status.bot_stack = nptos( g_status.bot_stack ) + len + lf; } /* * Name: load_file * Purpose: To read in a given file at 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 ) { /* * make sure this gets set properly even if there is no file. */ g_status.temp_end = g_status.end_mem; return( hw_load( name, g_status.end_mem, g_status.max_mem, &g_status.temp_end, g_display.nlines ) ); } /* * 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 to display prompt */ void set_prompt( char *prompt, int line ) { register 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 ); /* * put cursor at end of prompt */ xygoto( prompt_col, line ); } /* * Name: get_name * Purpose: To prompt the user and read the string entered in response. * Date: June 5, 1992 * Passed: prompt: prompt to offer the user * line: line to display prompt * 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: with the addition of macros in tde, this function became a little * more complicated. we have to deal with both executing macros * and macros that are the user uses when entering normal text * at the prompt. i call these local and global macros. a global * macro is when this function is called from a running macro. * the running macro can enter text and return from this function * w/o any action from the user. a local macro is when the user * presses a key inside this function, which happens quite often * when keys are assigned to ASCII and Extended ASCII characters. */ 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; int local_macro = FALSE; int next; /* * set up prompt and default */ strcpy( buffer, prompt ); plen = strlen( prompt ); answer = buffer + plen; strcpy( answer, name ); /* * let user edit default 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 ); if (g_status.macro_executing) { next = g_status.macro_next; g_status.macro_next = macro.strokes[g_status.macro_next].next; if (g_status.macro_next != -1) { c = macro.strokes[g_status.macro_next].key; func = getfunc( c ); if (func == PlayBack) { stop = TRUE; g_status.macro_next = next; } } else { c = 0x100; func = AbortCommand; stop = TRUE; } } else { if (local_macro == FALSE) { 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; if (func == PlayBack) { local_macro = TRUE; next = macro.first_stroke[ c-256 ]; c = macro.strokes[next].key; func = getfunc( c ); next = macro.strokes[next].next; } else { g_status.key_pressed = c; record_keys( line ); } } else { if (next != -1) { c = macro.strokes[next].key; next = macro.strokes[next].next; } else { local_macro = FALSE; c = 0x100; } func = getfunc( c ); } } switch (func) { case ToggleSearchCase : bm.search_case = bm.search_case == IGNORE ? MATCH : 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 = (char)c; c_output( c, col, line, color ); ++cp; ++col; } } break; } first = FALSE; } restore_screen_line( 0, line, line_buff ); return( func == AbortCommand ? ERROR : OK ); } /* * Name: get_sort_order * Purpose: To prompt the user and get sort order * Date: June 5, 1992 * Passed: window * Returns: OK if user entered something * ERROR if user aborted the command */ int get_sort_order( WINDOW *window ) { register int c; int col; char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ save_screen_line( 0, window->bottom_line, line_buff ); /* * sort ascending or descending */ s_output( utils4, window->bottom_line, 0, g_display.message_color ); c = strlen( utils4 ); eol_clear( c, window->bottom_line, g_display.text_color ); xygoto( c, window->bottom_line ); do { c = getkey( ); col = getfunc( c ); if (c == ESC) col = AbortCommand; } while (col != AbortCommand && c != 'A' && c != 'a' && c != 'D' && c != 'd'); switch ( c ) { case 'A': case 'a': sort.sort_order = ASCENDING; break; case 'D': case 'd': sort.sort_order = DESCENDING; break; } restore_screen_line( 0, window->bottom_line, line_buff ); return( col == AbortCommand ? ERROR : OK ); } /* * 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_lr * Purpose: To input a response of yes or no. * Date: June 1, 1991 * Returns: the user's answer, LEFT or RIGHT. */ int get_lr( void ) { int c; /* the user's response */ register int rc; /* return code */ for (rc=OK; rc == OK;) { c = getkey( ); if (getfunc( c ) == AbortCommand || c == ESC) rc = ERROR; else { switch ( c ) { case 'L': case 'l': rc = LEFT; break; case 'R': case 'r': rc = RIGHT; 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 */ register int rc; /* return code */ 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 * Notes: line: ususally line to is display "<=== eof ===>" */ void show_eof( WINDOW *window ) { register int color; char temp[MAX_COLS+2]; strcpy( temp, mode.eof ); color = window->end_col + 1 - window->start_col; if (strlen( temp ) > (unsigned)color) temp[color] = '\0'; color = g_display.eof_color; window_eol_clear( window, color ); s_output( temp, window->cline, window->start_col, color ); } /* * Name: display_current_window * Purpose: display text in current window * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: use a temporary window structure, "w", to do the dirty work. */ void display_current_window( WINDOW *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 */ register int i; /* register variable */ WINDOW w; /* scratch window structure */ long length; /* length of file. number of lines in the file */ int curl; /* current line on screen, window->cline */ /* * initialize the scratch variables */ number = window->bottom_line - ((window->top_line + window->ruler) - 1); dup_window_info( &w, window ); w.cursor = cpb( w.cursor ); curl = window->cline; count = window->cline - (window->top_line + window->ruler); length = window->file_info->length; /* * find the first text line on the screen */ for (i=count; i>0; i--) { p = find_prev( w.cursor ); if (p) { w.cursor = p; --w.cline; --w.rline; } } /* * start at the top of the window and display a window full of text */ w.cursor = cpf( w.cursor ); for (i=number; i>0; i--) { if (w.cursor) { if (w.rline <= length) { /* * if this is window->cline, do not show the line because we * show the curl at the end of this function. don't show it twice */ if (w.cline != curl) update_line( &w ); } else show_eof( &w ); w.cursor = find_next( w.cursor ); } else window_eol_clear( &w, COLOR_TEXT ); ++w.cline; ++w.rline; } show_asterisk( window ); show_curl_line( window ); } /* * Name: redraw_screen * Purpose: display all visible windows * Date: June 5, 1991 * Passed: window: pointer to current window */ int redraw_screen( WINDOW *window ) { register WINDOW *above; /* window above current */ register WINDOW *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( ); return( OK ); } /* * Name: redraw_current_window * Purpose: redraw all info in window * Date: July 13, 1991 * Passed: window: pointer to current window */ void redraw_current_window( WINDOW *window ) { /* * display the current window */ if (window->visible) { display_current_window( window ); show_window_header( window ); show_ruler( window ); show_ruler_pointer( window ); if (window->vertical) show_vertical_separator( window ); } } /* * Name: show_changed_line * Purpose: Only one line was changed in file, just show it * Date: June 5, 1991 * Passed: window: pointer to current window */ void show_changed_line( WINDOW *window ) { WINDOW *above; /* window above current */ WINDOW *below; /* window below current */ WINDOW w; /* scratch window structure */ long changed_line; /* line number in file that was changed */ long top_line, bottom_line; /* top and bottom line in file on screen */ int line_on_screen; /* is changed line on screen? */ file_infos *file; /* file pointer */ file = window->file_info; if ((file->dirty == LOCAL || file->dirty == GLOBAL) && window->visible) show_curl_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 ); } /* * is this window the changed file and is it visible? */ if (w.file_info == window->file_info && w.visible) { /* * calculate file lines at top and bottom of screen. * the changed line may not be the curl in other windows. */ line_on_screen = FALSE; top_line = w.rline - (w.cline - (w.top_line + w.ruler)); bottom_line = w.rline + (w.bottom_line - w.cline); if (changed_line == w.rline) line_on_screen = CURLINE; else if (changed_line < w.rline && changed_line >= top_line) { line_on_screen = NOTCURLINE; 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 = NOTCURLINE; w.cursor = cpf( w.cursor ); while (w.rline < changed_line) { w.cursor = find_next( w.cursor ); ++w.rline; ++w.cline; } } /* * display the changed line if on screen */ if (line_on_screen == NOTCURLINE) update_line( &w ); else if (line_on_screen == CURLINE) show_curl_line( &w ); } } } file->dirty = FALSE; } /* * Name: show_curl_line * Purpose: show current line in curl color * Date: January 16, 1992 * Passed: window: pointer to current window */ void show_curl_line( WINDOW *window ) { int text_color; text_color = g_display.text_color; g_display.text_color = g_display.curl_color; update_line( window ); g_display.text_color = text_color; } /* * 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( WINDOW *dw, WINDOW *sw ) { memcpy( dw, sw, sizeof( WINDOW ) ); } /* * 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: pointer to 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( WINDOW *window, long net_change ) { register WINDOW *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 and file are the same, use rline to compare * the current positions in the file. DO NOT use cursor positions * to compare current positions. Text may or may not be inserted * or deleted at the window->cursor position - we can un_copy_line * at any position or line in the file not just the window->cursor * line. */ if (next_file == file) { if (next->rline > window->rline) next->cursor = addltop( net_change, next->cursor ); } else { /* * else next_file is not same as file. see if the text * buffer for next_file is greater than file text buffer. */ 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: pointer to 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 lines * 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( WINDOW *window, int line_change ) { register WINDOW *next; register int reset; text_ptr p; int i; file_infos *file; file_infos *next_file; MARKER *marker; long length; 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 + next->ruler; } else { next_file->end_text = cpb( next_file->end_text ); p = next_file->end_text - 1; p = find_prev( p ); next->cursor = p != NULL ? p : next_file->end_text - 1; next->rline = next_file->length; } if (next->rline < (next->cline -(next->top_line+next->ruler-1))) next->cline = (int)next->rline+(next->top_line+next->ruler)-1; file->dirty = NOT_LOCAL; } } } next = next->next; } /* * now adjust any markers. */ length = file->length; for (i=0; i<3; i++) { marker = &file->marker[i]; if (marker->rline > window->rline) { marker->rline += line_change; if (marker->rline < 1L) marker->rline = 1L; else if (marker->rline > length) marker->rline = length; } } } /* * Name: adjust_start_end * Purpose: a file has been modified - must restore all start and end pointers * Date: June 5, 1991 * Passed: mod_file: 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; /* mst == Mod_file->Start_Text */ unsigned long ost; /* ost == Open_file_Start_Text */ register 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 of the first non-blank character * 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: is_line_blank * Purpose: is line empty or does it only contain spaces? * Date: November 28, 1991 * Passed: s: the string to search * Returns: TRUE if line is blank or FALSE if something is in line */ int is_line_blank( char far *s ) { s = cpf( s ); while (*s == ' ') ++s; return( *s == '\n' || *s == CONTROL_Z ); } /* * Name: page_up * Purpose: To move the cursor one page up the window * Date: June 5, 1991 * Passed: window: pointer to 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 movement stops. */ int page_up( WINDOW *window ) { int i; /* count of lines scanned */ int rc = OK; /* default return code */ text_ptr p, q; /* previous lines */ register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); if (win->rline != (win->cline - (win->top_line + win->ruler - 1))) { q = cpb( win->cursor ); i = win->cline - (win->top_line + win->ruler - 1); if (( win->rline - i) < win->page) { i = (int)win->rline - (win->cline - (win->top_line + win->ruler - 1)); for (; i>0; i--) { if ((p = find_prev( q )) != NULL) q = p; } win->rline = (win->cline-(win->top_line + win->ruler -1)) + win->page; } else { for (i=win->page; i>0; i--) { if ((p = find_prev( q )) != NULL) q = p; } } win->cursor = q; win->rline -= win->page; win->file_info->dirty = LOCAL; } else rc = ERROR; sync( win ); return( rc ); } /* * Name: page_down * Purpose: To move the cursor one page down the window * Date: June 5, 1991 * Passed: window: pointer to 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 movement stops. */ int page_down( WINDOW *window ) { int i, k; /* count of lines scanned so far */ int rc = OK; text_ptr p, q; /* lines below cursor */ register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); q = cpf( win->cursor ); k = win->cline - (win->top_line + win->ruler); for (i=0; i < win->page && *q != CONTROL_Z; i++, k++) { p = find_next( q ); if (p != NULL) q = p; else break; } if (k >= win->page) { win->cursor = q; win->rline += i; win->cline = win->cline + i - win->page; win->file_info->dirty = LOCAL; } else rc = ERROR; sync( win ); return( rc ); } /* * Name: scroll_down * Purpose: scroll window down one line * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: If there is a line to scroll_down, make the window LOCAL dirty. * We have to redraw the screen anyway, so don't update here. */ int scroll_down( WINDOW *window ) { int rc = OK; text_ptr next; register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); if (win->cline == win->top_line + win->ruler) { win->cursor = cpf( win->cursor ); if ((next = find_next( win->cursor )) != NULL) { win->cursor = next; ++win->rline; win->file_info->dirty = LOCAL; } else rc = ERROR; } else { --win->cline; win->file_info->dirty = LOCAL; } sync( win ); return( rc ); } /* * Name: scroll_up * Purpose: To scroll the window up one line * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: If this is the first page, then update screen here. Else, make * the window LOCAL dirty because we have to redraw screen. */ int scroll_up( WINDOW *window ) { int rc = OK; text_ptr prev; register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); win->cursor = cpb( win->cursor ); if (win->rline != 1) { if (win->rline == (win->cline - (win->top_line + win->ruler - 1))) { if (!mode.sync) update_line( win ); if ((prev = find_prev( win->cursor )) != NULL) win->cursor = prev; --win->rline; --win->cline; if (!mode.sync) show_curl_line( win ); } else { if (win->cline == win->bottom_line) { if ((prev = find_prev( win->cursor )) != NULL) { win->cursor = prev; --win->rline; win->file_info->dirty = LOCAL; } } else { ++win->cline; win->file_info->dirty = LOCAL; } } } else rc = ERROR; sync( win ); return( rc ); } /* * Name: fixed_scroll_up * Purpose: To leave cursor on same logical line and scroll text up * Date: September 1, 1991 * Passed: window: pointer to current window * Notes: If cursor is on first page then do not scroll. */ int fixed_scroll_up( WINDOW *window ) { int rc = OK; text_ptr prev; register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); win->cursor = cpb( win->cursor ); /* * see if cursor is on the first page. if it's not then fixed_scroll_up. */ if (win->rline != (win->cline+1 - (win->top_line + win->ruler))) { if ((prev = find_prev( win->cursor )) != NULL) { win->cursor = prev; --win->rline; win->file_info->dirty = LOCAL; } } else rc = ERROR; sync( win ); return( rc ); } /* * Name: fixed_scroll_down * Purpose: To leave cursor on same logical line and scroll text down * Date: September 1, 1991 * Passed: window: pointer to current window * Notes: If cursor is on last line in file then do not scroll. */ int fixed_scroll_down( WINDOW *window ) { int rc = OK; text_ptr next; register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); win->cursor = cpf( win->cursor ); if ((next = find_next( win->cursor )) != NULL) { win->cursor = next; ++win->rline; win->file_info->dirty = LOCAL; } else rc = ERROR; sync( win ); return( rc ); } /* * Name: file_file * Purpose: To file the current file to disk. * Date: September 17, 1991 * Passed: window: pointer to current window */ int file_file( WINDOW *window ) { if (save_file( window ) == OK) finish( window ); return( OK ); } /* * Name: save_file * Purpose: To save the current file to disk. * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: If anything goes wrong, then the modified flag is set. * If the file is saved successfully, then modified flag is * cleared. */ int save_file( WINDOW *window ) { char name[MAX_COLS]; /* name of file to be saved */ register file_infos *file; int rc; un_copy_line( window->cursor, window, TRUE ); file = window->file_info; if (file->modified == FALSE) return( OK ); /* * set up file name */ strcpy( name, file->file_name ); /* * see if there was a file name - if not, then make the user * supply one. */ if (strlen( name ) == 0) rc = save_as_file( window ); else { /* * save the file */ rc = write_to_disk( window, name ); if (rc != ERROR) { file->modified = FALSE; file->new_file = FALSE; } } return( rc ); } /* * Name: save_backup * Purpose: To save a backup copy of the current file to disk. * Date: June 5, 1991 * Passed: window: pointer to current window */ int save_backup( WINDOW *window ) { /* * set up file name */ return( write_to_disk( window, window->file_info->backup_fname ) ); } /* * Name: write_to_disk * Purpose: To write file from memory to disk * Date: June 5, 1991 * Passed: window: pointer to current window * fname: file name to save on disk */ int write_to_disk( WINDOW *window, char *fname ) { 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; int fattr; file = window->file_info; prompt_line = window->bottom_line; /* * set up file name */ strcpy( name, fname ); /* * save the file */ save_screen_line( 0, prompt_line, line_buff ); eol_clear( 0, prompt_line, g_display.message_color ); /* * saving */ combine_strings( status_line, utils6, name, "'" ); s_output( status_line, prompt_line, 0, g_display.message_color ); file->end_text = cpb( file->end_text ); if ((rc = hw_save( name, file->start_text, file->end_text - mode.control_z, NOTMARKED )) == ERROR) { if (ceh.flag != ERROR) { if (get_fattr( name, &fattr ) == OK && fattr & READ_ONLY) /* * file is read only */ combine_strings( status_line, utils7a, name, utils7b ); else /* * cannot write to */ combine_strings( status_line, utils8, name, "'" ); error( WARNING, prompt_line, status_line ); } } restore_screen_line( 0, prompt_line, line_buff ); return( rc ); } /* * Name: save_as_file * Purpose: To save the current file to disk, but under a new name. * Date: June 5, 1991 * Passed: window: pointer to current window */ int save_as_file( WINDOW *window ) { char name[MAX_COLS]; /* new name for file */ char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ register file_infos *file; int prompt_line; int rc; int fattr; register WINDOW *win; /* put window pointer in a register */ win = window; un_copy_line( win->cursor, win, TRUE ); /* * read in name */ prompt_line = win->bottom_line; file = win->file_info; save_screen_line( 0, prompt_line, line_buff ); name[0] = '\0'; /* * new file name: */ if ((rc = get_name( utils9, prompt_line, name, g_display.message_color )) == OK) { /* * make sure it is OK to overwrite any existing file */ rc = get_fattr( name, &fattr ); if (rc == OK) { /* file exists */ /* * overwrite existing file? */ set_prompt( utils10, prompt_line ); if (get_yn( ) != A_YES || change_mode( name, prompt_line ) == ERROR) rc = ERROR; } if (rc != ERROR) rc = write_to_disk( win, name ); } restore_screen_line( 0, prompt_line, line_buff ); return( rc ); } /* * Name: show_window_header * Purpose: show file stuff in window header * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: Clear line and display header in a lite bar */ void show_window_header( WINDOW *window ) { char status_line[MAX_COLS+2]; /* status line at top of window */ register WINDOW *win; /* put window pointer in a register */ int len; win = window; len = win->vertical ? win->end_col + 1 - win->start_col : win->end_col; memset( status_line, ' ', len ); status_line[len] = '\0'; s_output( status_line, win->top_line-1, win->start_col,g_display.head_color); show_window_number_letter( win ); show_window_fname( win ); show_size_name( win ); show_size( win ); show_line_col( win ); } /* * Name: show_window_number_letter * Purpose: show file number and letter of window in lite bar * Date: June 5, 1991 * Passed: window: pointer to current window */ void show_window_number_letter( WINDOW *window ) { int col; char temp[10]; register WINDOW *win; /* put window pointer in a register */ win = window; col = win->start_col; s_output( " ", win->top_line-1, col, g_display.head_color ); itoa( win->file_info->file_no, temp, 10 ); s_output( temp, win->top_line-1, strlen( temp ) > 1 ? col : col+1, g_display.head_color ); c_output( win->letter, col+2, win->top_line-1, g_display.head_color ); } /* * Name: show_window_fname * Purpose: show file name in window header. * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: Clear name field and display name in a lite bar */ void show_window_fname( WINDOW *window ) { char status_line[MAX_COLS+2]; /* status line at top of window */ register int fattr; char *p; register WINDOW *win; /* put window pointer in a register */ int col; int len; win = window; col = win->start_col; len = win->vertical ? 11 : FNAME_LENGTH; memset( status_line, ' ', len ); status_line[len] = '\0'; s_output( status_line, win->top_line-1, col+5, g_display.head_color ); strcpy( status_line, win->file_info->file_name ); p = status_line; if (win->vertical) { len = strlen( status_line ); for (p=status_line+len;*(p-1) != ':' && *(p-1) != '\\' && p>status_line;) --p; } else { status_line[FNAME_LENGTH] = '\0'; p = status_line; } s_output( p, win->top_line-1, col+5, g_display.head_color ); if (!win->vertical) { fattr = win->file_info->file_attrib; p = status_line; *p++ = fattr & ARCHIVE ? 'A' : '-'; *p++ = fattr & SYSTEM ? 'S' : '-'; *p++ = fattr & HIDDEN ? 'H' : '-'; *p++ = fattr & READ_ONLY ? 'R' : '-'; *p = '\0'; s_output( status_line, win->top_line-1, col+52, g_display.head_color ); } } /* * Name: show_size_name * Purpose: show ' s=' line lite bar header * Date: June 5, 1991 * Passed: window: pointer to current window */ void show_size_name( WINDOW *window ) { if (!window->vertical) s_output( " s=", window->top_line-1, 57, g_display.head_color ); } /* * Name: show_size * Purpose: show number of lines in file * Date: June 5, 1991 * Passed: window: pointer to current window */ void show_size( WINDOW *window ) { char csize[20]; if (!window->vertical) { s_output( " ", window->top_line-1, 60, g_display.head_color ); ltoa( window->file_info->length, csize, 10 ); s_output( csize, window->top_line-1, 60, g_display.head_color ); } } /* * Name: quit * Purpose: To close the current window without saving the current file. * Date: June 5, 1991 * Passed: window: pointer to 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. */ int quit( WINDOW *window ) { int prompt_line; char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute */ register file_infos *file; WINDOW *wp; int count = 0; int rc = OK; 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 ); /* * abandon changes (y/n) */ set_prompt( utils12, prompt_line ); if (get_yn( ) != A_YES) rc = ERROR; restore_screen_line( 0, prompt_line, line_buff ); } /* * remove window, allocate screen lines to other windows etc */ if (rc == OK) finish( window ); return( OK ); } /* * Name: move_up * Purpose: To move the cursor up one line * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: If the cursor is at the top of the window, then the file must * be scrolled down. */ int move_up( WINDOW *window ) { int rc = OK; text_ptr p; /* the previous line on the screen */ register WINDOW *win; /* put window pointer in a register */ int at_top = FALSE; /* is cline at top of screen? */ win = window; un_copy_line( win->cursor, win, TRUE ); /* * if no previous line, give up */ win->cursor = cpb( win->cursor ); if ((p = find_prev( win->cursor )) != NULL) { if (win->cline == win->top_line + win->ruler) { win->file_info->dirty = LOCAL; at_top = TRUE; } if (!at_top) update_line( win ); win->cursor = p; --win->rline; /* ALWAYS decrement line counter */ if (!at_top) { --win->cline; /* we aren't at top of screen - so move up */ show_curl_line( win ); } } else rc = ERROR; sync( win ); return( rc ); } /* * Name: move_down * Purpose: To move the cursor down one line * Date: June 5, 1991 * Passed: window: pointer to 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 line up until it is at top of screen. */ int move_down( WINDOW *window ) { int rc; rc = prepare_move_down( window ); sync( window ); return( rc ); } /* * Name: prepare_move_down * Purpose: Do the stuff needed to move the cursor down one line. * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: Put all the stuff needed to move the cursor down one line in * one function, so several functions can use the guts of the * algorithm. */ int prepare_move_down( WINDOW *window ) { int rc = OK; text_ptr p; register WINDOW *win; /* put window pointer in a register */ int at_bottom = FALSE; /* is cline at bottom of screen */ win = window; un_copy_line( win->cursor, win, TRUE ); if (win->cline == win->bottom_line) { win->file_info->dirty = LOCAL; at_bottom = TRUE; } if (!at_bottom) update_line( win ); win->cursor = cpf( win->cursor ); if ((p = find_next( win->cursor )) != NULL) { win->cursor = p; ++win->rline; /* ALWAYS increment line counter */ if (!at_bottom) { ++win->cline; /* if not at bottom of screen move down */ show_curl_line( win ); } } else if (win->cline > win->top_line + win->ruler) { --win->cline; win->file_info->dirty = LOCAL; rc = ERROR; } else rc = ERROR; return( rc ); } /* * Name: move_left * Purpose: To move the cursor left one character * Date: June 5, 1991 * Passed: window: pointer to 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. */ int move_left( WINDOW *window ) { int new_ruler = FALSE; if (window->ccol > window->start_col) { show_ruler_char( window ); --window->ccol; --window->rcol; } else if (window->ccol == window->start_col && window->rcol > 0) { --window->rcol; --window->bcol; window->file_info->dirty = LOCAL; new_ruler = TRUE; } sync( window ); if (new_ruler) { make_ruler( window ); show_ruler( window ); } return( OK ); } /* * Name: move_right * Purpose: To move the cursor right one character * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: If the cursor is already at the right of the screen (logical * column 80) then scroll horizontally right. */ int move_right( WINDOW *window ) { int new_ruler = FALSE; if (window->rcol < g_display.line_length - 1) { if (window->ccol < window->end_col) { show_ruler_char( window ); ++window->ccol; ++window->rcol; } else if (window->ccol == window->end_col) { ++window->rcol; ++window->bcol; window->file_info->dirty = LOCAL; new_ruler = TRUE; } } sync( window ); if (new_ruler) { make_ruler( window ); show_ruler( window ); } return( OK ); } /* * Name: scroll_left * Purpose: To scroll the screen left one character * Date: January 5, 1992 * Passed: window: pointer to current window */ int scroll_left( WINDOW *window ) { if (window->bcol == 0) { if (window->ccol > window->start_col) { show_ruler_char( window ); --window->ccol; --window->rcol; } } else if (window->bcol > 0 ) { /* * Scroll window left function: * --window->bcol; * if (window->ccol < g_display.ncols - 1) * ++window->ccol; * else * --window->rcol; */ --window->bcol; --window->rcol; window->file_info->dirty = LOCAL; make_ruler( window ); show_ruler( window ); } sync( window ); return( OK ); } /* * Name: scroll_right * Purpose: To scroll the screen right one character * Date: January 5, 1992 * Passed: window: pointer to current window */ int scroll_right( WINDOW *window ) { if (window->rcol < g_display.line_length - 1) { /* * scroll screen right function: * if (window->ccol > 0) * --window->ccol; * else * ++window->rcol; */ ++window->rcol; ++window->bcol; window->file_info->dirty = LOCAL; make_ruler( window ); show_ruler( window ); } sync( window ); return( OK ); } /* * Name: word_left * Purpose: To move the cursor left one word * Date: June 5, 1991 * Passed: window: pointer to 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. */ int word_left( WINDOW *window ) { text_ptr p; /* text pointer */ int len; /* length of current line */ register int c; /* character at pointer */ register int check = 0; int rc = OK; WINDOW w; un_copy_line( window->cursor, window, TRUE ); dup_window_info( &w, window ); p = cpf( window->cursor ); len = linelen( p ); p += window->rcol > len ? len : 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) { for (; c != CONTROL_Z && !myisalnum( c ); check++) { c = *--p; if (check > 8000) { p = cpb( p ); check = 0; } } if (c != CONTROL_Z) { for (; c != CONTROL_Z && myisalnum( c ); check++) { c = *--p; if (check > 8000) { p = cpb( p ); check = 0; } } find_adjust( window, ++p ); if (w.rline != window->rline && !window->file_info->dirty) { update_line( &w ); show_curl_line( window ); } make_ruler( window ); show_ruler( window ); } } if (c == CONTROL_Z) rc = ERROR; sync( window ); return( rc ); } /* * Name: word_right * Purpose: To move the cursor right one word * Date: June 5, 1991 * Passed: window: pointer to 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. */ int word_right( WINDOW *window ) { int len; /* length of current line */ text_ptr p; /* text pointer */ register int c; /* character at pointer */ register int check = 0; int rc = OK; WINDOW w; un_copy_line( window->cursor, window, TRUE ); dup_window_info( &w, window ); p = cpf( window->cursor ); len = linelen( p ); p += window->rcol > len ? len : 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 ); make_ruler( window ); show_ruler( window ); } else rc = ERROR; if (w.rline != window->rline && !window->file_info->dirty) { update_line( &w ); show_curl_line( window ); } sync( window ); return( rc ); } /* * Name: center_window * Purpose: To place the current line or cursor in the center of a window. * Date: June 5, 1991 * Passed: window: pointer to current window */ int center_window( WINDOW *window ) { int center; int center_line; int diff; register file_infos *file; int i; register WINDOW *win; /* put window pointer in a register */ win = window; file = win->file_info; center = (win->bottom_line + 1 - win->top_line) / 2 - win->ruler; center_line = win->top_line + win->ruler + center; diff = center_line - win->cline; if (g_status.command == CenterWindow) { un_copy_line( win->cursor, win, TRUE ); if (diff > 0) { if (win->rline + diff <= file->length) { update_line( win ); win->cline += diff; win->rline += diff; win->cursor = cpf( win->cursor ); for (i=0; icursor = find_next( win->cursor ); show_curl_line( win ); } } else if (diff < 0) { update_line( win ); win->cline += diff; win->rline += diff; win->cursor = cpb( win->cursor ); for (i=diff; i<0; i++) win->cursor = find_prev( win->cursor ); show_curl_line( win ); } } else if (g_status.command == CenterLine) { if (diff > 0) { win->cline += diff; if ((long)(win->cline+1 - (win->top_line + win->ruler)) > win->rline) win->cline = (win->top_line + win->ruler) - 1 + (int)win->rline; file->dirty = LOCAL; } else if (diff < 0) { win->cline = win->cline + diff; file->dirty = LOCAL; } } sync( win ); return( OK ); } /* * Name: horizontal_screen_right * Purpose: To move the cursor one screen to the right * Date: September 13, 1991 * Passed: window: pointer to current window * Notes: Add 80 columns to the real cursor. If the cursor is past the * maximum line length then move it back. */ int horizontal_screen_right( WINDOW *window ) { int col; col = window->rcol; col += (window->end_col + 1 - window->start_col); if (col < MAX_LINE_LENGTH) { window->rcol = col; window->bcol += (window->end_col + 1 - window->start_col); window->file_info->dirty = LOCAL; check_virtual_col( window, window->rcol, window->ccol ); make_ruler( window ); show_ruler( window ); } sync( window ); return( OK ); } /* * Name: horizontal_screen_left * Purpose: To move the cursor one screen to the left * Date: September 13, 1991 * Passed: window: pointer to current window * Notes: Subtract screen width from 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. */ int horizontal_screen_left( WINDOW *window ) { int screen_width; screen_width = window->end_col + 1 - window->start_col; if (window->rcol - screen_width < 0) { if (window->bcol != 0) { window->bcol = 0; window->file_info->dirty = LOCAL; } } else { window->rcol -= screen_width; window->bcol -= screen_width; if (window->bcol < 0) window->bcol = 0; window->file_info->dirty = LOCAL; } check_virtual_col( window, window->rcol, window->ccol ); sync( window ); make_ruler( window ); show_ruler( window ); return( OK ); } /* * Name: set_marker * Purpose: To set file marker * Date: December 28, 1991 * Passed: window: pointer to current window */ int set_marker( WINDOW *window ) { register MARKER *marker; /* put the marker in a register */ marker = &window->file_info->marker[g_status.command - SetMark1]; marker->rline = window->rline; marker->rcol = window->rcol; marker->ccol = window->ccol; marker->bcol = window->bcol; marker->marked = TRUE; return( OK ); } /* * Name: goto_marker * Purpose: To goto a file marker * Date: December 28, 1991 * Passed: window: pointer to current window */ int goto_marker( WINDOW *window ) { int m; file_infos *file; text_ptr p; long i; long number; MARKER *marker; register WINDOW *win; /* put window pointer in a register */ int rc; win = window; m = g_status.command - GotoMark1; file = win->file_info; marker = &file->marker[m]; if (marker->marked) { un_copy_line( win->cursor, win, TRUE ); file->dirty = LOCAL; if (marker->rline > file->length) marker->rline = file->length; number = marker->rline; p = win->cursor; i = win->rline; if (number < win->rline) { p = cpb( p ); for (; i>number; i--) p = find_prev( p ); } else { p = cpf( p ); for (; icursor = p; win->rline = marker->rline; win->rcol = marker->rcol; win->ccol = marker->ccol; win->bcol = marker->bcol; if (win->rline < (win->cline - ((win->top_line + win->ruler) - 1))) win->cline = (int)win->rline + (win->top_line + win->ruler) - 1; check_virtual_col( win, win->rcol, win->ccol ); make_ruler( window ); show_ruler( window ); rc = OK; } else { if (m == 9) m = -1; *(utils13 + 7) = (char)('0' + m + 1); /* * marker not set */ error( WARNING, win->bottom_line, utils13 ); rc = ERROR; } return( rc ); } /* * Name: change_fattr * Purpose: To change the file attributes * Date: December 31, 1991 * Passed: window: pointer to current window */ int change_fattr( WINDOW *window ) { char name[MAX_COLS]; /* new name for file */ char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ file_infos *file; WINDOW *wp; int prompt_line; register int ok; unsigned char fattr; char *s; int rc; prompt_line = window->bottom_line; save_screen_line( 0, prompt_line, line_buff ); name[0] = '\0'; /* * enter new file attributes */ if ((ok = get_name( utils14, prompt_line, name, g_display.message_color )) == OK) { if (*name != '\0') { fattr = 0; s = name; while (ok = *s++) { switch (ok) { case 'a' : case 'A' : fattr |= ARCHIVE; break; case 's' : case 'S' : fattr |= SYSTEM; break; case 'h' : case 'H' : fattr |= HIDDEN; break; case 'r' : case 'R' : fattr |= READ_ONLY; break; } } file = window->file_info; if (set_fattr( file->file_name, fattr )) /* * new file attributes not set */ error( WARNING, prompt_line, utils15 ); else { file->file_attrib = fattr; for (wp=g_status.window_list; wp!=NULL; wp=wp->next) { if (wp->file_info == file && wp->visible) show_window_fname( wp ); } } } rc = OK; } else rc = ERROR; restore_screen_line( 0, prompt_line, line_buff ); return( rc ); } /* * Name: date_time_stamp * Purpose: put system date and time into file at cursor position * Date: June 5, 1992 * Passed: window: pointer to current window */ int date_time_stamp( WINDOW *window ) { char date_time[MAX_COLS]; char stuff[20]; register char *dt; int year, month, day; int hours, minutes; int one, two, three; int i; int pm; get_date( &year, &month, &day, &i ); get_time( &hours, &minutes, &i, &i ); dt = date_time; /* * mod year with 100 if needed. */ switch (mode.date_style) { case MM_DD_YY : case DD_MM_YY : case YY_MM_DD : year = year % 100; } switch (mode.date_style) { case MM_DD_YY : case MM_DD_YYYY : one = month; two = day; three = year; break; case DD_MM_YY : case DD_MM_YYYY : one = day; two = month; three = year; break; case YY_MM_DD : case YYYY_MM_DD : one = year; two = month; three = day; break; } strcpy( dt, itoa( one, stuff, 10 ) ); strcat( dt, "-" ); strcat( dt, itoa( two, stuff, 10 ) ); strcat( dt, "-" ); strcat( dt, itoa( three, stuff, 10 ) ); strcat( dt, " " ); if (mode.time_style == _12_HOUR) { pm = FALSE; if (hours >= 12 && hours < 24) pm = TRUE; if (hours < 1) hours = 12; else if (hours >= 13) hours -= 12; } if (hours < 1) strcat( dt, "0" ); strcat( dt, itoa( hours, stuff, 10 ) ); strcat( dt, ":" ); if (minutes < 10) strcat( dt, "0" ); strcat( dt, itoa( minutes, stuff, 10 ) ); if (mode.time_style == _12_HOUR) strcat( dt, pm == FALSE ? "am" : "pm" ); strcat( dt, " " ); return( add_chars( dt, window ) ); } /* * Name: add_chars * Purpose: insert string into file * Date: June 5, 1992 * Passed: string: string to add to file * window: pointer to current window */ int add_chars( char *string, WINDOW *window ) { int rc = OK; while (*string) { g_status.key_pressed = *string; rc = insert_overwrite( window ); ++string; } return( rc ); }