📄 ed.c
字号:
/* * check that current line would not get too long. */ if (len + pad + add >= MAX_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) { shift_tabbed_block( win->file_info ); 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 + add ); shift_block( win->file_info, win->rline, rcol, add ); } if (dir == CUR_LEFT && rcol == 0) { *g_status.line_buff = ' '; ++rcol; } g_status.line_buff[rcol] = (char)g_status.key_pressed; g_status.line_buff_len += pad + add; entab_linebuff( win->file_info->inflate_tabs, win->file_info->ptab_size ); /* * 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. * * jmh 981129: update cursor according to direction. */ win->file_info->modified = TRUE; win->file_info->dirty = NOT_LOCAL; win->ll->type |= DIRTY; show_changed_line( win ); switch (dir) { case CUR_RIGHT: if (win->ccol < win->end_col) { show_curl_line( win ); show_ruler_char( win ); win->ccol++; } else { win->bcol++; win->file_info->dirty = LOCAL; show_ruler( win ); } rcol = win->rcol + 1; /* real tabs may make rcol wrong */ check_virtual_col( win, rcol, win->ccol ); if (mode.word_wrap) { add = mode.right_justify; mode.right_justify = FALSE; g_status.command = FormatText; word_wrap( win ); mode.right_justify = add; } break; case CUR_LEFT : --rcol; --win->ccol; check_virtual_col( win, rcol, win->ccol ); if (win->file_info->dirty == FALSE) show_curl_line( win ); break; case CUR_DOWN : if (win->ll->next->len == EOF) { g_status.command = AddLine; rc = insert_newline( win ); } if (rc == OK) prepare_move_down( win ); break; case CUR_UP : prepare_move_up( win ); if (win->rline == 0) { g_status.command = AddLine; rc = insert_newline( win ); prepare_move_down( win ); } break; } } } } 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. * * jmh 991113: if this is called from WordDelete, remove leading space. * jmh 000604: corrected bug when WordDelete joined with a blank line. */int join_line( TDE_WIN *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 TDE_WIN *win; /* put window pointer in a register */TDE_WIN *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, win, TRUE ); /* * 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 ); assert( pad < MAX_LINE_LENGTH ); /* * if there any tabs in the next line, expand them because we * probably have to redo them anyway. * jmh 991113: keep the tabs in real tab mode. */ next_len = next_node->len; if (win->file_info->inflate_tabs == 1) tab_free = detab_a_line( next_node->line, &next_len, win->file_info->inflate_tabs, win->file_info->ptab_size ); else tab_free = next_node->line; if (g_status.command == WordDelete) { while (next_len > 0 && bj_isspace( *tab_free )) { ++tab_free; --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 >= MAX_LINE_LENGTH) { /* * cannot combine lines. */ error( WARNING, win->bottom_line, ed4 ); rc = ERROR; } else { win->file_info->modified = TRUE; if (mode.do_backups == TRUE) rc = backup_file( win ); q = g_status.line_buff + len; /* * insert padding */ if (pad > 0) { while (pad--) *q++ = ' '; } my_memcpy( q, tab_free, next_len ); g_status.line_buff_len = new_len; if ((rc = un_copy_line( win->ll, win, FALSE, TRUE )) == OK) { if (next_node->next != NULL) next_node->next->prev = win->ll; win->ll->next = next_node->next; win->ll->type |= DIRTY; --win->file_info->length; ++win->rline; adjust_windows_cursor( win, -1 ); restore_marked_block( win, -1 ); --win->rline; syntax_check_lines( win->ll, win->file_info->syntax ); 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. */ 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 * Modified: 27 November, 1996, Jason Hood - treat words similar to word_right * 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( TDE_WIN *window ){int len; /* length of current line */int count; /* number of characters deleted from line */register int start; /* column that next word starts in */text_ptr source; /* source for block move to delete word */text_ptr dest; /* destination for block move */text_ptr p;register TDE_WIN *win; /* put window pointer in a register */int rcol;int rc; win = window; if (win->ll->len == EOF) return( ERROR ); rc = OK; rcol = win->rcol; copy_line( win->ll, win, FALSE ); adjust_for_tabs( &rcol, win->file_info->inflate_tabs, win->file_info->ptab_size ); if (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 = rcol; if (bj_isspace( g_status.line_buff[start] )) { /* * the cursor was on a space, so eat all consecutive spaces * from the cursor onwards. */ while (start < len && bj_isspace( g_status.line_buff[start] )) ++start; } else if (myiswhitespc( g_status.line_buff[start] )) { /* * the cursor was on a white space, so eat all consecutive * white space from the cursor onwards (jmh) */ while (start < len && myiswhitespc( 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 && !myiswhitespc( g_status.line_buff[start] )) ++start; while (start < len && bj_isspace( g_status.line_buff[start] )) ++start; } /* * move text to delete word */ count = start - rcol; source = g_status.line_buff + start; dest = g_status.line_buff + rcol; shift_tabbed_block( win->file_info ); assert( len - start >= 0 ); memmove( dest, source, len - start ); g_status.line_buff_len = len - count; shift_block( win->file_info, win->rline, start, -count ); entab_linebuff( win->file_info->inflate_tabs, win->file_info->ptab_size ); win->file_info->modified = TRUE; win->file_info->dirty = GLOBAL; win->ll->type |= DIRTY; /* * 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( TDE_WIN *window ){register int len; /* length of current line */register TDE_WIN *win; /* put window pointer in a register */line_list_ptr next_node;int rc; win = window; /* * don't dup a NULL line */ if (win->ll->len == EOF || un_copy_line( win->ll, win, TRUE, TRUE ) == ERROR) return( ERROR ); rc = OK; len = win->ll->len; assert( len >= 0); assert( len < MAX_LINE_LENGTH ); next_node = new_line_text( win->ll->line, len, DIRTY, &rc ); if (rc == OK) { win->file_info->modified = TRUE; if (mode.do_backups == TRUE) rc = backup_file( win ); insert_node( win->file_info, win->ll, next_node ); syntax_check_lines( next_node, win->file_info->syntax ); adjust_windows_cursor( win, 1 ); restore_marked_block( 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 ); if (win->file_info->dirty != GLOBAL) win->file_info->dirty = NOT_LOCAL; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -