📄 ed.c
字号:
assert( pad < MAX_LINE_LENGTH );
/*
* if there any tabs in the next line, expand them because we
* probably have to redo them anyway.
*/
next_len = next_node->len;
tab_free = detab_a_line( next_node->line, &next_len );
assert( next_len >= 0 );
assert( next_len < MAX_LINE_LENGTH );
assert( len >= 0 );
assert( len < MAX_LINE_LENGTH );
/*
* check room to combine lines
*/
new_len = len + pad + next_len;
if (new_len >= g_display.line_length) {
/*
* cannot combine lines.
*/
error( WARNING, win->bottom_line, ed4 );
rc = ERROR;
} else {
if (mode.do_backups == TRUE) {
win->file_info->modified = TRUE;
rc = backup_file( win );
}
q = (text_ptr)(g_status.line_buff + len);
/*
* insert padding
*/
if (pad > 0) {
while (pad--)
*q++ = ' ';
}
_fmemcpy( q, tab_free, next_len );
g_status.line_buff_len = new_len;
entab_linebuff( );
if ((rc = un_copy_line( win->ll, win, FALSE )) == OK) {
if (next_node->next != NULL)
next_node->next->prev = win->ll;
win->ll->next = next_node->next;
win->ll->dirty = TRUE;
--win->file_info->length;
++win->rline;
adjust_windows_cursor( win, -1 );
restore_marked_block( win, -1 );
--win->rline;
wp = g_status.window_list;
while (wp != NULL) {
if (wp->file_info == win->file_info) {
/*
* make sure none of the window pointers point to the
* node we are about to delete.
*/
if (wp != win) {
if (wp->ll == next_node)
wp->ll = win->ll->next;
}
}
wp = wp->next;
}
/*
* now, it's safe to delete the next_node line as well as
* the next node.
*/
if (next_node->line != NULL)
my_free( next_node->line );
my_free( next_node );
show_size( win );
show_avail_mem( );
win->file_info->dirty = GLOBAL;
}
}
return( rc );
}
/*
* Name: word_delete
* Purpose: To delete from the cursor to the start of the next word.
* Date: September 1, 1991
* Passed: window: pointer to current window
* Notes: If the cursor is at the right of the line, then combine the
* current line with the next one, leaving the cursor where it
* is.
* If the cursor is on an alphanumeric character, then all
* subsequent alphanumeric characters are deleted.
* If the cursor is on a space, then all subsequent spaces
* are deleted.
* If the cursor is on a punctuation character, then all
* subsequent punctuation characters are deleted.
*/
int word_delete( WINDOW *window )
{
int len; /* length of current line */
int count; /* number of characters deleted from line */
register int start; /* column that next word starts in */
char *source; /* source for block move to delete word */
char *dest; /* destination for block move */
text_ptr p;
register WINDOW *win; /* put window pointer in a register */
int rc;
win = window;
if (win->rline > win->file_info->length || win->ll->len == EOF)
return( ERROR );
rc = OK;
copy_line( win->ll );
detab_linebuff( );
if (win->rcol >= (len = g_status.line_buff_len)) {
rc = join_line( win );
if (rc == OK) {
p = win->ll->line;
if (p != NULL) {
p += win->rcol;
if (win->rcol < win->ll->len) {
len = win->ll->len - win->rcol;
load_undo_buffer( win->file_info, p, len );
}
}
}
} else {
assert( len >= 0);
assert( len < MAX_LINE_LENGTH );
/*
* normal word delete
*
* find the start of the next word
*/
start = win->rcol;
if (isspace( g_status.line_buff[start] )) {
/*
* the cursor was on a space, so eat all consecutive spaces
* from the cursor onwards.
*/
while (start < len && isspace( g_status.line_buff[start] ))
++start;
} else {
/*
* eat all consecutive characters in the same class (spaces
* are considered to be in the same class as the cursor
* character)
*/
while (start < len && !isspace( g_status.line_buff[start] ))
++start;
while (start < len && isspace( g_status.line_buff[start] ))
++start;
}
/*
* move text to delete word
*/
count = start - win->rcol;
source = g_status.line_buff + start;
dest = g_status.line_buff + win->rcol;
assert( len - start >= 0 );
memmove( dest, source, len - start );
g_status.line_buff_len = len - count;
entab_linebuff( );
win->file_info->modified = TRUE;
win->file_info->dirty = GLOBAL;
win->ll->dirty = TRUE;
/*
* word_delete is also called by the word processing functions to get
* rid of spaces.
*/
if (g_status.command == WordDelete)
show_changed_line( win );
}
return( rc );
}
/*
* Name: dup_line
* Purpose: Duplicate current line
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: cursor stays on current line
*/
int dup_line( WINDOW *window )
{
register int len; /* length of current line */
text_ptr p;
register WINDOW *win; /* put window pointer in a register */
line_list_ptr next_node;
int rc;
win = window;
/*
* don't dup a NULL line
*/
if (win->rline > win->file_info->length || win->ll->len == EOF)
return( ERROR );
entab_linebuff( );
rc = un_copy_line( win->ll, win, TRUE );
len = win->ll->len;
assert( len >= 0);
assert( len < MAX_LINE_LENGTH );
p = NULL;
next_node = NULL;
if (rc == OK) {
p = (text_ptr)my_malloc( len, &rc );
next_node = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
}
if (rc == OK) {
win->file_info->modified = TRUE;
if (mode.do_backups == TRUE)
rc = backup_file( win );
++win->file_info->length;
if (len > 0)
_fmemcpy( p, win->ll->line, len );
next_node->line = p;
next_node->dirty = TRUE;
next_node->len = len;
if (win->ll->next != NULL)
win->ll->next->prev = next_node;
next_node->next = win->ll->next;
next_node->prev = win->ll;
win->ll->next = next_node;
adjust_windows_cursor( win, 1 );
/*
* if current line is the bottom line, we can't see the dup line because
* cursor doesn't move and dup line is added after current line.
*/
if (win->cline != win->bottom_line)
my_scroll_down( win );
win->file_info->dirty = NOT_LOCAL;
/*
* record that file has been modified
*/
restore_marked_block( win, 1 );
show_size( win );
show_avail_mem( );
} else {
/*
* cannot duplicate line
*/
if (p != NULL)
my_free( p );
if (next_node != NULL)
my_free( next_node );
error( WARNING, win->bottom_line, ed5 );
}
return( rc );
}
/*
* Name: back_space
* Purpose: To delete the character to the left of the cursor.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: If the cursor is at the left of the line, then combine the
* current line with the previous one.
* If in indent mode, and the cursor is on the first non-blank
* character of the line, then match the indentation of an
* earlier line.
*/
int back_space( WINDOW *window )
{
int rc; /* return code */
int len; /* length of the current line */
char *source; /* source of block move to delete character */
char *dest; /* destination of block move */
text_ptr p; /* previous line in file */
int plen; /* length of previous line */
int del_count; /* number of characters to delete */
int pos; /* the position of the first non-blank char */
register int rcol;
int ccol;
int old_bcol;
register WINDOW *win; /* put window pointer in a register */
WINDOW *wp;
line_list_ptr temp_ll;
win = window;
if (win->rline > win->file_info->length || win->ll->len == EOF)
return( ERROR );
rc = OK;
copy_line( win->ll );
detab_linebuff( );
len = g_status.line_buff_len;
rcol = win->rcol;
ccol = win->ccol;
old_bcol = win->bcol;
if (rcol == 0) {
if (win->rline > 1) {
/*
* combine this line with the previous, if any
*/
assert( win->ll->prev != NULL );
p = win->ll->prev->line;
plen = win->ll->prev->len;
if (len + 2 + plen >= g_display.line_length) {
/*
* cannot combine lines
*/
error( WARNING, win->bottom_line, ed4 );
return( ERROR );
}
win->file_info->modified = TRUE;
if ((rc = un_copy_line( win->ll, win, TRUE )) == OK) {
--win->rline;
win->ll = win->ll->prev;
win->bin_offset -= win->ll->len;
win->ll->dirty = TRUE;
copy_line( win->ll );
detab_linebuff( );
len = g_status.line_buff_len;
rcol = len;
p = win->ll->next->line;
plen = win->ll->next->len;
/*
* copy previous line into new previous line.
*/
assert( plen >= 0 );
assert( len >= 0 );
_fmemcpy( g_status.line_buff+len, p, plen );
g_status.line_buff_len = len + plen;
load_undo_buffer( win->file_info, p, plen );
if (p != NULL)
my_free( p );
temp_ll = win->ll->next;
if (temp_ll->prev != NULL)
temp_ll->prev->next = temp_ll->next;
temp_ll->next->prev = temp_ll->prev;
--win->file_info->length;
++win->rline;
restore_marked_block( win, -1 );
adjust_windows_cursor( win, -1 );
--win->rline;
wp = g_status.window_list;
while (wp != NULL) {
if (wp->file_info == win->file_info) {
if (wp != win) {
if (wp->ll == temp_ll)
wp->ll = win->ll->next;
}
}
wp = wp->next;
}
my_free( temp_ll );
if (win->cline > win->top_line + win->ruler)
--win->cline;
/*
* make sure cursor stays on the screen, at the end of the
* previous line
*/
ccol = rcol - win->bcol;
show_size( win );
show_avail_mem( );
check_virtual_col( win, rcol, ccol );
win->file_info->dirty = GLOBAL;
make_ruler( win );
show_ruler( win );
}
} else
return( ERROR );
} else {
/*
* normal delete
*
* find out how much to delete (depends on indent mode)
*/
del_count = 1; /* the default */
if (mode.indent) {
/*
* indent only happens if the cursor is on the first
* non-blank character of the line
*/
pos = first_non_blank( (text_ptr)g_status.line_buff, len );
if (pos == rcol ||
is_line_blank( (text_ptr)g_status.line_buff, len )) {
/*
* now work out how much to indent
*/
temp_ll = win->ll->prev;
for (; temp_ll != NULL; temp_ll=temp_ll->prev) {
p = temp_ll->line;
plen = first_non_blank( p, temp_ll->len );
if (plen < rcol && plen != temp_ll->len) {
/*
* found the line to match
*/
del_count = rcol - plen;
break;
}
}
}
}
/*
* move text to delete char(s), unless no chars actually there
*/
if (rcol - del_count < len) {
dest = g_status.line_buff + rcol - del_count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -