home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
editors
/
tde150.arj
/
UTILS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-01
|
67KB
|
2,252 lines
/******************* start of original comments ********************/
/*
* Written by Douglas Thomson (1989/1990)
*
* This source code is released into the public domain.
*/
/*
* Name: dte - Doug's Text Editor program - miscellaneous utilities
* Purpose: This file contains miscellaneous functions that were required
* in more than one of the other files, or were thought to be
* likely to be used elsewhere in the future.
* File: utils.c
* Author: Douglas Thomson
* System: this file is intended to be system-independent
* Date: October 1, 1989
*/
/********************* end of original comments ********************/
/*
* The utility routines have been EXTENSIVELY rewritten. Update screens as
* needed. Most times, only one line has changed. Just show changed line
* in all windows if it is on screen.
*
* Support routines for text lines longer than screen width have been added.
* Currently support lines as long as 255 bytes. If longer lines are needed,
* the assembly routines need to be modified since they use bytes (a byte
* goes from 255 to 0, unsigned).
*
* New editor name: tde, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, 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
*
* This modification of Douglas Thomson's code is released into the
* public domain, Frank Davis. You may distribute it freely.
*/
#include "tdestr.h"
#include "common.h"
#include "define.h"
#include "tdefunc.h"
#ifdef __TURBOC__
#include <dir.h> /* for making temporary file names etc */
#endif
#if defined( __MSC__ )
#include <dos.h>
#include <io.h>
#endif
/*
* Name: myisalnum
* Purpose: To determine whether or not a character is part of a "word",
* which in languages like Pascal means a letter, digit or
* underscore.
* Date: October 1, 1989
* Passed: c: the character to be tested
* Returns: TRUE if c is an alphanumeric or '_' character, FALSE otherwise
*/
int myisalnum( int c )
{
return( isalnum( c ) || (c == '_') );
}
/*
* Name: check_virtual_col
* Purpose: ensure integrity of rcol, ccol, and bcol
* Date: June 5, 1991
* Passed: window: 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.
*/
void copy_line( text_ptr text_line, int line )
{
char *d; /* destination of copy */
text_ptr s; /* source of copy */
register int len;
if (g_status.copied == FALSE) {
g_status.copied = TRUE;
/*
* copy the cursor line to the line buffer
*/
d = g_status.line_buff;
g_status.buff_line = text_line;
s = cpf( text_line );
len = linelen( s );
if (s[len] == '\n')
++len;
if (len >= g_display.line_length) {
len = g_display.line_length;
error( WARNING, line, "line buffer overflow - rest of line ignored" );
}
_fmemcpy( d, s, len );
d[len] = CONTROL_Z;
}
}
/*
* Name: un_copy_line
* Purpose: To copy the cursor line, if necessary, from the current line
* buffer, shifting the main text to make the right amount of
* room.
* Date: June 5, 1991
* Passed: test_line: pointer to location in file to copy line buffer
* window: pointer to current window info
* del_trailing: delete the trailing blanks at eol? TRUE or FALSE
* Notes: For some functions, trailing spaces should not be removed when
* returning the line buffer to the main text. The JoinLine function
* is a good example. We need to leave trailing space so when we
* join lines - the current line will extend at least up to
* the column of the cursor. We 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) {
rc = save_backup( window );
if (rc == ERROR)
error( WARNING, window->bottom_line,
"Error writing file or disk full" );
else
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 )) {
error( WARNING, prompt_line, "buffer full, part line truncated" );
len = curs_len + (int) (ptoul( g_status.max_mem ) -
ptoul( g_status.end_mem ));
}
/*
* move text to either make room for the extra characters in the new
* line, or else close up the gap.
*/
p = text_line + curs_len;
dest = addltop( (long)space, p );
number = ptoul( g_status.end_mem ) - ptoul( p );
hw_move( dest, p, number );
g_status.end_mem = addltop( (long)space, g_status.end_mem );
/*
* now copy the line buffer into the space just created
*/
_fmemcpy( text_line, g_status.line_buff, len );
g_status.copied = FALSE;
file->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 UNDO_MAX changed lines in a stack. when we
* overflow the stack, dump the oldest line. don't worry
* about which file the line comes from - just load the stack.
*/
void load_undo_buffer( text_ptr line_to_undo )
{
register char *s; /* char pointer to stack */
char *d;
int top; /* top of stack */
register int len;
/*
* if the stack is empty, g_status.undo_head will be -1. set it to
* 0, the first buffer in the stack.
*/
if (g_status.undo_head < 0)
g_status.undo_head = 0;
/*
* if the stack overflows, dump the oldest line.
*/
else if (g_status.undo_head == UNDO_MAX) {
d = (char *)g_status.undo_buffer;
s = d + BUFF_SIZE;
memmove( d, s, (UNDO_MAX * BUFF_SIZE) - BUFF_SIZE );
}
len = linelen( line_to_undo );
if (line_to_undo[len] == '\n')
++len;
top = g_status.undo_head;
if (top == UNDO_MAX)
--top;
s = &g_status.undo_buffer[top][0];
hw_move( s, line_to_undo, len );
if (s[len-1] != '\n')
s[len++] = '\n';
s[len] = CONTROL_Z;
if (g_status.undo_head < UNDO_MAX)
++g_status.undo_head;
}
/*
* Name: load_file
* Purpose: To read in a given file 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: October 1, 1989
* 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: Editing of the line is supported.
*/
int get_name( char *prompt, int line, char *name, int color )
{
int col; /* cursor column for answer */
int c; /* character user just typed */
char *cp; /* cursor position in answer */
char *answer; /* user's answer */
int first = TRUE; /* first character typed */
register int len; /* length of answer */
int plen; /* length of prompt */
int func; /* function of key pressed */
int stop; /* flag to stop getting characters */
char *p; /* for copying text in answer */
char buffer[MAX_COLS+2];/* line on which name is being entered */
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
int normal;
/*
* set up prompt and default
*/
strcpy( buffer, prompt );
plen = strlen( prompt );
answer = buffer + plen;
strcpy( answer, name );
/*
* let user edit default string
*/
len = strlen( answer );
col = strlen( buffer );
g_status.prompt_line = line;
g_status.prompt_col = col;
cp = answer + len;
normal = g_display.text_color;
save_screen_line( 0, line, line_buff );
s_output( buffer, line, 0, color );
eol_clear( col, line, normal );
for (stop = FALSE; stop == FALSE;) {
xygoto( col, line );
c = getkey( );
func = getfunc( c );
/*
* User may have redefined the Enter and ESC keys. Make the Enter key
* perform a Rturn in this function. Make the ESC key do an AbortCommand.
*/
if (c == RTURN)
func = Rturn;
else if (c == ESC)
func = AbortCommand;
switch (func) {
case ToggleSearchCase :
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_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: October 1, 1989
* Returns: the user's answer. A_??? - see tdestr.h
*/
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
* Passed: line: line to 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: 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: current window
*/
void 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( );
}
/*
* Name: redraw_current_window
* Purpose: redraw all info in window
* Date: July 13, 1991
* Passed: window: 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: 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: 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: 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: current window
* line_change: number of lines added or subtracted from a file
* Notes: If a file has been changed, all of the memory pointers greater
* than window->cursor must be adjusted by the number of characters
* added or subtracted from the file pointed to by window.
* If a file has been truncated in one window and there is another
* window open to the same file and its current line is near the
* end, the current line is reset to the last line of the file.
*/
void adjust_windows_cursor( WINDOW *window, int line_change )
{
register WINDOW *next;
register int reset;
text_ptr p;
int i;
file_infos *file;
file_infos *next_file;
file = window->file_info;
next = g_status.window_list;
while (next != NULL) {
if (next != window) {
next_file = next->file_info;
if (next_file == file) {
reset = FALSE;
if (ptoul( next->cursor ) > ptoul( file->end_text ))
reset = END;
else if (ptoul( next->cursor ) < ptoul( file->start_text ))
reset = BEGIN;
else if (next->rline > window->rline) {
if (line_change) {
p = next->cursor;
if (line_change < 0) {
p = cpf( p );
for (i=line_change; i < 0 && p != NULL; i++)
p = find_next( p );
if (p != NULL)
next->cursor = p;
else
reset = END;
} else if (line_change > 0) {
p = cpb( p );
for (i=line_change; i > 0 && p != NULL; i--)
p = find_prev( p );
if (p != NULL)
next->cursor = p;
else
reset = BEGIN;
}
}
}
if (reset) {
if (reset == BEGIN) {
next->cursor = next_file->start_text;
next->rline = 1;
next->cline = next->top_line + 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;
}
}
/*
* 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: information allowing access to the current window
* Notes: The cursor line is moved back the required number of lines
* towards the start of the file.
* If the start of the file is reached, then movement stops.
*/
void page_up( WINDOW *window )
{
int i; /* count of lines scanned */
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;
}
sync( win );
}
/*
* Name: page_down
* Purpose: To move the cursor one page down the window
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: The cursor line is moved forwards the required number of lines
* towards the end of the file.
* If the end of the file is reached, then movement stops.
*/
void page_down( WINDOW *window )
{
int i, k; /* count of lines scanned so far */
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;
}
sync( win );
}
/*
* Name: scroll_down
* Purpose: scroll window down one line
* Date: June 5, 1991
* Passed: window: information allowing access to the 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.
*/
void scroll_down( WINDOW *window )
{
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 {
--win->cline;
win->file_info->dirty = LOCAL;
}
sync( win );
}
/*
* Name: scroll_up
* Purpose: To scroll the window up one line
* Date: June 5, 1991
* Passed: window: information allowing access to the 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.
*/
void scroll_up( WINDOW *window )
{
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;
}
}
}
sync( win );
}
/*
* Name: fixed_scroll_up
* Purpose: To leave cursor on same logical line and scroll text up
* Date: September 1, 1991
* Passed: window: information allowing access to the current window
* Notes: If cursor is on first page then do not scroll.
*/
void fixed_scroll_up( WINDOW *window )
{
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;
}
}
sync( win );
}
/*
* Name: fixed_scroll_down
* Purpose: To leave cursor on same logical line and scroll text down
* Date: September 1, 1991
* Passed: window: information allowing access to the current window
* Notes: If cursor is on last line in file then do not scroll.
*/
void fixed_scroll_down( WINDOW *window )
{
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;
}
sync( win );
}
/*
* Name: file_file
* Purpose: To file the current file to disk.
* Date: September 17, 1991
* Passed: window: information allowing access to the current window
*/
void file_file( WINDOW *window )
{
if (save_file( window ) == OK)
finish( window );
}
/*
* Name: save_file
* Purpose: To save the current file to disk.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If anything goes wrong, then the modified flag is set.
* If the file is saved successfully, then modified flag is
* cleared.
*/
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;
} else
error( WARNING, window->bottom_line,
"Error writing file or disk full" );
}
return( rc );
}
/*
* Name: save_backup
* Purpose: To save a backup copy of the current file to disk.
* Date: June 5, 1991
* Passed: window: information allowing access to the 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: information allowing access to the current window
*/
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 );
combine_strings( status_line, "Saving '", name, "'" );
s_output( status_line, prompt_line, 0, g_display.message_color );
eol_clear( strlen( status_line ), prompt_line, g_display.message_color );
file->end_text = cpb( file->end_text );
if ((rc = hw_save( name, file->start_text, file->end_text - mode.control_z,
NOTMARKED )) == ERROR) {
if (ceh.flag != ERROR) {
if (get_fattr( name, &fattr ) == OK && fattr & READ_ONLY)
combine_strings( status_line, "file '", name, "' is Read Only" );
else
combine_strings( status_line, "cannot write to '", 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: information allowing access to the 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';
if ((rc = get_name( "New file name: ", 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 */
set_prompt( "Overwrite existing file? (y/n): ", prompt_line );
if (get_yn( ) != A_YES || change_mode( name, prompt_line ) == ERROR)
rc = ERROR;
}
if (rc != ERROR)
rc = write_to_disk( win, name );
if (rc == ERROR)
error( WARNING, prompt_line, "Error writing file or disk full" );
}
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: information allowing access to the 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: information allowing access to the 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: information allowing access to the 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: information allowing access to the 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: information allowing access to the 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: information allowing access to the current window
* Notes: If the file has been modified but not saved, then the user is
* given a second chance before the changes are discarded.
* Note that this is only necessary if this is the last window
* that refers to the file. If another window still refers to
* the file, then the check can be left until later.
*/
void quit( 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 );
set_prompt( "Abandon changes? (y/n): ", prompt_line );
if (get_yn( ) == A_NO)
rc = ERROR;
restore_screen_line( 0, prompt_line, line_buff );
}
/*
* remove window, allocate screen lines to other windows etc
*/
if (rc == OK)
finish( window );
}
/*
* Name: move_up
* Purpose: To move the cursor up one line
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is at the top of the window, then the file must
* be scrolled down.
*/
void move_up( WINDOW *window )
{
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 );
}
}
sync( win );
}
/*
* Name: move_down
* Purpose: To move the cursor down one line
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is at the bottom of the window, then the file must
* be scrolled up. If the cursor is at the bottom of the file,
* then scroll line up until it is at top of screen.
*/
void move_down( WINDOW *window )
{
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;
}
sync( win );
}
/*
* Name: move_left
* Purpose: To move the cursor left one character
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is already at the left of the screen, then
* scroll horizontally if we're not at beginning of line.
*/
void move_left( 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 );
}
}
/*
* Name: move_right
* Purpose: To move the cursor right one character
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: If the cursor is already at the right of the screen (logical
* column 80) then scroll horizontally right.
*/
void move_right( 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 );
}
}
/*
* Name: scroll_left
* Purpose: To scroll the screen left one character
* Date: January 5, 1992
* Passed: window: information allowing access to the current window
*/
void 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 );
}
/*
* Name: scroll_right
* Purpose: To scroll the screen right one character
* Date: January 5, 1992
* Passed: window: information allowing access to the current window
*/
void 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 );
}
/*
* Name: word_left
* Purpose: To move the cursor left one word
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Words are considered strings of letters, numbers and underscores,
* which must be separated by other characters. After every 8000
* characters, check the pointer.
*/
void word_left( WINDOW *window )
{
text_ptr p; /* text pointer */
int len; /* length of current line */
register int c; /* character at pointer */
register int check = 0;
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 );
}
}
sync( window );
}
/*
* Name: word_right
* Purpose: To move the cursor right one word
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Words are considered strings of letters, numbers and underscores,
* which must be separated by other characters. After every 8000
* characters, check the pointer.
*/
void word_right( WINDOW *window )
{
int len; /* length of current line */
text_ptr p; /* text pointer */
register int c; /* character at pointer */
register int check = 0;
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 );
}
if (w.rline != window->rline && !window->file_info->dirty) {
update_line( &w );
show_curl_line( window );
}
sync( window );
}
/*
* Name: center_window
* Purpose: To place the current line or cursor in the center of a window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
*/
void 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; i<diff; i++)
win->cursor = 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 );
}
/*
* Name: horizontal_screen_right
* Purpose: To move the cursor one screen to the right
* Date: September 13, 1991
* Passed: window: information allowing access to the current window
* Notes: Add 80 columns to the real cursor. If the cursor is past the
* maximum line length then move it back.
*/
void horizontal_screen_right( WINDOW *window )
{
window->rcol += (window->end_col + 1 - window->start_col);
if (window->rcol >= MAX_LINE_LENGTH)
window->rcol = MAX_LINE_LENGTH - 1;
else {
window->bcol += (window->end_col + 1 - window->start_col);
window->file_info->dirty = LOCAL;
}
check_virtual_col( window, window->rcol, window->ccol );
sync( window );
make_ruler( window );
show_ruler( window );
}
/*
* Name: horizontal_screen_left
* Purpose: To move the cursor one screen to the left
* Date: September 13, 1991
* Passed: window: information allowing access to the current window
* Notes: Subtract 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.
*/
void 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 );
}
/*
* Name: set_marker
* Purpose: To set file marker
* Date: December 28, 1991
* Passed: window: information allowing access to the current window
*/
void 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;
}
/*
* Name: goto_marker
* Purpose: To goto a file marker
* Date: December 28, 1991
* Passed: window: information allowing access to the current window
*/
void goto_marker( WINDOW *window )
{
int m;
file_infos *file;
char *q = "Marker not set in this file";
text_ptr p;
long i;
long number;
MARKER *marker;
register WINDOW *win; /* put window pointer in a register */
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 (; i<number; i++)
p = find_next( p );
}
win->cursor = 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 );
} else {
if (m == 9)
m = -1;
*(q + 7) = (char)('0' + m + 1);
error( WARNING, win->bottom_line, q );
}
}
/*
* Name: change_fattr
* Purpose: To change the file attributes
* Date: December 31, 1991
* Passed: window: information allowing access to the current window
*/
void 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;
prompt_line = window->bottom_line;
save_screen_line( 0, prompt_line, line_buff );
name[0] = '\0';
if ((ok = get_name( "Enter new file attributes, \"AaSsHhRr\" : ",
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 ))
error( WARNING, prompt_line, "New file attributes not set" );
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 );
}
}
}
}
restore_screen_line( 0, prompt_line, line_buff );
}