home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
useful
/
util
/
edit
/
vim
/
src
/
edit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-09
|
32KB
|
1,296 lines
/* vi:ts=4:sw=4
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Read the file "credits.txt" for a list of people who contributed.
* Read the file "uganda.txt" for copying and usage conditions.
*/
/*
* edit.c: functions for insert mode
*/
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
#include "ops.h" /* for operator */
extern char_u *get_inserted();
static void start_arrow __ARGS((void));
static void stop_arrow __ARGS((void));
static void stop_insert __ARGS((void));
static int echeck_abbr __ARGS((int));
int arrow_used; /* Normally FALSE, set to TRUE after hitting
* cursor key in insert mode. Used by vgetorpeek()
* to decide when to call u_sync() */
int restart_edit = 0; /* call edit when next command finished */
static char_u *last_insert = NULL;
/* the text of the previous insert */
static int last_insert_skip;
/* number of chars in front of the previous insert */
static int new_insert_skip;
/* number of chars in front of the current insert */
void
edit(count)
long count;
{
int c;
int cc;
char_u *ptr;
char_u *saved_line = NULL; /* saved line for replace mode */
linenr_t saved_lnum = 0; /* lnum of saved line */
int saved_char = NUL; /* char replaced by NL */
linenr_t lnum;
int temp = 0;
int mode;
int nextc = 0;
int lastc = 0;
colnr_t mincol;
static linenr_t o_lnum = 0;
static int o_eol = FALSE;
#ifdef WEBB_KEYWORD_COMPL
FPOS complete_pos;
FPOS first_match;
char_u *complete_pat = NULL;
char_u *completion_str = NULL;
char_u *last_completion_str = NULL;
char_u *tmp_ptr;
int previous_c = 0;
int complete_col = 0; /* init for gcc */
int complete_direction;
int complete_any_word = 0; /* true -> ^N/^P hit with no prefix
* init for gcc */
int done;
int found_error = FALSE;
char_u backup_char = 0; /* init for gcc */
c = NUL;
#endif /* WEBB_KEYWORD_COMPL */
if (restart_edit)
{
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).
*/
if (o_eol && curwin->w_cursor.lnum == o_lnum &&
*((ptr = ml_get(curwin->w_cursor.lnum)) + curwin->w_cursor.col) != NUL &&
*(ptr + curwin->w_cursor.col + 1) == NUL)
++curwin->w_cursor.col;
}
else
{
arrow_used = FALSE;
o_eol = FALSE;
}
#ifdef DIGRAPHS
dodigraph(-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();
new_insert_skip = STRLEN(ptr);
free(ptr);
old_indent = 0;
for (;;)
{
if (arrow_used) /* don't repeat insert when arrow key used */
count = 0;
if (!arrow_used)
curwin->w_set_curswant = TRUE; /* set curwin->w_curswant for next K_DARROW or K_UARROW */
cursupdate(); /* Figure out where the cursor is based on curwin->w_cursor. */
showruler(0);
setcursor();
#ifdef WEBB_KEYWORD_COMPL
previous_c = c;
#endif /* WEBB_KEYWORD_COMPL */
if (nextc) /* character remaining from CTRL-V */
{
c = nextc;
nextc = 0;
}
else
{
c = vgetc();
if (c == Ctrl('C'))
got_int = FALSE;
}
#ifdef WEBB_KEYWORD_COMPL
if (previous_c == Ctrl('N') || previous_c == Ctrl('P'))
{
/* Show error message from attempted keyword completion (probably
* 'Pattern not found') until another key is hit, then go back to
* showing what mode we are in.
*/
showmode();
if (c != Ctrl('N') && c != Ctrl('P'))
{
/* Get here when we have finished typing a sequence of ^N and
* ^P. Free up memory that was used, and make sure we can redo
* the insert.
*/
if (completion_str != NULL)
AppendToRedobuff(completion_str);
free(complete_pat);
free(completion_str);
free(last_completion_str);
complete_pat = completion_str = last_completion_str = NULL;
}
}
#endif /* WEBB_KEYWORD_COMPL */
if (c != Ctrl('D')) /* remember to detect ^^D and 0^D */
lastc = c;
/*
* In replace mode a backspace puts the original text back.
* We save the current line to be able to do that.
* If characters are appended to the line, they will be deleted.
* If we start a new line (with CR) the saved line will be empty, thus
* the characters will be deleted.
* If we backspace over the new line, that line will be saved.
*/
if (State == REPLACE && saved_lnum != curwin->w_cursor.lnum)
{
free(saved_line);
saved_line = strsave(ml_get(curwin->w_cursor.lnum));
saved_lnum = curwin->w_cursor.lnum;
}
#ifdef DIGRAPHS
c = dodigraph(c);
#endif /* DIGRAPHS */
if (c == Ctrl('V'))
{
screen_start();
screen_outchar('^', curwin->w_row, curwin->w_col);
AppendToRedobuff((char_u *)"\026"); /* CTRL-V */
cursupdate();
setcursor();
c = get_literal(&nextc);
insertchar(c);
continue;
}
switch (c) /* handle character in insert mode */
{
case Ctrl('O'): /* execute one command */
if (echeck_abbr(Ctrl('O') + 0x100))
break;
count = 0;
if (State == INSERT)
restart_edit = 'I';
else
restart_edit = 'R';
o_lnum = curwin->w_cursor.lnum;
o_eol = (gchar_cursor() == NUL);
goto doESCkey;
case ESC: /* an escape ends input mode */
if (echeck_abbr(ESC + 0x100))
break;
/*FALLTHROUGH*/
case Ctrl('C'):
doESCkey:
if (!arrow_used)
{
AppendToRedobuff(ESC_STR);
if (--count > 0) /* repeat what was typed */
{
(void)start_redo_ins();
continue;
}
stop_insert();
}
if (!restart_edit)
curwin->w_set_curswant = TRUE;
/*
* The cursor should end up on the last inserted character.
*/
if (curwin->w_cursor.col != 0 && (!restart_edit || gchar_cursor() == NUL) && !p_ri)
dec_cursor();
if (extraspace) /* did reverse replace in column 0 */
{
(void)delchar(FALSE);
updateline();
extraspace = FALSE;
}
State = NORMAL;
/* inchar() may have deleted the "INSERT" message */
if (Recording)
showmode();
else if (p_smd)
MSG("");
free(saved_line);
old_indent = 0;
return;
/*
* Insert the previously inserted text.
* Last_insert actually is a copy of the redo buffer, so we
* first have to remove the command.
* For ^@ the trailing ESC will end the insert.
*/
case K_ZERO:
case Ctrl('A'):
stuff_inserted(NUL, 1L, (c == Ctrl('A')));
break;
/*
* insert the contents of a register
*/
case Ctrl('R'):
if (insertbuf(vgetc()) == FAIL)
beep();
break;
case Ctrl('B'): /* toggle reverse insert mode */
p_ri = !p_ri;
showmode();
break;
/*
* If the cursor is on an indent, ^T/^D insert/delete one
* shiftwidth. Otherwise ^T/^D behave like a TAB/backspace.
* This isn't completely compatible with
* vi, but the difference isn't very noticeable and now you can
* mix ^D/backspace and ^T/TAB without thinking about which one
* must be used.
*/
case Ctrl('T'): /* make indent one shiftwidth greater */
case Ctrl('D'): /* make indent one shiftwidth smaller */
stop_arrow();
AppendCharToRedobuff(c);
if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
{
--curwin->w_cursor.col;
(void)delchar(FALSE); /* delete the '^' or '0' */
if (lastc == '^')
old_indent = get_indent(); /* remember current indent */
/* determine offset from first non-blank */
temp = curwin->w_cursor.col;
beginline(TRUE);
temp -= curwin->w_cursor.col;
set_indent(0, TRUE); /* remove all indent */
}
else
{
ins_indent:
/* determine offset from first non-blank */
temp = curwin->w_cursor.col;
beginline(TRUE);
temp -= curwin->w_cursor.col;
shift_line(c == Ctrl('D'), TRUE, 1);
/* try to put cursor on same character */
temp += curwin->w_cursor.col;
}
if (temp <= 0)
curwin->w_cursor.col = 0;
else
curwin->w_cursor.