edit.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:128k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- */
- /*
- * edit.c: functions for Insert mode
- */
- #include "vim.h"
- #ifdef INSERT_EXPAND
- /*
- * definitions used for CTRL-X submode
- */
- #define CTRL_X_WANT_IDENT 0x100
- #define CTRL_X_NOT_DEFINED_YET (1)
- #define CTRL_X_SCROLL (2)
- #define CTRL_X_WHOLE_LINE (3)
- #define CTRL_X_FILES (4)
- #define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
- #define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
- #define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
- #define CTRL_X_FINISHED (8)
- #define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
- #define C_X_SKIP (7) /* length of " Adding" */
- char *ctrl_x_msgs[] =
- {
- " Adding Keyword completion (^N/^P)", /* ctrl_x_mode == 0, ^P/^N compl. */
- " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)",
- /* Scroll has it's own msgs, in it's place there is the msg for local
- * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL) -- Acevedo */
- " Adding Keyword Local completion (^N/^P)",
- " Adding Whole line completion (^L/^N/^P)",
- " Adding File name completion (^F/^N/^P)",
- " Adding Tag completion (^]/^N/^P)",
- " Adding Path pattern completion (^N/^P)",
- " Adding Definition completion (^D/^N/^P)",
- NULL,
- " Adding Dictionary completion (^K/^N/^P)"
- };
- char_u e_hitend[] = "Hit end of paragraph";
- char_u e_hitend_f[] = "Hit end of paragraph (forward)";
- char_u e_hitend_b[] = "Hit end of paragraph (backward)";
- char_u e_patnotf_f[] = "Pattern not found (forward)";
- char_u e_patnotf_b[] = "Pattern not found (backward)";
- /*
- * Structure used to store one match for insert completion.
- */
- struct Completion
- {
- struct Completion *next;
- struct Completion *prev;
- char_u *str; /* matched text */
- char_u *fname; /* file containing the match */
- int original; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
- };
- /* the original text when the expansion begun */
- #define ORIGINAL_TEXT (1)
- #define FREE_FNAME (2)
- /*
- * All the current matches are stored in a list.
- * "first_match" points to the start of the list.
- * "curr_match" points to the currently selected entry.
- */
- static struct Completion *first_match = NULL;
- static struct Completion *curr_match = NULL;
- static int started_completion;
- static char_u *complete_pat;
- static int save_sm;
- static char_u *original_text = NULL; /* text before completion */
- static int continue_mode = 0;
- static int add_completion __ARGS((char_u *str, int len, char_u *, int dir, int reuse));
- static int make_cyclic __ARGS((void));
- static void complete_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags));
- static void free_completions __ARGS((void));
- static void clear_insexp __ARGS((void));
- static int ins_expand_pre __ARGS((int c));
- static BUF *next_buf __ARGS((BUF *buf, int flag));
- static int get_expansion __ARGS((FPOS *ini, int dir));
- static int ins_complete __ARGS((int c));
- static int quote_meta __ARGS((char_u *dest, char_u *str, int len));
- #endif /* INSERT_EXPAND */
- #define BACKSPACE_CHAR 1
- #define BACKSPACE_WORD 2
- #define BACKSPACE_WORD_NOT_SPACE 3
- #define BACKSPACE_LINE 4
- static void edit_putchar __ARGS((int c, int highlight));
- static void undisplay_dollar __ARGS((void));
- static void change_indent __ARGS((int type, int amount, int round, int replaced));
- static void insert_special __ARGS((int, int, int));
- static void redo_literal __ARGS((int c));
- static void start_arrow __ARGS((FPOS *end_insert_pos));
- static void stop_insert __ARGS((FPOS *end_insert_pos));
- static int echeck_abbr __ARGS((int));
- static void replace_push_off __ARGS((int c));
- static int replace_pop __ARGS((void));
- static void replace_join __ARGS((int off));
- static void replace_pop_ins __ARGS((void));
- static void replace_flush __ARGS((void));
- static void replace_do_bs __ARGS((void));
- static int ins_reg __ARGS((void));
- static int ins_esc __ARGS((long *count, int need_redraw, int cmdchar));
- #ifdef RIGHTLEFT
- static void ins_ctrl_ __ARGS((void));
- #endif
- static void ins_shift __ARGS((int c, int lastc));
- static void ins_del __ARGS((void));
- static int ins_bs __ARGS((int c, int mode, int *inserted_space_p));
- #ifdef USE_MOUSE
- static void ins_mouse __ARGS((int c));
- #endif
- static void ins_left __ARGS((void));
- static void ins_home __ARGS((void));
- static void ins_end __ARGS((void));
- static void ins_s_left __ARGS((void));
- static void ins_right __ARGS((void));
- static void ins_s_right __ARGS((void));
- static void ins_up __ARGS((void));
- static void ins_pageup __ARGS((void));
- static void ins_down __ARGS((void));
- static void ins_pagedown __ARGS((void));
- static int ins_tab __ARGS((void));
- static int ins_eol __ARGS((int c));
- #ifdef DIGRAPHS
- static int ins_digraph __ARGS((void));
- #endif
- static int ins_copychar __ARGS((linenr_t lnum));
- #ifdef SMARTINDENT
- static void ins_try_si __ARGS((int c));
- #endif
- static colnr_t get_nolist_virtcol __ARGS((void));
- static FPOS Insstart; /* This is where the latest
- * insert/append mode started. */
- static colnr_t Insstart_textlen; /* length of line when insert started */
- static colnr_t Insstart_blank_vcol; /* vcol for first inserted blank */
- static char_u *last_insert = NULL; /* the text of the previous insert */
- static int last_insert_skip; /* nr of chars in front of previous insert */
- static int new_insert_skip; /* nr of chars in front of current insert */
- #ifdef CINDENT
- static int can_cindent; /* may do cindenting on this line */
- #endif
- static int old_indent = 0; /* for ^^D command in insert mode */
- #ifdef RIGHTLEFT
- int revins_on; /* reverse insert mode on */
- int revins_chars; /* how much to skip after edit */
- int revins_legal; /* was the last char 'legal'? */
- int revins_scol; /* start column of revins session */
- #endif
- /*
- * edit(): Start insering text.
- *
- * "cmdchar" can be:
- * 'i' normal insert command
- * 'a' normal append command
- * 'R' replace command
- * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo,
- * but still only one <CR> is inserted. The <Esc> is not used for redo.
- * 'g' "gI" command.
- *
- * This function is not called recursively. For CTRL-O commands, it returns
- * and lets the caller handle the Normal-mode command.
- *
- * Return TRUE if a CTRL-O command caused the return (insert mode pending).
- */
- int
- edit(cmdchar, startln, count)
- int cmdchar;
- int startln; /* if set, insert at start of line */
- long count;
- {
- int c = 0;
- char_u *ptr;
- int lastc;
- colnr_t mincol;
- static linenr_t o_lnum = 0;
- static int o_eol = FALSE;
- int need_redraw = FALSE;
- int i;
- int did_backspace = TRUE; /* previous char was backspace */
- #ifdef CINDENT
- int line_is_white = FALSE; /* line is empty before insert */
- #endif
- linenr_t old_topline = 0; /* topline before insertion */
- int inserted_space = FALSE; /* just inserted a space */
- int has_startsel; /* may start selection */
- /* sleep before redrawing, needed for "CTRL-O :" that results in an
- * error message */
- check_for_delay(TRUE);
- #ifdef INSERT_EXPAND
- clear_insexp(); /* clear stuff for ctrl-x mode */
- #endif
- #ifdef USE_MOUSE
- /*
- * When doing a paste with the middle mouse button, Insstart is set to
- * where the paste started.
- */
- if (where_paste_started.lnum != 0)
- Insstart = where_paste_started;
- else
- #endif
- {
- Insstart = curwin->w_cursor;
- if (startln)
- Insstart.col = 0;
- }
- Insstart_textlen = linetabsize(ml_get_curline());
- Insstart_blank_vcol = MAXCOL;
- if (cmdchar != NUL && !restart_edit)
- {
- ResetRedobuff();
- AppendNumberToRedobuff(count);
- AppendCharToRedobuff(cmdchar);
- if (cmdchar == 'g') /* "gI" command */
- AppendCharToRedobuff('I');
- else if (cmdchar == 'r') /* "r<CR>" command */
- count = 1; /* insert only one <CR> */
- }
- if (cmdchar == 'R')
- {
- #ifdef FKMAP
- if (p_fkmap && p_ri)
- {
- beep_flush();
- EMSG(farsi_text_3); /* encoded in Farsi */
- State = INSERT;
- }
- else
- #endif
- State = REPLACE;
- }
- else
- State = INSERT;
- #if defined(USE_GUI_WIN32) && defined(MULTI_BYTE_IME)
- ImeSetOriginMode();
- #endif
- /*
- * Need to recompute the cursor position, it might move when the cursor is
- * on a TAB or special character.
- */
- curs_columns(TRUE);
- #ifdef USE_MOUSE
- setmouse();
- #endif
- #ifdef SHOWCMD
- clear_showcmd();
- #endif
- #ifdef RIGHTLEFT
- /* there is no reverse replace mode */
- revins_on = (State == INSERT && p_ri);
- if (revins_on)
- undisplay_dollar();
- revins_chars = 0;
- revins_legal = 0;
- revins_scol = -1;
- #endif
- /* if 'keymodel' contains "startsel", may start selection on shifted
- * special key */
- has_startsel = (vim_strchr(p_km, 'a') != NULL);
- /*
- * Handle restarting Insert mode.
- * Don't do this for CTRL-O . (repeat an insert): we get here with
- * restart_edit non-zero, and something in the stuff buffer.
- */
- if (restart_edit && stuff_empty())
- {
- #ifdef USE_MOUSE
- /*
- * After a paste we consider text typed to be part of the insert for
- * the pasted text. You can backspace over the paste text too.
- */
- if (where_paste_started.lnum)
- arrow_used = FALSE;
- else
- #endif
- arrow_used = TRUE;
- restart_edit = 0;
- /*
- * If the cursor was after the end-of-line before the CTRL-O and it is
- * now at the end-of-line, put it after the end-of-line (this is not
- * correct in very rare cases).
- * Also do this if curswant is greater than the current virtual
- * column. Eg after "^O$" or "^O80|".
- */
- validate_virtcol();
- update_curswant();
- if ( ((o_eol && curwin->w_cursor.lnum == o_lnum)
- || curwin->w_curswant > curwin->w_virtcol)
- && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL
- && *(ptr + 1) == NUL)
- ++curwin->w_cursor.col;
- }
- else
- {
- arrow_used = FALSE;
- o_eol = FALSE;
- }
- #ifdef USE_MOUSE
- where_paste_started.lnum = 0;
- #endif
- #ifdef CINDENT
- can_cindent = TRUE;
- #endif
- /*
- * If 'showmode' is set, show the current (insert/replace/..) mode.
- * A warning message for changing a readonly file is given here, before
- * actually changing anything. It's put after the mode, if any.
- */
- i = 0;
- if (p_smd)
- i = showmode();
- if (!p_im)
- change_warning(i + 1);
- #ifdef CURSOR_SHAPE
- ui_cursor_shape(); /* may show different cursor shape */
- #endif
- #ifdef DIGRAPHS
- do_digraph(-1); /* clear digraphs */
- #endif
- /*
- * Get the current length of the redo buffer, those characters have to be
- * skipped if we want to get to the inserted characters.
- */
- ptr = get_inserted();
- if (ptr == NULL)
- new_insert_skip = 0;
- else
- {
- new_insert_skip = STRLEN(ptr);
- vim_free(ptr);
- }
- old_indent = 0;
- for (;;)
- {
- #ifdef RIGHTLEFT
- if (!revins_legal)
- revins_scol = -1; /* reset on illegal motions */
- else
- revins_legal = 0;
- #endif
- if (arrow_used) /* don't repeat insert when arrow key used */
- count = 0;
- /* set curwin->w_curswant for next K_DOWN or K_UP */
- if (!arrow_used)
- curwin->w_set_curswant = TRUE;
- /*
- * When emsg() was called msg_scroll will have been set.
- */
- msg_scroll = FALSE;
- /*
- * If we inserted a character at the last position of the last line in
- * the window, scroll the window one line up. This avoids an extra
- * redraw.
- * This is detected when the cursor column is smaller after inserting
- * something.
- * Don't do this when the topline changed already, it has
- * already been adjusted (by insertchar() calling open_line())).
- */
- if (need_redraw && curwin->w_p_wrap && !did_backspace &&
- curwin->w_topline == old_topline)
- {
- mincol = curwin->w_wcol;
- validate_cursor_col();
- if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts &&
- curwin->w_wrow == curwin->w_winpos +
- curwin->w_height - 1 - p_so &&
- curwin->w_cursor.lnum != curwin->w_topline)
- {
- set_topline(curwin, curwin->w_topline + 1);
- update_topline();
- #ifdef SYNTAX_HL
- /* recompute syntax hl., starting with current line */
- syn_changed(curwin->w_cursor.lnum);
- #endif
- update_screen(VALID_TO_CURSCHAR);
- need_redraw = FALSE;
- }
- else
- update_topline();
- }
- else
- update_topline();
- did_backspace = FALSE;
- /*
- * redraw is postponed until here to make 'dollar' option work
- * correctly.
- */
- validate_cursor(); /* may set must_redraw */
- if (need_redraw || must_redraw)
- {
- update_screenline();
- if (curwin->w_redr_status == TRUE)
- win_redr_status(curwin); /* display [+] if required */
- need_redraw = FALSE;
- }
- else if (clear_cmdline || redraw_cmdline)
- showmode(); /* clear cmdline, show mode and ruler */
- showruler(FALSE);
- setcursor();
- update_curswant();
- emsg_on_display = FALSE; /* may remove error message now */
- old_topline = curwin->w_topline;
- #ifdef USE_GUI_WIN32
- dont_scroll = FALSE; /* allow scrolling here */
- #endif
- lastc = c; /* remember previous char for CTRL-D */
- c = vgetc();
- #ifdef RIGHTLEFT
- if (p_hkmap && KeyTyped)
- c = hkmap(c); /* Hebrew mode mapping */
- #endif
- #ifdef FKMAP
- if (p_fkmap && KeyTyped)
- c = fkmap(c); /* Farsi mode mapping */
- #endif
- #ifdef INSERT_EXPAND
- /*
- * Prepare for or stop ctrl-x mode.
- */
- need_redraw |= ins_expand_pre(c);
- #endif
- #ifdef DIGRAPHS
- c = do_digraph(c);
- #endif
- if (c == Ctrl('V') || c == Ctrl('Q'))
- {
- if (redrawing() && !char_avail())
- edit_putchar('^', TRUE);
- AppendToRedobuff((char_u *)"