📄 utils.c
字号:
/******************* 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.
*
* In DTE, Doug chose to test whether characters are part of a word. In TDE,
* we will test whether characters are not part of a word. The character
* set not part of a word will not change as much as the characters that
* are part of a word. In most languages, human and computer, the delimiters
* are much more common across languages than the tokens that make up a word.
* Thanks to Pierre Jelenc, pcj1@columbia.edu, for recommending looking for
* delimiters.
*
* New editor name: TDE, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, version 1.0
* Date: July 29, 1991, version 1.1
* Date: October 5, 1991, version 1.2
* Date: January 20, 1992, version 1.3
* Date: February 17, 1992, version 1.4
* Date: April 1, 1992, version 1.5
* Date: June 5, 1992, version 2.0
* Date: October 31, 1992, version 2.1
* Date: April 1, 1993, version 2.2
* Date: June 5, 1993, version 3.0
*
* 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"
/*
* Name: myiswhitespc
* Purpose: To determine whether or not a character is *NOT* part of a "word".
* Date: July 4, 1992
* Passed: c: the character to be tested
* Returns: TRUE if c is in the character set *NOT* part of a word
* Notes: The characters in the set not part of a word will not change as
* as much as the characters that are part of a word. In most
* languages, human and computer, the delimiters are much more
* common than the tokens that make up a word. For example,
* the set of punction characters don't change as much across
* languages, human and computer, as the characters that make
* up the alphabet, usually. In other words, the delimiters
* are fairly constant across languages.
*/
int myiswhitespc( int c )
{
return( c == ' ' || (ispunct( c ) && c != '_') || iscntrl( 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);
}
assert( rcol >= 0 );
assert( rcol < MAX_LINE_LENGTH );
assert( bcol >= 0 );
assert( bcol < MAX_LINE_LENGTH );
assert( ccol >= start_col );
assert( ccol <= end_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.
* 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( line_list_ptr ll )
{
register unsigned int len;
text_ptr text_line;
if (g_status.copied == FALSE && ll->len != EOF) {
assert( ll != NULL );
len = ll->len;
text_line = ll->line;
g_status.buff_node = ll;
assert( len < MAX_LINE_LENGTH );
if (text_line != NULL)
_fmemcpy( g_status.line_buff, text_line, len );
g_status.line_buff_len = len;
g_status.copied = TRUE;
}
}
/*
* 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: 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.
*/
int un_copy_line( line_list_ptr ll, WINDOW *window, int del_trailing )
{
text_ptr p;
size_t len; /* length of line buffer text */
size_t ll_len; /* length of ll->line */
int net_change;
int rc;
char c;
file_infos *file;
WINDOW *wp;
rc = OK;
if (mode.do_backups == TRUE)
rc = backup_file( window );
if (g_status.copied == TRUE && ll->len != EOF) {
file = window->file_info;
/*
* 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;
if (del_trailing && mode.trailing && file->crlf != BINARY) {
len = g_status.line_buff_len;
for (p=(text_ptr)(g_status.line_buff+len); len > 0; len--, p--) {
c = *(p - 1);
if (c != ' ' && c != '\t')
break;
if (!mode.inflate_tabs && c == '\t')
break;
}
g_status.line_buff_len = len;
file->dirty = GLOBAL;
if (window->visible == TRUE)
show_changed_line( window );
}
len = g_status.line_buff_len;
ll_len = (ll->line == NULL) ? 0 : ll->len;
assert( len < MAX_LINE_LENGTH );
assert( ll_len < MAX_LINE_LENGTH );
net_change = len - ll_len;
if (ll_len != len || ll->line == NULL) {
/*
* let malloc space for the new line before we free the old line.
*/
p = my_malloc( len, &rc );
if (rc == ERROR)
error( WARNING, window->bottom_line, main4 );
/*
* free the space taken up by current line in far heap.
*/
if (rc != ERROR && ll->line != NULL)
my_free( ll->line );
} else
p = ll->line;
if (rc != ERROR) {
if (len > 0)
_fmemcpy( p, g_status.line_buff, len );
ll->line = p;
ll->len = len;
if (net_change != 0) {
for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
if (wp->file_info == file && wp != window)
if (wp->rline > window->rline)
wp->bin_offset += net_change;
}
}
file->modified = TRUE;
show_avail_mem( );
}
}
g_status.copied = FALSE;
return( rc );
}
/*
* Name: un_copy_tab_buffer
* Purpose: To copy the tab buffer line the main text buffer
* Date: October 31, 1992
* Passed: line_number: line number to copy line tab out buffer
* window: pointer to current window
*/
int un_copy_tab_buffer( line_list_ptr ll, WINDOW *window )
{
text_ptr p;
int len; /* length of current line buffer text */
int net_change;
int rc;
file_infos *file;
WINDOW *wp;
rc = OK;
file = window->file_info;
/*
* file has changed. lets create the back_up if needed
*/
if (mode.do_backups == TRUE) {
window->file_info->modified = TRUE;
rc = backup_file( window );
}
len = g_status.tabout_buff_len;
assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );
assert( ll->len >= 0 );
assert( ll->len < MAX_LINE_LENGTH );
/*
* if the far heap has run out of space, then only part of the
* current line can be moved back into the far heap. Warn the user
* that some of the current line has been lost.
*/
p = my_malloc( len, &rc );
if (rc == ERROR)
error( WARNING, window->bottom_line, main4 );
if (rc == OK) {
net_change = len - ll->len;
if (ll->line != NULL)
my_free( ll->line );
if (len > 0)
_fmemcpy( p, g_status.line_buff, len );
ll->line = p;
ll->len = len;
if (net_change != 0) {
for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
if (wp->file_info == file && wp != window)
if (wp->rline > window->rline)
wp->bin_offset += net_change;
}
}
file->modified = TRUE;
}
return( rc );
}
/*
* Name: load_undo_buffer
* Purpose: To copy the cursor line to the undo buffer.
* Date: September 26, 1991
* Passed: file: pointer to file
* line_to_undo: pointer to line in file to save
* Notes: save the last mode.undo_max lines in a stack. when we overflow
* the stack, dump the oldest line.
*/
void load_undo_buffer( file_infos *file, text_ptr line_to_undo, int len )
{
int rc;
text_ptr l;
line_list_ptr temp_ll;
rc = OK;
if (file->undo_count >= mode.undo_max) {
--file->undo_count;
temp_ll = file->undo_bot->prev;
temp_ll->prev->next = file->undo_bot;
file->undo_bot->prev = temp_ll->prev;
if (temp_ll->line != NULL)
my_free( temp_ll->line );
} else
temp_ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );
l = my_malloc( len, &rc );
if (rc == ERROR) {
if (l != NULL)
my_free( l );
if (temp_ll != NULL)
my_free( temp_ll );
} else {
if (len > 0)
_fmemcpy( l, line_to_undo, len );
temp_ll->line = l;
temp_ll->len = len;
temp_ll->dirty = TRUE;
temp_ll->prev = NULL;
temp_ll->next = file->undo_top;
file->undo_top->prev = temp_ll;
file->undo_top = temp_ll;
++file->undo_count;
}
}
/*
* 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 );
assert( prompt_col <= MAX_COLS );
/*
* output the prompt
*/
s_output( prompt, line, 0, g_display.message_color );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -