📄 ed.c
字号:
#include "tdestr.h" /* typedefs for global variables */
#include "define.h" /* editor function defs */
#include "tdefunc.h" /* prototypes for all functions in tde */
#include "global.h" /* global variables */
#include "prompts.h" /* prompt assignments */
#include "default.h" /* default function key assignments */
/*
* Name: insert_newline
* Purpose: insert a newline
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: There a several ways to insert a line into a file: 1) pressing
* a key, 2) word wrap, 3) any others?
* When doing word wrap or format paragraph, don't show any changes.
* Wait until the function finishes then show all changes at once.
*/
int insert_newline( WINDOW *window )
{
char *source; /* source for block move to make room for c */
char *dest; /* destination for block move */
int len; /* length of current line */
int split_len;
int add; /* characters to be added (usually 1 in insert mode) */
int rcol;
int rc;
long length;
int carriage_return;
int split_line;
int wordwrap;
int dirty;
int old_bcol;
register WINDOW *win; /* put window pointer in a register */
file_infos *file; /* pointer to file structure in current window */
line_list_ptr new_node;
text_ptr new_line; /* new line */
rc = OK;
win = window;
file = win->file_info;
length = file->length;
wordwrap = mode.word_wrap;
switch (g_status.command) {
case WordWrap :
carriage_return = TRUE;
split_line = FALSE;
break;
case AddLine :
split_line = carriage_return = FALSE;
break;
case SplitLine :
split_line = carriage_return = TRUE;
break;
case Rturn :
default :
/*
* if file is opened in BINARY mode, lets keep the user from
* unintentially inserting a line feed into the text.
*/
if (file->crlf == BINARY)
return( next_line( win ) );
show_ruler_char( win );
carriage_return = TRUE;
split_line = FALSE;
break;
}
/*
* make window temporarily invisible to the un_copy_line function
*/
new_node = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
new_line = NULL;
win->visible = FALSE;
old_bcol = win->bcol;
if (rc == OK) {
new_node->line = new_line;
new_node->len = 0;
new_node->dirty = FALSE;
if (win->ll->len != EOF) {
win->file_info->modified = TRUE;
if (mode.do_backups == TRUE)
rc = backup_file( win );
copy_line( win->ll );
detab_linebuff( );
len = g_status.line_buff_len;
split_len = 0;
if (win->rcol < len)
win->ll->dirty = TRUE;
source = g_status.line_buff + len;
if (carriage_return || split_line) {
if (win->rcol < len) {
source = g_status.line_buff + win->rcol;
split_len = len - win->rcol;
len = win->rcol;
}
}
g_status.line_buff_len = len;
entab_linebuff( );
if (un_copy_line( win->ll, win, TRUE ) == OK) {
assert( split_len >= 0 );
assert( split_len < MAX_LINE_LENGTH );
memmove( g_status.line_buff, source, split_len );
g_status.line_buff_len = len = split_len;
g_status.copied = TRUE;
entab_linebuff( );
} else
rc = ERROR;
} else {
g_status.line_buff_len = len = 0;
g_status.copied = TRUE;
}
if (rc == OK) {
new_node->line = new_line;
new_node->len = 0;
new_node->dirty = TRUE;
/*
* we are somewhere in the list and we need to insert the new node.
* if we are anywhere except the EOF node, insert the new node
* after the current node. if the current node is the EOF node,
* insert the new node before the EOF node. this keeps the
* EOF node at the end of the list.
*/
if (win->ll->next != NULL) {
win->ll->next->prev = new_node;
new_node->next = win->ll->next;
win->ll->next = new_node;
new_node->prev = win->ll;
} else {
new_node->next = win->ll;
if (win->ll->prev != NULL)
win->ll->prev->next = new_node;
new_node->prev = win->ll->prev;
win->ll->prev = new_node;
if (new_node->prev == NULL)
win->file_info->line_list = new_node;
win->ll = new_node;
}
++file->length;
detab_linebuff( );
entab_linebuff( );
rc = un_copy_line( new_node, win, FALSE );
adjust_windows_cursor( win, 1 );
file->dirty = NOT_LOCAL;
if (length == 0l || wordwrap || win->cline == win->bottom_line)
file->dirty = GLOBAL;
else if (!split_line)
update_line( win );
/*
* If the cursor is to move down to the next line, then update
* the line and column appropriately.
*/
if (rc == OK && (carriage_return || split_line)) {
dirty = file->dirty;
if (win->cline < win->bottom_line)
win->cline++;
win->rline++;
if (win->ll->next != NULL) {
win->bin_offset += win->ll->len;
win->ll = win->ll->next;
}
rcol = win->rcol;
old_bcol = win->bcol;
if (win->ll->next != NULL) {
if (mode.indent || wordwrap) {
/*
* autoindentation is required. Match the indentation of
* the first line above that is not blank.
*/
add = find_left_margin( wordwrap == FIXED_WRAP ?
win->ll : win->ll->prev, wordwrap );
assert( add >= 0 );
assert( add < MAX_LINE_LENGTH );
copy_line( win->ll );
detab_linebuff( );
len = g_status.line_buff_len;
source = g_status.line_buff;
if (len + add > MAX_LINE_LENGTH)
add = MAX_LINE_LENGTH - len;
dest = source + add;
assert( len >= 0);
assert( len < MAX_LINE_LENGTH );
memmove( dest, source, len );
/*
* now put in the autoindent characters
*/
assert( add >= 0 );
assert( add < MAX_LINE_LENGTH );
memset( source, ' ', add );
win->rcol = add;
g_status.line_buff_len += add;
entab_linebuff( );
rc = un_copy_line( win->ll, win, TRUE );
} else
win->rcol = 0;
}
if (rc == OK && split_line) {
win->rline--;
win->ll = win->ll->prev;
if (win->cline > win->top_line + window->ruler)
win->cline--;
win->rcol = rcol;
}
check_virtual_col( win, win->rcol, win->ccol );
if (dirty == GLOBAL || file->dirty == LOCAL || wordwrap)
file->dirty = GLOBAL;
else
file->dirty = dirty;
}
} else {
if (new_node != NULL)
my_free( new_node );
}
} else {
if (new_node != NULL)
my_free( new_node );
error( WARNING, window->bottom_line, main4 );
}
/*
* record that file has been modified
*/
win->visible = TRUE;
if (rc == OK) {
if (file->dirty != GLOBAL)
my_scroll_down( win );
restore_marked_block( win, 1 );
show_size( win );
show_avail_mem( );
if (old_bcol != win->bcol) {
make_ruler( win );
show_ruler( win );
}
}
return( rc );
}
/*
* Name: insert_overwrite
* Purpose: To make the necessary changes after the user has typed a normal
* printable character
* Date: June 5, 1991
* Passed: window: pointer to current window
*/
int insert_overwrite( WINDOW *window )
{
char *source; /* source for block move to make room for c */
char *dest; /* destination for block move */
int len; /* length of current line */
int pad; /* padding to add if cursor beyond end of line */
int add; /* characters to be added (usually 1 in insert mode) */
register int rcol;
register WINDOW *win; /* put window pointer in a register */
int rc;
win = window;
if (win->ll->len == EOF || g_status.key_pressed >= 256)
rc = OK;
else {
rcol = win->rcol;
/*
* first check we have room - the editor can not
* cope with lines wider than g_display.line_length
*/
if (rcol >= g_display.line_length) {
/*
* cannot insert more characters
*/
error( WARNING, win->bottom_line, ed2 );
rc = ERROR;
} else {
copy_line( win->ll );
detab_linebuff( );
/*
* work out how many characters need to be inserted
*/
len = g_status.line_buff_len;
pad = rcol > len ? rcol - len : 0;
if (mode.insert || rcol >= len)
/*
* inserted characters, or overwritten characters at the end of
* the line, are inserted.
*/
add = 1;
else
/*
* and no extra space is required to overwrite existing characters
*/
add = 0;
/*
* check that current line would not get too long.
*/
if (len + pad + add >= g_display.line_length) {
/*
* no more room to add
*/
error( WARNING, win->bottom_line, ed3 );
rc = ERROR;
} else {
/*
* make room for whatever needs to be inserted
*/
if (pad > 0 || add > 0) {
source = g_status.line_buff + rcol - pad;
dest = source + pad + add;
assert( len + pad - rcol >= 0 );
assert( len + pad - rcol < MAX_LINE_LENGTH );
memmove( dest, source, len + pad - rcol );
/*
* put in the required padding
*/
assert( pad >= 0 );
assert( pad < MAX_LINE_LENGTH );
memset( source, ' ', pad );
}
g_status.line_buff[rcol] = (char)g_status.key_pressed;
g_status.line_buff_len += pad + add;
entab_linebuff( );
/*
* always increment the real column (rcol) then adjust the
* logical and base column as needed. show the changed line
* in all but the LOCAL window. In the LOCAL window, there are
* two cases: 1) update the line, or 2) redraw the window if
* cursor goes too far right.
*/
win->file_info->dirty = NOT_LOCAL;
win->ll->dirty = TRUE;
show_changed_line( win );
if (win->ccol < win->end_col) {
show_curl_line( win );
show_ruler_char( win );
win->ccol++;
} else {
win->bcol++;
win->file_info->dirty = LOCAL;
make_ruler( win );
show_ruler( win );
}
rcol++;
}
/*
* record that file has been modified and adjust cursors,
* file start and end pointers as needed.
*/
check_virtual_col( win, rcol, win->ccol );
win->file_info->modified = TRUE;
if (mode.word_wrap) {
add = mode.right_justify;
mode.right_justify = FALSE;
g_status.command = FormatText;
word_wrap( win );
mode.right_justify = add;
}
rc = OK;
}
}
return( rc );
}
/*
* Name: join_line
* Purpose: To join current line and line below at cursor
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: trunc the line. then, join with line below, if it exists.
*/
int join_line( WINDOW *window )
{
int len; /* length of current line */
int new_len; /* length of the joined lines */
int next_len; /* length of the line below current line */
text_ptr q; /* next line in file */
text_ptr tab_free; /* next line in file -- with the tabs removed */
int pad; /* padding spaces required */
register WINDOW *win; /* put window pointer in a register */
WINDOW *wp;
line_list_ptr next_node;
int rc;
win = window;
if (win->ll->len == EOF || win->ll->next->len == EOF)
return( ERROR );
rc = OK;
assert( win->ll->next != NULL );
next_node = win->ll->next;
load_undo_buffer( win->file_info, win->ll->line, win->ll->len );
copy_line( win->ll );
detab_linebuff( );
/*
* if cursor is in line before eol, reset len to rcol
*/
if (win->rcol < (len = g_status.line_buff_len))
len = win->rcol;
/*
* calculate needed padding
*/
pad = win->rcol > len ? win->rcol - len : 0;
assert( pad >= 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -