home *** CD-ROM | disk | FTP | other *** search
- From: mool@oce.nl (Bram Moolenaar)
- Newsgroups: comp.sources.misc
- Subject: v44i031: vim - Vi IMproved editor, v3.0, Part12/26
- Date: 16 Aug 1994 21:18:23 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <32rs1f$keu@sparky.sterling.com>
- X-Md4-Signature: 6e4b8a9e175c9588805902d12a2cfbec
-
- Submitted-by: mool@oce.nl (Bram Moolenaar)
- Posting-number: Volume 44, Issue 31
- Archive-name: vim/part12
- Environment: UNIX, AMIGA, MS-DOS, Windows NT
- Supersedes: vim: Volume 41, Issue 50-75
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: vim/doc/vim.1 vim/src/ops.c vim/src/proto/normal.pro
- # vim/src/term.c
- # Wrapped by kent@sparky on Mon Aug 15 21:44:05 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 12 (of 26)."'
- if test -f 'vim/doc/vim.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/doc/vim.1'\"
- else
- echo shar: Extracting \"'vim/doc/vim.1'\" \(5252 characters\)
- sed "s/^X//" >'vim/doc/vim.1' <<'END_OF_FILE'
- X.TH VIM 1 "1994 August 12"
- X.SH NAME
- Xvim \- Vi IMproved, a programmers text editor
- X.SH SYNOPSIS
- X.B vim
- X[options] [file ..]
- X.br
- X.B vim
- X[options] \-t tag
- X.br
- X.B vim
- X[options] \-e [errorfile]
- X.SH DESCRIPTION
- X.B Vim
- Xis a text editor that is upwards compatible to vi. It can be used to edit any
- XASCII text. It is especially useful for editing programs.
- X.PP
- XThere are a lot of enhancements above vi: multi level undo,
- Xmulti windows and buffers, command line
- Xediting, filename completion, on-line help, visual selection, etc..
- XRead difference.doc
- Xfor a summary of the differences between vi and Vim.
- X.PP
- XMost often
- X.B Vim
- Xis started to edit a single file with the command
- X.PP
- X vim file
- X.PP
- XMore generally VIM is started with:
- X.PP
- X vim [options] [filelist]
- X.PP
- XIf the filelist is missing, the editor will start with an empty buffer.
- XOtherwise exactly one out of the following three may be used to choose one or
- Xmore files to be edited.
- X.TP 12
- Xfile ..
- XA list of file names. The first one (alphabetically) will be
- Xthe current file and read into the buffer. The cursor will be
- Xpositioned on the first line of the buffer. You can get to the other files
- Xwith the ":next" command.
- X.TP
- X-t {tag}
- XThe file to edit and the initial cursor position depends on a "tag", a sort
- Xof goto label. {tag} is looked up in the tags file, the associated file
- Xbecomes the current file and the associated command is executed. Mostly this
- Xis used for C programs. {tag} then should be a function name. The effect is
- Xthat the file containing that function becomes the current file and the
- Xcursor is positioned on the start of the function (see reference.doc,
- Xsection "tag searches").
- X.TP
- X-e [errorfile]
- XStart in quickFix mode. The file [errorfile]
- Xis read and the first error is displayed. If [errorfile] is omitted the file
- Xname is obtained from the 'errorfile' option (defaults to "AztecC.Err" for
- Xthe Amiga, "errors" on other systems). Further errors can be jumped to
- Xwith the ":cn" command. See reference.doc section 5.5.
- X.SH OPTIONS
- XThe options, if present, must precede the filelist. The options may be given
- Xin any order.
- X.TP 12
- X-r
- XRecovery mode. The swap file is used to recover a crashed editing session. The
- Xswap file is a file with the same file name as the text file with ".swp"
- Xappended. See reference.doc, chapter "Recovery after a crash".
- X.TP
- X-v
- XView mode. The 'readonly' option will be set. You can still
- Xedit the buffer, but will be prevented from accidently
- Xoverwriting a file. If you do want to overwrite a file, add
- Xan exclamation mark to the Ex command, as in ":w!".
- XThe -v option also implies the -n option (see below).
- XThe 'readonly' option can be reset with ":set noro" (see reference.doc,
- Xoptions chapter).
- X.TP
- X-b
- XBinary. A few options will be set that makes it possible to edit a binary or
- Xexecutable file.
- X.TP
- X+[num]
- XFor the first file the cursor will be positioned on line
- X"num". If "num" is missing, the cursor will be positioned on
- Xthe last line.
- X.TP
- X+/pat
- XFor the first file the cursor will be positioned on the
- Xfirst occurrence of "pat" (see reference.doc,
- Xsection "pattern searches" for the available search
- Xpatterns).
- X.TP
- X+{command}
- X.TP
- X-c {command}
- X{command} will be executed after the
- Xfirst file has been read. {command} is interpreted as an Ex
- Xcommand. If the {command} contains spaces it must
- Xbe enclosed in double quotes (this depends on the shell that
- Xis used).
- XExample: Vim "+set si" main.c
- X.TP
- X-x
- X(Amiga only) Vim is not restarted to open a new window. This option should
- Xbe used when Vim is executed by a program that will wait for the edit
- Xsession to finish (e.g. mail). The ":sh" and ":!" commands will not work.
- X.TP
- X-o[N]
- XOpen N windows. When N is omitted, open one window for each file.
- X.TP
- X-n
- XNo swap file will be used. Recovery after a crash
- Xwill be impossible. Handy if you want to edit a file on a
- Xvery slow medium (e.g. floppy). Can also be done with ":set
- Xuc=0". Can be undone with ":set uc=200".
- X.TP
- X-s {scriptin}
- XThe script file {scriptin} is read. The characters in the
- Xfile are interpreted as if you had typed them. The same can
- Xbe done with the command ":source! {scriptin}". If the end
- Xof the file is reached before the editor exits, further
- Xcharacters are read from the keyboard.
- X.TP
- X-w {scriptout}
- XAll the characters that you type are recorded in the file
- X{scriptout}, until you exit VIM. This is useful if you want
- Xto create a script file to be used with "vim -s" or
- X":source!".
- X.TP
- X-T terminal
- XTells Vim the name of the terminal you are using. Should be a terminal known
- Xto Vim (builtin) or defined in the termcap file.
- X.TP
- X-d device
- XOpen "device" for use as a terminal. Only on the Amiga. Example:
- X"\-d con:20/30/600/150".
- X.SH SEE ALSO
- XVim documentation:
- X.TP 12
- Xreference.doc:
- XA complete reference of Vim (long)
- X.TP
- Xwindows.doc:
- XExplanation of the multi windows and buffers commands and options
- X.TP
- Xindex:
- XOverview of all command characters (useful when adding new mappings)
- X.TP
- Xdifference.doc:
- XOverview of the differences between vi and Vim
- X.TP
- Xunix.doc:
- XUnix-specific comments
- X.TP
- Xvim.hlp:
- XFile used by the on-line help (short)
- X.SH AUTHOR
- XMost of VIM was made by Bram Moolenaar.
- X.br
- XVIM is based on Stevie, worked on by: Tim Thompson,
- XTony Andrews and G.R. (Fred) Walter
- X.SH BUGS
- XProbably.
- END_OF_FILE
- if test 5252 -ne `wc -c <'vim/doc/vim.1'`; then
- echo shar: \"'vim/doc/vim.1'\" unpacked with wrong size!
- fi
- # end of 'vim/doc/vim.1'
- fi
- if test -f 'vim/src/ops.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/src/ops.c'\"
- else
- echo shar: Extracting \"'vim/src/ops.c'\" \(39495 characters\)
- sed "s/^X//" >'vim/src/ops.c' <<'END_OF_FILE'
- X/* vi:ts=4:sw=4
- X *
- X * VIM - Vi IMproved by Bram Moolenaar
- X *
- X * Read the file "credits.txt" for a list of people who contributed.
- X * Read the file "uganda.txt" for copying and usage conditions.
- X */
- X
- X/*
- X * ops.c: implementation of various operators: doshift, dodelete, dotilde,
- X * dochange, doyank, doput, dojoin
- X */
- X
- X#include "vim.h"
- X#include "globals.h"
- X#include "proto.h"
- X#include "param.h"
- X#include "ops.h"
- X
- X/*
- X * We have one yank buffer for normal yanks and puts, nine yank buffers for
- X * deletes and 26 yank buffers for use by name.
- X * Each yank buffer is an array of pointers to lines.
- X */
- Xstatic struct yankbuf
- X{
- X char_u **y_array; /* pointer to array of line pointers */
- X linenr_t y_size; /* number of lines in y_array */
- X char_u y_type; /* MLINE, MCHAR or MBLOCK */
- X} y_buf[36]; /* 0..9 = number buffers, 10..35 = char buffers */
- X
- Xstatic struct yankbuf *y_current; /* ptr to current yank buffer */
- Xstatic int yankappend; /* TRUE when appending */
- Xstatic struct yankbuf *y_previous = NULL; /* ptr to last written yank buffer */
- X
- Xstatic void get_yank_buffer __ARGS((int));
- Xstatic int stuff_yank __ARGS((int, char_u *));
- Xstatic void free_yank __ARGS((long));
- Xstatic void free_yank_all __ARGS((void));
- Xstatic void block_prep __ARGS((linenr_t, int));
- X
- X/* variables use by block_prep, dodelete and doyank */
- Xstatic int startspaces;
- Xstatic int endspaces;
- Xstatic int textlen;
- Xstatic char_u *textstart;
- Xstatic colnr_t textcol;
- X
- X/*
- X * doshift - handle a shift operation
- X */
- X void
- Xdoshift(op, curs_top, amount)
- X int op;
- X int curs_top;
- X int amount;
- X{
- X register long i;
- X int first_char;
- X
- X if (!u_save((linenr_t)(curwin->w_cursor.lnum - 1), (linenr_t)(curwin->w_cursor.lnum + nlines)))
- X return;
- X
- X for (i = nlines; --i >= 0; )
- X {
- X first_char = *ml_get(curwin->w_cursor.lnum);
- X if (first_char == NUL) /* empty line */
- X curwin->w_cursor.col = 0;
- X /*
- X * Don't move the line right if it starts with # and p_si is set.
- X */
- X else if (!curbuf->b_p_si || first_char != '#')
- X {
- X /* if (Visual_block)
- X shift the block, not the whole line
- X else */
- X shift_line(op == LSHIFT, p_sr, amount);
- X }
- X ++curwin->w_cursor.lnum;
- X }
- X
- X if (curs_top) /* put cursor on first line, for ">>" */
- X curwin->w_cursor.lnum -= nlines;
- X else
- X --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */
- X updateScreen(CURSUPD);
- X
- X if (nlines > p_report)
- X smsg((char_u *)"%ld line%s %ced", nlines, plural(nlines),
- X (op == RSHIFT) ? '>' : '<');
- X}
- X
- X/*
- X * shift the current line one shiftwidth left (if left != 0) or right
- X * leaves cursor on first blank in the line
- X */
- X void
- Xshift_line(left, round, amount)
- X int left;
- X int round;
- X int amount;
- X{
- X register int count;
- X register int i, j;
- X int p_sw = (int)curbuf->b_p_sw;
- X
- X count = get_indent(); /* get current indent */
- X
- X if (round) /* round off indent */
- X {
- X i = count / p_sw; /* number of p_sw rounded down */
- X j = count % p_sw; /* extra spaces */
- X if (j && left) /* first remove extra spaces */
- X --amount;
- X if (left)
- X {
- X i -= amount;
- X if (i < 0)
- X i = 0;
- X }
- X else
- X i += amount;
- X count = i * p_sw;
- X }
- X else /* original vi indent */
- X {
- X if (left)
- X {
- X count -= p_sw * amount;
- X if (count < 0)
- X count = 0;
- X }
- X else
- X count += p_sw * amount;
- X }
- X set_indent(count, TRUE); /* set new indent */
- X}
- X
- X/*
- X * check if character is name of yank buffer
- X * Note: There is no check for 0 (default register), caller should do this
- X */
- X int
- Xis_yank_buffer(c, write)
- X int c;
- X int write; /* if TRUE check for writable buffers */
- X{
- X if (isalnum(c) || (!write && strchr(".%:", c) != NULL) || c == '"')
- X return TRUE;
- X return FALSE;
- X}
- X
- X/*
- X * Set y_current and yankappend, according to the value of yankbuffer.
- X *
- X * If yankbuffer is 0 and writing, use buffer 0
- X * If yankbuffer is 0 and reading, use previous buffer
- X */
- X static void
- Xget_yank_buffer(writing)
- X int writing;
- X{
- X register int i;
- X
- X yankappend = FALSE;
- X if (((yankbuffer == 0 && !writing) || yankbuffer == '"') && y_previous != NULL)
- X {
- X y_current = y_previous;
- X return;
- X }
- X i = yankbuffer;
- X if (isdigit(i))
- X i -= '0';
- X else if (islower(i))
- X i -= 'a' - 10;
- X else if (isupper(i))
- X {
- X i -= 'A' - 10;
- X yankappend = TRUE;
- X }
- X else /* not 0-9, a-z or A-Z: use buffer 0 */
- X i = 0;
- X y_current = &(y_buf[i]);
- X if (writing) /* remember the buffer we write into for doput() */
- X y_previous = y_current;
- X}
- X
- X/*
- X * start or stop recording into a yank buffer
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xdorecord(c)
- X int c;
- X{
- X char_u *p;
- X static int bufname;
- X int retval;
- X
- X if (Recording == FALSE) /* start recording */
- X {
- X if (!isalnum(c) && c != '"') /* registers 0-9, a-z and " are allowed */
- X retval = FAIL;
- X else
- X {
- X Recording = TRUE;
- X showmode();
- X bufname = c;
- X retval = OK;
- X }
- X }
- X else /* stop recording */
- X {
- X Recording = FALSE;
- X MSG("");
- X /* the trailing 'q' command will not have been put in the buffer */
- X p = get_recorded();
- X if (p == NULL)
- X retval = FAIL;
- X else
- X retval = (stuff_yank(bufname, p));
- X }
- X return retval;
- X}
- X
- X/*
- X * stuff string 'p' into yank buffer 'bufname' (append if uppercase)
- X * 'p' is assumed to be alloced.
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X static int
- Xstuff_yank(bufname, p)
- X int bufname;
- X char_u *p;
- X{
- X char_u *lp;
- X char_u **pp;
- X
- X yankbuffer = bufname;
- X /* check for read-only buffer */
- X if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
- X return FAIL;
- X get_yank_buffer(TRUE);
- X if (yankappend && y_current->y_array != NULL)
- X {
- X pp = &(y_current->y_array[y_current->y_size - 1]);
- X lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
- X if (lp == NULL)
- X {
- X free(p);
- X return FAIL;
- X }
- X STRCPY(lp, *pp);
- X STRCAT(lp, p);
- X free(p);
- X free(*pp);
- X *pp = lp;
- X }
- X else
- X {
- X free_yank_all();
- X if ((y_current->y_array = (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
- X {
- X free(p);
- X return FAIL;
- X }
- X y_current->y_array[0] = p;
- X y_current->y_size = 1;
- X y_current->y_type = MCHAR; /* used to be MLINE, why? */
- X }
- X return OK;
- X}
- X
- X/*
- X * execute a yank buffer (register): copy it into the stuff buffer
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xdoexecbuf(c)
- X int c;
- X{
- X static int lastc = NUL;
- X long i;
- X
- X if (c == '@') /* repeat previous one */
- X c = lastc;
- X if (!is_yank_buffer(c, FALSE)) /* check for valid buffer */
- X return FAIL;
- X lastc = c;
- X
- X if (c == ':') /* use last command line */
- X {
- X if (last_cmdline == NULL)
- X {
- X EMSG(e_nolastcmd);
- X return FAIL;
- X }
- X free(new_last_cmdline); /* don't keep the command line containing @: */
- X new_last_cmdline = NULL;
- X if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
- X return FAIL;
- X if (ins_typestr(last_cmdline, FALSE) == FAIL)
- X return FAIL;
- X }
- X else
- X {
- X yankbuffer = c;
- X get_yank_buffer(FALSE);
- X if (y_current->y_array == NULL)
- X return FAIL;
- X
- X for (i = y_current->y_size; --i >= 0; )
- X {
- X /* insert newline between lines and after last line if type is MLINE */
- X if (y_current->y_type == MLINE || i < y_current->y_size - 1)
- X {
- X if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
- X return FAIL;
- X }
- X if (ins_typestr(y_current->y_array[i], FALSE) == FAIL)
- X return FAIL;
- X }
- X Exec_reg = TRUE; /* disable the 'q' command */
- X }
- X return OK;
- X}
- X
- X/*
- X * insert a yank buffer: copy it into the Read buffer
- X * used by CTRL-R command in insert mode
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xinsertbuf(c)
- X int c;
- X{
- X long i;
- X
- X /*
- X * It is possible to get into an endless loop by having CTRL-R a in
- X * register a and then, in insert mode, doing CTRL-R a.
- X * If you hit CTRL-C, the loop will be broken here.
- X */
- X breakcheck();
- X if (got_int)
- X return FAIL;
- X
- X if (!is_yank_buffer(c, FALSE)) /* check for valid buffer */
- X return FAIL;
- X
- X if (c == '.') /* insert last inserted text */
- X {
- X stuff_inserted(NUL, 1L, TRUE);
- X return OK;
- X }
- X
- X if (c == '%') /* insert file name */
- X {
- X if (check_fname() == FAIL)
- X return FAIL;
- X stuffReadbuff(curbuf->b_xfilename);
- X return OK;
- X }
- X
- X if (c == ':') /* insert last command line */
- X {
- X if (last_cmdline == NULL)
- X {
- X EMSG(e_nolastcmd);
- X return FAIL;
- X }
- X stuffReadbuff(last_cmdline);
- X return OK;
- X }
- X
- X yankbuffer = c;
- X get_yank_buffer(FALSE);
- X if (y_current->y_array == NULL)
- X return FAIL;
- X
- X for (i = 0; i < y_current->y_size; ++i)
- X {
- X stuffReadbuff(y_current->y_array[i]);
- X /* insert newline between lines and after last line if type is MLINE */
- X if (y_current->y_type == MLINE || i < y_current->y_size - 1)
- X stuffReadbuff((char_u *)"\n");
- X }
- X return OK;
- X}
- X
- X/*
- X * dodelete - handle a delete operation
- X */
- X void
- Xdodelete()
- X{
- X register int n;
- X linenr_t lnum;
- X char_u *ptr;
- X char_u *new, *old;
- X linenr_t old_lcount = curbuf->b_ml.ml_line_count;
- X int did_yank = FALSE;
- X
- X /*
- X * Imitate the strange Vi behaviour: If the delete spans more than one line
- X * and mtype == MCHAR and the result is a blank line, make the delete
- X * linewise. Don't do this for the change command.
- X */
- X if (mtype == MCHAR && nlines > 1 && operator == DELETE)
- X {
- X ptr = ml_get(curbuf->b_endop.lnum) + curbuf->b_endop.col + mincl;
- X skipspace(&ptr);
- X if (*ptr == NUL && inindent())
- X mtype = MLINE;
- X }
- X
- X/*
- X * If a yank buffer was specified, put the deleted text into that buffer
- X */
- X if (yankbuffer != 0)
- X {
- X /* check for read-only buffer */
- X if (!is_yank_buffer(yankbuffer, TRUE))
- X {
- X beep();
- X return;
- X }
- X get_yank_buffer(TRUE); /* yank into specified buffer */
- X if (doyank(TRUE) == OK)
- X did_yank = TRUE;
- X }
- X
- X/*
- X * Put deleted text into register 1 and shift number buffers if
- X * the delete contains a line break.
- X * Overruled when a yankbuffer has been specified!
- X */
- X if (yankbuffer != 0 || mtype == MLINE || nlines > 1)
- X {
- X y_current = &y_buf[9];
- X free_yank_all(); /* free buffer nine */
- X for (n = 9; n > 1; --n)
- X y_buf[n] = y_buf[n - 1];
- X y_previous = y_current = &y_buf[1];
- X y_buf[1].y_array = NULL; /* set buffer one to empty */
- X yankbuffer = 0;
- X }
- X else if (yankbuffer == 0) /* yank into unnamed buffer */
- X get_yank_buffer(TRUE);
- X
- X /*
- X * Do a yank of whatever we're about to delete. If there's too much stuff
- X * to fit in the yank buffer, then get a confirmation before doing the
- X * delete. This is crude, but simple. And it avoids doing a delete of
- X * something we can't put back if we want.
- X */
- X if (yankbuffer == 0 && doyank(TRUE) == OK)
- X did_yank = TRUE;
- X
- X if (!did_yank)
- X {
- X if (ask_yesno((char_u *)"cannot yank; delete anyway") != 'y')
- X {
- X emsg(e_abort);
- X return;
- X }
- X }
- X
- X/*
- X * block mode
- X */
- X if (Visual_block)
- X {
- X if (!u_save((linenr_t)(curbuf->b_startop.lnum - 1), (linenr_t)(curbuf->b_endop.lnum + 1)))
- X return;
- X
- X for (lnum = curwin->w_cursor.lnum; curwin->w_cursor.lnum <= curbuf->b_endop.lnum; ++curwin->w_cursor.lnum)
- X {
- X block_prep(curwin->w_cursor.lnum, TRUE);
- X if (textlen == 0) /* nothing to delete */
- X continue;
- X
- X /*
- X * If we delete a TAB, it may be replaced by several characters.
- X * Thus the number of characters may increase!
- X */
- X n = textlen - startspaces - endspaces; /* number of chars deleted */
- X old = ml_get(curwin->w_cursor.lnum);
- X new = alloc((unsigned)STRLEN(old) + 1 - n);
- X if (new == NULL)
- X continue;
- X /* copy up to deleted part */
- X memmove((char *)new, (char *)old, (size_t)textcol);
- X /* insert spaces */
- X copy_spaces(new + textcol, (size_t)(startspaces + endspaces));
- X /* copy the part after the deleted part */
- X old += textcol + textlen;
- X memmove((char *)new + textcol + startspaces + endspaces,
- X (char *)old, STRLEN(old) + 1);
- X /* replace the line */
- X ml_replace(curwin->w_cursor.lnum, new, FALSE);
- X }
- X curwin->w_cursor.lnum = lnum;
- X CHANGED;
- X updateScreen(VALID_TO_CURSCHAR);
- X nlines = 0; /* no lines deleted */
- X }
- X else if (mtype == MLINE)
- X {
- X if (operator == CHANGE)
- X {
- X dellines((long)(nlines - 1), TRUE, TRUE);
- X if (!u_save_cursor())
- X return;
- X if (curbuf->b_p_ai) /* don't delete indent */
- X {
- X beginline(TRUE); /* put cursor on first non-white */
- X did_ai = TRUE; /* delete the indent when ESC hit */
- X }
- X while (delchar(FALSE) == OK) /* slow but simple */
- X ;
- X if (curwin->w_cursor.col > 0)
- X --curwin->w_cursor.col; /* put cursor on last char in line */
- X }
- X else
- X {
- X dellines(nlines, TRUE, TRUE);
- X }
- X u_clearline(); /* "U" command should not be possible after "dd" */
- X beginline(TRUE);
- X }
- X else if (nlines == 1) /* delete characters within one line */
- X {
- X if (!u_save_cursor())
- X return;
- X n = curbuf->b_endop.col - curbuf->b_startop.col + 1 - !mincl;
- X while (n-- > 0)
- X if (delchar(TRUE) == FAIL)
- X break;
- X }
- X else /* delete characters between lines */
- X {
- X if (!u_save_cursor()) /* save first line for undo */
- X return;
- X n = curwin->w_cursor.col;
- X while (curwin->w_cursor.col >= n) /* delete from cursor to end of line */
- X if (delchar(TRUE) == FAIL)
- X break;
- X
- X curbuf->b_startop = curwin->w_cursor; /* remember curwin->w_cursor */
- X ++curwin->w_cursor.lnum;
- X dellines((long)(nlines - 2), TRUE, TRUE); /* includes save for undo */
- X
- X if (!u_save_cursor()) /* save last line for undo */
- X return;
- X n = curbuf->b_endop.col - !mincl;
- X curwin->w_cursor.col = 0;
- X while (n-- >= 0) /* delete from start of line until endop */
- X if (delchar(TRUE) == FAIL)
- X break;
- X curwin->w_cursor = curbuf->b_startop; /* restore curwin->w_cursor */
- X (void)dojoin(FALSE, TRUE);
- X }
- X
- X if ((mtype == MCHAR && nlines == 1) || operator == CHANGE)
- X {
- X cursupdate();
- X updateline();
- X }
- X else
- X updateScreen(CURSUPD);
- X
- X msgmore(curbuf->b_ml.ml_line_count - old_lcount);
- X
- X /* correct endop for deleted text (for "']" command) */
- X if (Visual_block)
- X curbuf->b_endop.col = curbuf->b_startop.col;
- X else
- X curbuf->b_endop = curbuf->b_startop;
- X}
- X
- X/*
- X * dotilde - handle the (non-standard vi) tilde operator
- X */
- X void
- Xdotilde()
- X{
- X FPOS pos;
- X
- X if (!u_save((linenr_t)(curbuf->b_startop.lnum - 1), (linenr_t)(curbuf->b_endop.lnum + 1)))
- X return;
- X
- X pos = curbuf->b_startop;
- X if (Visual_block) /* block mode */
- X {
- X for (; pos.lnum <= curbuf->b_endop.lnum; ++pos.lnum)
- X {
- X block_prep(pos.lnum, FALSE);
- X pos.col = textcol;
- X while (--textlen >= 0)
- X {
- X swapchar(&pos);
- X if (inc(&pos) == -1) /* at end of file */
- X break;
- X }
- X }
- X }
- X else /* not block mode */
- X {
- X if (mtype == MLINE)
- X {
- X pos.col = 0;
- X curbuf->b_endop.col = STRLEN(ml_get(curbuf->b_endop.lnum));
- X if (curbuf->b_endop.col)
- X --curbuf->b_endop.col;
- X }
- X else if (!mincl)
- X dec(&(curbuf->b_endop));
- X
- X while (ltoreq(pos, curbuf->b_endop))
- X {
- X swapchar(&pos);
- X if (inc(&pos) == -1) /* at end of file */
- X break;
- X }
- X }
- X
- X if (mtype == MCHAR && nlines == 1 && !Visual_block)
- X {
- X cursupdate();
- X updateline();
- X }
- X else
- X updateScreen(CURSUPD);
- X
- X if (nlines > p_report)
- X smsg((char_u *)"%ld line%s ~ed", nlines, plural(nlines));
- X}
- X
- X/*
- X * If operator == UPPER: make uppercase,
- X * if operator == LOWER: make lowercase,
- X * else swap case of character at 'pos'
- X */
- X void
- Xswapchar(pos)
- X FPOS *pos;
- X{
- X int c;
- X
- X c = gchar(pos);
- X if (islower(c) && operator != LOWER)
- X {
- X pchar(*pos, toupper(c));
- X CHANGED;
- X }
- X else if (isupper(c) && operator != UPPER)
- X {
- X pchar(*pos, tolower(c));
- X CHANGED;
- X }
- X}
- X
- X/*
- X * dochange - handle a change operation
- X */
- X void
- Xdochange()
- X{
- X register colnr_t l;
- X
- X l = curbuf->b_startop.col;
- X
- X if (!no_op)
- X dodelete();
- X
- X if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum))
- X inc_cursor();
- X
- X startinsert(NUL, FALSE, (linenr_t)1);
- X}
- X
- X/*
- X * set all the yank buffers to empty (called from main())
- X */
- X void
- Xinit_yank()
- X{
- X register int i;
- X
- X for (i = 0; i < 36; ++i)
- X y_buf[i].y_array = NULL;
- X}
- X
- X/*
- X * Free "n" lines from the current yank buffer.
- X * Called for normal freeing and in case of error.
- X */
- X static void
- Xfree_yank(n)
- X long n;
- X{
- X if (y_current->y_array != NULL)
- X {
- X register long i;
- X
- X for (i = n; --i >= 0; )
- X {
- X if (i % 1000 == 999) /* this may take a while */
- X smsg((char_u *)"freeing %ld lines", i + 1);
- X free(y_current->y_array[i]);
- X }
- X free(y_current->y_array);
- X y_current->y_array = NULL;
- X if (n >= 1000)
- X MSG("");
- X }
- X}
- X
- X static void
- Xfree_yank_all()
- X{
- X free_yank(y_current->y_size);
- X}
- X
- X/*
- X * Yank the text between curwin->w_cursor and startpos into a yank buffer.
- X * If we are to append ("uppercase), we first yank into a new yank buffer and
- X * then concatenate the old and the new one (so we keep the old one in case
- X * of out-of-memory).
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xdoyank(deleting)
- X int deleting;
- X{
- X long i; /* index in y_array[] */
- X struct yankbuf *curr; /* copy of y_current */
- X struct yankbuf new; /* new yank buffer when appending */
- X char_u **new_ptr;
- X register linenr_t lnum; /* current line number */
- X long j;
- X int yanktype = mtype;
- X long yanklines = nlines;
- X linenr_t yankendlnum = curbuf->b_endop.lnum;
- X
- X char_u *pnew;
- X
- X /* check for read-only buffer */
- X if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
- X {
- X beep();
- X return FAIL;
- X }
- X if (!deleting) /* dodelete() already set y_current */
- X get_yank_buffer(TRUE);
- X
- X curr = y_current;
- X if (yankappend && y_current->y_array != NULL) /* append to existing contents */
- X y_current = &new;
- X else
- X free_yank_all(); /* free previously yanked lines */
- X
- X/*
- X * If the cursor was in column 1 before and after the movement, the
- X * yank is always linewise.
- X */
- X if (mtype == MCHAR && curbuf->b_startop.col == 0 && curbuf->b_endop.col == 0 && nlines > 1)
- X {
- X yanktype = MLINE;
- X if (mincl == FALSE && yankendlnum > curbuf->b_startop.lnum)
- X {
- X --yankendlnum;
- X --yanklines;
- X }
- X }
- X
- X y_current->y_size = yanklines;
- X y_current->y_type = yanktype; /* set the yank buffer type */
- X y_current->y_array = (char_u **)lalloc((long_u)(sizeof(char_u *) * yanklines), TRUE);
- X
- X if (y_current->y_array == NULL)
- X {
- X y_current = curr;
- X return FAIL;
- X }
- X
- X i = 0;
- X lnum = curbuf->b_startop.lnum;
- X
- X if (Visual_block)
- X {
- X/*
- X * block mode
- X */
- X y_current->y_type = MBLOCK; /* set the yank buffer type */
- X for ( ; lnum <= yankendlnum; ++lnum)
- X {
- X block_prep(lnum, FALSE);
- X if ((pnew = alloc(startspaces + endspaces + textlen + 1)) == NULL)
- X goto fail;
- X y_current->y_array[i++] = pnew;
- X copy_spaces(pnew, (size_t)startspaces);
- X pnew += startspaces;
- X STRNCPY(pnew, textstart, (size_t)textlen);
- X pnew += textlen;
- X copy_spaces(pnew, (size_t)endspaces);
- X pnew += endspaces;
- X *pnew = NUL;
- X }
- X }
- X else
- X {
- X/*
- X * there are three parts for non-block mode:
- X * 1. if yanktype != MLINE yank last part of the top line
- X * 2. yank the lines between startop and endop, inclusive when yanktype == MLINE
- X * 3. if yanktype != MLINE yank first part of the bot line
- X */
- X if (yanktype != MLINE)
- X {
- X if (yanklines == 1) /* startop and endop on same line */
- X {
- X j = curbuf->b_endop.col - curbuf->b_startop.col + 1 - !mincl;
- X if ((y_current->y_array[0] = strnsave(ml_get(lnum) + curbuf->b_startop.col, (int)j)) == NULL)
- X {
- X fail:
- X free_yank(i); /* free the lines that we allocated */
- X y_current = curr;
- X return FAIL;
- X }
- X goto success;
- X }
- X if ((y_current->y_array[0] = strsave(ml_get(lnum++) + curbuf->b_startop.col)) == NULL)
- X goto fail;
- X ++i;
- X }
- X
- X while (yanktype == MLINE ? (lnum <= yankendlnum) : (lnum < yankendlnum))
- X {
- X if ((y_current->y_array[i] = strsave(ml_get(lnum++))) == NULL)
- X goto fail;
- X ++i;
- X }
- X if (yanktype != MLINE)
- X {
- X if ((y_current->y_array[i] = strnsave(ml_get(yankendlnum), curbuf->b_endop.col + 1 - !mincl)) == NULL)
- X goto fail;
- X }
- X }
- X
- Xsuccess:
- X if (curr != y_current) /* append the new block to the old block */
- X {
- X new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) * (curr->y_size + y_current->y_size)), TRUE);
- X if (new_ptr == NULL)
- X goto fail;
- X for (j = 0; j < curr->y_size; ++j)
- X new_ptr[j] = curr->y_array[j];
- X free(curr->y_array);
- X curr->y_array = new_ptr;
- X
- X if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */
- X curr->y_type = MLINE;
- X if (curr->y_type == MCHAR) /* concatenate the last line of the old
- X block with the first line of the new block */
- X {
- X pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1]) + STRLEN(y_current->y_array[0]) + 1), TRUE);
- X if (pnew == NULL)
- X {
- X i = y_current->y_size - 1;
- X goto fail;
- X }
- X STRCPY(pnew, curr->y_array[--j]);
- X STRCAT(pnew, y_current->y_array[0]);
- X free(curr->y_array[j]);
- X free(y_current->y_array[0]);
- X curr->y_array[j++] = pnew;
- X i = 1;
- X }
- X else
- X i = 0;
- X while (i < y_current->y_size)
- X curr->y_array[j++] = y_current->y_array[i++];
- X curr->y_size = j;
- X free(y_current->y_array);
- X y_current = curr;
- X }
- X if (operator == YANK) /* don't do this when deleting */
- X {
- X if (yanktype == MCHAR && !Visual_block)
- X --yanklines;
- X if (yanklines > p_report)
- X {
- X cursupdate(); /* redisplay now, so message is not deleted */
- X smsg((char_u *)"%ld line%s yanked", yanklines, plural(yanklines));
- X }
- X }
- X
- X return OK;
- X}
- X
- X/*
- X * put contents of register into the text
- X */
- X void
- Xdoput(dir, count, fix_indent)
- X int dir; /* BACKWARD for 'P', FORWARD for 'p' */
- X long count;
- X int fix_indent; /* make indent look nice */
- X{
- X char_u *ptr;
- X char_u *new, *old;
- X int yanklen;
- X int oldlen;
- X int totlen = 0; /* init for gcc */
- X linenr_t lnum;
- X int col;
- X long i; /* index in y_array[] */
- X int y_type;
- X long y_size;
- X char_u **y_array;
- X long nlines = 0;
- X int vcol;
- X int delchar;
- X int incr = 0;
- X long j;
- X FPOS new_cursor;
- X int commandchar;
- X char_u temp[2];
- X int indent;
- X int orig_indent = 0; /* init for gcc */
- X int indent_diff = 0; /* init for gcc */
- X int first_indent = TRUE;
- X
- X if (fix_indent)
- X orig_indent = get_indent();
- X
- X curbuf->b_startop = curwin->w_cursor; /* default for "'[" command */
- X if (dir == FORWARD)
- X curbuf->b_startop.col++;
- X curbuf->b_endop = curwin->w_cursor; /* default for "']" command */
- X commandchar = (dir == FORWARD ? (count == -1 ? 'o' : 'a') : (count == -1 ? 'O' : 'i'));
- X if (yankbuffer == '.') /* use inserted text */
- X {
- X stuff_inserted(commandchar, count, FALSE);
- X return;
- X }
- X else if (yankbuffer == '%') /* use file name */
- X {
- X if (check_fname() == OK)
- X {
- X stuffcharReadbuff(commandchar);
- X stuffReadbuff(curbuf->b_xfilename);
- X stuffcharReadbuff(ESC);
- X }
- X return;
- X }
- X else if (yankbuffer == ':') /* use last command line */
- X {
- X if (last_cmdline == NULL)
- X EMSG(e_nolastcmd);
- X else
- X {
- X stuffcharReadbuff(commandchar);
- X stuffReadbuff(last_cmdline);
- X stuffcharReadbuff(ESC);
- X }
- X return;
- X }
- X
- X get_yank_buffer(FALSE);
- X
- X y_type = y_current->y_type;
- X y_size = y_current->y_size;
- X y_array = y_current->y_array;
- X
- X if (count == -1) /* :put command */
- X {
- X y_type = MLINE;
- X count = 1;
- X }
- X
- X if (y_size == 0 || y_array == NULL)
- X {
- X temp[0] = yankbuffer;
- X temp[1] = NUL;
- X EMSG2("Nothing in register %s", temp);
- X return;
- X }
- X
- X if (y_type == MBLOCK)
- X {
- X lnum = curwin->w_cursor.lnum + y_size + 1;
- X if (lnum > curbuf->b_ml.ml_line_count)
- X lnum = curbuf->b_ml.ml_line_count + 1;
- X if (!u_save(curwin->w_cursor.lnum - 1, lnum))
- X return;
- X }
- X else if (!u_save_cursor())
- X return;
- X
- X yanklen = STRLEN(y_array[0]);
- X CHANGED;
- X
- X lnum = curwin->w_cursor.lnum;
- X col = curwin->w_cursor.col;
- X
- X/*
- X * block mode
- X */
- X if (y_type == MBLOCK)
- X {
- X if (dir == FORWARD && gchar_cursor() != NUL)
- X {
- X col = getvcol(curwin, &curwin->w_cursor, 3) + 1;
- X ++curwin->w_cursor.col;
- X }
- X else
- X col = getvcol(curwin, &curwin->w_cursor, 2);
- X for (i = 0; i < y_size; ++i)
- X {
- X startspaces = 0;
- X endspaces = 0;
- X textcol = 0;
- X vcol = 0;
- X delchar = 0;
- X
- X /* add a new line */
- X if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
- X {
- X ml_append(curbuf->b_ml.ml_line_count, (char_u *)"", (colnr_t)1, FALSE);
- X ++nlines;
- X }
- X old = ml_get(curwin->w_cursor.lnum);
- X oldlen = STRLEN(old);
- X for (ptr = old; vcol < col && *ptr; ++ptr)
- X {
- X /* Count a tab for what it's worth (if list mode not on) */
- X incr = chartabsize(*ptr, (long)vcol);
- X vcol += incr;
- X ++textcol;
- X }
- X if (vcol < col) /* line too short, padd with spaces */
- X {
- X startspaces = col - vcol;
- X }
- X else if (vcol > col)
- X {
- X endspaces = vcol - col;
- X startspaces = incr - endspaces;
- X --textcol;
- X delchar = 1;
- X }
- X yanklen = STRLEN(y_array[i]);
- X totlen = count * yanklen + startspaces + endspaces;
- X new = alloc((unsigned)totlen + oldlen + 1);
- X if (new == NULL)
- X break;
- X /* copy part up to cursor to new line */
- X ptr = new;
- X memmove((char *)ptr, (char *)old, (size_t)textcol);
- X ptr += textcol;
- X /* may insert some spaces before the new text */
- X copy_spaces(ptr, (size_t)startspaces);
- X ptr += startspaces;
- X /* insert the new text */
- X for (j = 0; j < count; ++j)
- X {
- X STRNCPY(ptr, y_array[i], (size_t)yanklen);
- X ptr += yanklen;
- X }
- X /* may insert some spaces after the new text */
- X copy_spaces(ptr, (size_t)endspaces);
- X ptr += endspaces;
- X /* move the text after the cursor to the end of the line. */
- X memmove((char *)ptr, (char *)old + textcol + delchar,
- X (size_t)(oldlen - textcol - delchar + 1));
- X ml_replace(curwin->w_cursor.lnum, new, FALSE);
- X
- X ++curwin->w_cursor.lnum;
- X if (i == 0)
- X curwin->w_cursor.col += startspaces;
- X }
- X curbuf->b_endop.lnum = curwin->w_cursor.lnum - 1; /* for "']" command */
- X curbuf->b_endop.col = textcol + totlen - 1;
- X curwin->w_cursor.lnum = lnum;
- X cursupdate();
- X updateScreen(VALID_TO_CURSCHAR);
- X }
- X else /* not block mode */
- X {
- X if (y_type == MCHAR)
- X {
- X /* if type is MCHAR, FORWARD is the same as BACKWARD on the next character */
- X if (dir == FORWARD && gchar_cursor() != NUL)
- X {
- X ++col;
- X if (yanklen)
- X {
- X ++curwin->w_cursor.col;
- X ++curbuf->b_endop.col;
- X }
- X }
- X new_cursor = curwin->w_cursor;
- X }
- X else if (dir == BACKWARD)
- X /* if type is MLINE, BACKWARD is the same as FORWARD on the previous line */
- X --lnum;
- X
- X/*
- X * simple case: insert into current line
- X */
- X if (y_type == MCHAR && y_size == 1)
- X {
- X totlen = count * yanklen;
- X if (totlen)
- X {
- X old = ml_get(lnum);
- X new = alloc((unsigned)(STRLEN(old) + totlen + 1));
- X if (new == NULL)
- X return; /* alloc() will give error message */
- X memmove((char *)new, (char *)old, (size_t)col);
- X ptr = new + col;
- X for (i = 0; i < count; ++i)
- X {
- X memmove((char *)ptr, (char *)y_array[0], (size_t)yanklen);
- X ptr += yanklen;
- X }
- X memmove((char *)ptr, (char *)old + col, STRLEN(old + col) + 1);
- X ml_replace(lnum, new, FALSE);
- X curwin->w_cursor.col += (colnr_t)(totlen - 1); /* put cursor on last putted char */
- X }
- X curbuf->b_endop = curwin->w_cursor;
- X updateline();
- X }
- X else
- X {
- X if (y_type == MCHAR)
- X --y_size;
- X while (--count >= 0)
- X {
- X i = 0;
- X if (y_type == MCHAR)
- X {
- X /*
- X * Split the current line in two at the insert position.
- X * First insert y_array[size - 1] in front of second line.
- X * Then append y_array[0] to first line.
- X */
- X ptr = ml_get(lnum) + col;
- X totlen = STRLEN(y_array[y_size]);
- X new = alloc((unsigned)(STRLEN(ptr) + totlen + 1));
- X if (new == NULL)
- X goto error;
- X STRCPY(new, y_array[y_size]);
- X STRCAT(new, ptr);
- X ml_append(lnum, new, (colnr_t)0, FALSE); /* insert second line */
- X free(new);
- X ++nlines;
- X
- X old = ml_get(lnum);
- X new = alloc((unsigned)(col + yanklen + 1));
- X if (new == NULL)
- X goto error;
- X /* copy first part of line */
- X memmove((char *)new, (char *)old, (size_t)col);
- X /* append to first line */
- X memmove((char *)new + col, (char *)y_array[0],
- X (size_t)(yanklen + 1));
- X ml_replace(lnum, new, FALSE);
- X
- X curwin->w_cursor.lnum = lnum;
- X i = 1;
- X }
- X
- X while (i < y_size)
- X {
- X if (ml_append(lnum++, y_array[i++], (colnr_t)0, FALSE) == FAIL)
- X goto error;
- X if (fix_indent)
- X {
- X curwin->w_cursor.lnum = lnum;
- X if (curbuf->b_p_si && *ml_get(lnum) == '#')
- X indent = 0; /* Leave # lines at start */
- X else if (first_indent)
- X {
- X indent_diff = orig_indent - get_indent();
- X indent = orig_indent;
- X first_indent = FALSE;
- X }
- X else if ((indent = get_indent() + indent_diff) < 0)
- X indent = 0;
- X set_indent(indent, TRUE);
- X }
- X ++nlines;
- X }
- X if (y_type == MCHAR)
- X ++lnum; /* lnum is now number of line below inserted lines */
- X }
- X
- X curbuf->b_endop.lnum = lnum; /* for "']" command */
- X if (y_type == MLINE)
- X {
- X curwin->w_cursor.col = 0;
- X curbuf->b_endop.col = 0;
- X if (dir == FORWARD)
- X {
- X updateScreen(NOT_VALID); /* recompute curwin->w_botline */
- X ++curwin->w_cursor.lnum;
- X }
- X /* put cursor on first non-blank in last inserted line */
- X beginline(TRUE);
- X }
- X else /* put cursor on first inserted character */
- X {
- X if (col > 1)
- X curbuf->b_endop.col = col - 1;
- X else
- X curbuf->b_endop.col = 0;
- X curwin->w_cursor = new_cursor;
- X }
- X
- Xerror:
- X if (y_type == MLINE) /* for '[ */
- X {
- X curbuf->b_startop.col = 0;
- X if (dir == FORWARD)
- X curbuf->b_startop.lnum++;
- X }
- X mark_adjust(curbuf->b_startop.lnum + (y_type == MCHAR), MAXLNUM, nlines);
- X updateScreen(CURSUPD);
- X }
- X }
- X
- X msgmore(nlines);
- X curwin->w_set_curswant = TRUE;
- X}
- X
- X/*
- X * display the contents of the yank buffers
- X */
- X void
- Xdodis()
- X{
- X register int i, n;
- X register long j;
- X register char_u *p;
- X register struct yankbuf *yb;
- X
- X gotocmdline(TRUE, NUL);
- X
- X msg_outstr((char_u *)"--- Registers ---");
- X for (i = -1; i < 36; ++i)
- X {
- X if (i == -1)
- X {
- X if (y_previous != NULL)
- X yb = y_previous;
- X else
- X yb = &(y_buf[0]);
- X }
- X else
- X yb = &(y_buf[i]);
- X if (yb->y_array != NULL)
- X {
- X msg_outchar('\n');
- X if (i == -1)
- X msg_outstr((char_u *)"\"\"");
- X else
- X {
- X msg_outchar('"');
- X if (i < 10)
- X msg_outchar(i + '0');
- X else
- X msg_outchar(i + 'a' - 10);
- X }
- X msg_outstr((char_u *)" ");
- X
- X n = (int)Columns - 6;
- X for (j = 0; j < yb->y_size && n > 1; ++j)
- X {
- X if (j)
- X {
- X msg_outstr((char_u *)"^J");
- X n -= 2;
- X }
- X for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
- X msg_outtrans(p, 1);
- X }
- X flushbuf(); /* show one line at a time */
- X }
- X }
- X
- X /*
- X * display last inserted text
- X */
- X if ((p = get_last_insert()) != NULL)
- X {
- X msg_outstr((char_u *)"\n\". ");
- X dis_msg(p, TRUE);
- X }
- X
- X /*
- X * display last command line
- X */
- X if (last_cmdline != NULL)
- X {
- X msg_outstr((char_u *)"\n\": ");
- X dis_msg(last_cmdline, FALSE);
- X }
- X
- X /*
- X * display current file name
- X */
- X if (curbuf->b_xfilename != NULL)
- X {
- X msg_outstr((char_u *)"\n\"% ");
- X dis_msg(curbuf->b_xfilename, FALSE);
- X }
- X
- X msg_end();
- X}
- X
- X/*
- X * display a string for dodis()
- X * truncate at end of screen line
- X */
- X void
- Xdis_msg(p, skip_esc)
- X char_u *p;
- X int skip_esc; /* if TRUE, ignore trailing ESC */
- X{
- X int n;
- X
- X n = (int)Columns - 6;
- X while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
- X (n -= charsize(*p)) >= 0)
- X msg_outtrans(p++, 1);
- X}
- X
- X/*
- X * join 'count' lines (minimal 2), including u_save()
- X */
- X void
- Xdodojoin(count, insert_space, redraw)
- X long count;
- X int insert_space;
- X int redraw;
- X{
- X if (!u_save((linenr_t)(curwin->w_cursor.lnum - 1), (linenr_t)(curwin->w_cursor.lnum + count)))
- X return;
- X
- X while (--count > 0)
- X if (dojoin(insert_space, redraw) == FAIL)
- X {
- X beep();
- X break;
- X }
- X
- X if (redraw)
- X updateScreen(VALID_TO_CURSCHAR);
- X}
- X
- X/*
- X * join two lines at the cursor position
- X *
- X * return FAIL for failure, OK ohterwise
- X */
- X int
- Xdojoin(insert_space, redraw)
- X int insert_space;
- X int redraw;
- X{
- X char_u *curr;
- X char_u *next;
- X char_u *new;
- X int endcurr1, endcurr2;
- X int currsize; /* size of the current line */
- X int nextsize; /* size of the next line */
- X int spaces; /* number of spaces to insert */
- X int rows_to_del; /* number of rows on screen to delete */
- X linenr_t t;
- X
- X if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) /* on last line */
- X return FAIL;
- X
- X rows_to_del = plines_m(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1);
- X
- X curr = ml_get(curwin->w_cursor.lnum);
- X currsize = STRLEN(curr);
- X endcurr1 = endcurr2 = NUL;
- X if (currsize > 0)
- X {
- X endcurr1 = *(curr + currsize - 1);
- X if (currsize > 1)
- X endcurr2 = *(curr + currsize - 2);
- X }
- X
- X next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
- X spaces = 0;
- X if (insert_space)
- X {
- X skipspace(&next);
- X spaces = 1;
- X if (*next == ')' || currsize == 0)
- X spaces = 0;
- X else
- X {
- X if (endcurr1 == ' ' || endcurr1 == TAB)
- X {
- X spaces = 0;
- X if (currsize > 1)
- X endcurr1 = endcurr2;
- X }
- X if (p_js && strchr(".!?", endcurr1) != NULL)
- X spaces = 2;
- X }
- X }
- X nextsize = STRLEN(next);
- X
- X new = alloc((unsigned)(currsize + nextsize + spaces + 1));
- X if (new == NULL)
- X return FAIL;
- X
- X /*
- X * Insert the next line first, because we already have that pointer.
- X * Curr has to be obtained again, because getting next will have
- X * invalidated it.
- X */
- X memmove((char *)new + currsize + spaces, (char *)next, (size_t)(nextsize + 1));
- X
- X curr = ml_get(curwin->w_cursor.lnum);
- X memmove((char *)new, (char *)curr, (size_t)currsize);
- X
- X copy_spaces(new + currsize, (size_t)spaces);
- X
- X ml_replace(curwin->w_cursor.lnum, new, FALSE);
- X
- X /*
- X * Delete the following line. To do this we move the cursor there
- X * briefly, and then move it back. After dellines() the cursor may
- X * have moved up (last line deleted), so the current lnum is kept in t.
- X */
- X t = curwin->w_cursor.lnum;
- X ++curwin->w_cursor.lnum;
- X dellines(1L, FALSE, FALSE);
- X curwin->w_cursor.lnum = t;
- X
- X /*
- X * the number of rows on the screen is reduced by the difference
- X * in number of rows of the two old lines and the one new line
- X */
- X if (redraw)
- X {
- X rows_to_del -= plines(curwin->w_cursor.lnum);
- X if (rows_to_del > 0)
- X win_del_lines(curwin, curwin->w_row, rows_to_del, TRUE, TRUE);
- X }
- X
- X /*
- X * go to first character of the joined line
- X */
- X if (currsize == 0)
- X curwin->w_cursor.col = 0;
- X else
- X {
- X curwin->w_cursor.col = currsize - 1;
- X (void)oneright();
- X }
- X CHANGED;
- X
- X return OK;
- X}
- X
- X/*
- X * implementation of the format operator 'Q'
- X */
- X void
- Xdoformat()
- X{
- X /* prepare undo and join the lines */
- X dodojoin((long)nlines, TRUE, FALSE);
- X
- X /* put cursor on last non-space */
- X coladvance(MAXCOL);
- X while (curwin->w_cursor.col && isspace(gchar_cursor()))
- X dec_cursor();
- X curs_columns(FALSE); /* update curwin->w_virtcol */
- X
- X /* do the formatting */
- X State = INSERT; /* for Opencmd() */
- X insertchar(NUL);
- X State = NORMAL;
- X updateScreen(NOT_VALID);
- X}
- X
- X void
- Xstartinsert(initstr, startln, count)
- X int initstr;
- X int startln; /* if set, insert at start of line */
- X long count;
- X{
- X Insstart = curwin->w_cursor;
- X if (startln)
- X Insstart.col = 0;
- X
- X if (initstr != NUL)
- X {
- X ResetRedobuff();
- X AppendNumberToRedobuff(count);
- X AppendCharToRedobuff(initstr);
- X }
- X
- X if (initstr == 'R')
- X State = REPLACE;
- X else
- X State = INSERT;
- X
- X if (p_smd)
- X showmode();
- X
- X change_warning(); /* give a warning if readonly */
- X edit(count);
- X}
- X
- X/*
- X * prepare a few things for block mode yank/delete/tilde
- X *
- X * for delete:
- X * - textlen includes the first/last char to be (partly) deleted
- X * - start/endspaces is the number of columns that are taken by the
- X * first/last deleted char minus the number of columns that have to be deleted.
- X * for yank and tilde:
- X * - textlen includes the first/last char to be wholly yanked
- X * - start/endspaces is the number of columns of the first/last yanked char
- X * that are to be yanked.
- X */
- X static void
- Xblock_prep(lnum, delete)
- X linenr_t lnum;
- X int delete;
- X{
- X int vcol;
- X int incr = 0;
- X char_u *pend;
- X
- X startspaces = 0;
- X endspaces = 0;
- X textlen = 0;
- X textcol = 0;
- X vcol = 0;
- X textstart = ml_get(lnum);
- X while (vcol < startvcol && *textstart)
- X {
- X /* Count a tab for what it's worth (if list mode not on) */
- X incr = chartabsize(*textstart, (long)vcol);
- X vcol += incr;
- X ++textstart;
- X ++textcol;
- X }
- X if (vcol < startvcol) /* line too short */
- X {
- X if (!delete)
- X endspaces = endvcol - startvcol + 1;
- X }
- X else /* vcol >= startvcol */
- X {
- X startspaces = vcol - startvcol;
- X if (delete && vcol > startvcol)
- X startspaces = incr - startspaces;
- X pend = textstart;
- X if (vcol > endvcol) /* it's all in one character */
- X {
- X startspaces = endvcol - startvcol + 1;
- X if (delete)
- X startspaces = incr - startspaces;
- X }
- X else
- X {
- X while (vcol <= endvcol && *pend)
- X {
- X /* Count a tab for what it's worth (if list mode not on) */
- X incr = chartabsize(*pend, (long)vcol);
- X vcol += incr;
- X ++pend;
- X }
- X if (vcol < endvcol && !delete) /* line too short */
- X {
- X endspaces = endvcol - vcol;
- X }
- X else if (vcol > endvcol)
- X {
- X endspaces = vcol - endvcol - 1;
- X if (!delete && pend != textstart && endspaces)
- X --pend;
- X }
- X }
- X if (delete && startspaces)
- X {
- X --textstart;
- X --textcol;
- X }
- X textlen = (int)(pend - textstart);
- X }
- X}
- X
- X#define NUMBUFLEN 30
- X
- X/*
- X * add or subtract 'Prenum1' from a number in a line
- X * 'command' is CTRL-A for add, CTRL-X for subtract
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xdoaddsub(command, Prenum1)
- X int command;
- X linenr_t Prenum1;
- X{
- X register int col;
- X char_u buf[NUMBUFLEN];
- X int hex; /* 'x' or 'X': hexadecimal; '0': octal */
- X static int hexupper = FALSE; /* 0xABC */
- X long n;
- X char_u *ptr;
- X int i;
- X int c;
- X
- X ptr = ml_get(curwin->w_cursor.lnum);
- X col = curwin->w_cursor.col;
- X
- X /* first check if we are on a hexadecimal number */
- X while (col > 0 && isxdigit(ptr[col]))
- X --col;
- X if (col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') &&
- X ptr[col - 1] == '0' && isxdigit(ptr[col + 1]))
- X --col; /* found hexadecimal number */
- X else
- X {
- X /* first search forward and then backward for start of number */
- X col = curwin->w_cursor.col;
- X
- X while (ptr[col] != NUL && !isdigit(ptr[col]))
- X ++col;
- X
- X while (col > 0 && isdigit(ptr[col - 1]))
- X --col;
- X }
- X
- X if (isdigit(ptr[col]) && u_save_cursor())
- X {
- X ptr = ml_get(curwin->w_cursor.lnum); /* get it again, because of undo */
- X curwin->w_set_curswant = TRUE;
- X
- X hex = 0; /* default is decimal */
- X if (ptr[col] == '0') /* could be hex or octal */
- X {
- X hex = TO_UPPER(ptr[col + 1]); /* assume hexadecimal */
- X if (hex != 'X' || !isxdigit(ptr[col + 2]))
- X {
- X if (isdigit(hex))
- X hex = '0'; /* octal */
- X else
- X hex = 0; /* 0 by itself is decimal */
- X }
- X }
- X
- X if (!hex && col > 0 && ptr[col - 1] == '-')
- X --col;
- X
- X ptr += col;
- X /*
- X * we copy the number into a buffer because some versions of sscanf
- X * cannot handle characters with the upper bit set, making some special
- X * characters handled like digits.
- X */
- X for (i = 0; *ptr && !(*ptr & 0x80) && i < NUMBUFLEN - 1; ++i)
- X buf[i] = *ptr++;
- X buf[i] = NUL;
- X
- X if (hex == '0')
- X sscanf((char *)buf, "%lo", &n);
- X else if (hex)
- X sscanf((char *)buf + 2, "%lx", &n); /* "%X" doesn't work! */
- X else
- X n = atol((char *)buf);
- X
- X if (command == Ctrl('A'))
- X n += Prenum1;
- X else
- X n -= Prenum1;
- X
- X if (hex == 'X') /* skip the '0x' */
- X col += 2;
- X curwin->w_cursor.col = col;
- X c = gchar_cursor();
- X do /* delete the old number */
- X {
- X if (isalpha(c))
- X {
- X if (isupper(c))
- X hexupper = TRUE;
- X else
- X hexupper = FALSE;
- X }
- X (void)delchar(FALSE);
- X c = gchar_cursor();
- X }
- X while (hex ? (hex == '0' ? c >= '0' && c <= '7' : isxdigit(c)) : isdigit(c));
- X
- X if (hex == '0')
- X sprintf((char *)buf, "0%lo", n);
- X else if (hex && hexupper)
- X sprintf((char *)buf, "%lX", n);
- X else if (hex)
- X sprintf((char *)buf, "%lx", n);
- X else
- X sprintf((char *)buf, "%ld", n);
- X insstr(buf); /* insert the new number */
- X --curwin->w_cursor.col;
- X updateline();
- X return OK;
- X }
- X else
- X {
- X beep();
- X return FAIL;
- X }
- X}
- END_OF_FILE
- if test 39495 -ne `wc -c <'vim/src/ops.c'`; then
- echo shar: \"'vim/src/ops.c'\" unpacked with wrong size!
- fi
- # end of 'vim/src/ops.c'
- fi
- if test -f 'vim/src/proto/normal.pro' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/src/proto/normal.pro'\"
- else
- echo shar: Extracting \"'vim/src/proto/normal.pro'\" \(44 characters\)
- sed "s/^X//" >'vim/src/proto/normal.pro' <<'END_OF_FILE'
- X/* normal.c */
- Xvoid normal __PARMS((void));
- END_OF_FILE
- if test 44 -ne `wc -c <'vim/src/proto/normal.pro'`; then
- echo shar: \"'vim/src/proto/normal.pro'\" unpacked with wrong size!
- fi
- # end of 'vim/src/proto/normal.pro'
- fi
- if test -f 'vim/src/term.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/src/term.c'\"
- else
- echo shar: Extracting \"'vim/src/term.c'\" \(19580 characters\)
- sed "s/^X//" >'vim/src/term.c' <<'END_OF_FILE'
- X/* vi:ts=4:sw=4
- X *
- X * VIM - Vi IMproved by Bram Moolenaar
- X *
- X * Read the file "credits.txt" for a list of people who contributed.
- X * Read the file "uganda.txt" for copying and usage conditions.
- X */
- X/*
- X *
- X * term.c: functions for controlling the terminal
- X *
- X * primitive termcap support for Amiga and MSDOS included
- X *
- X * NOTE: padding and variable substitution is not performed,
- X * when compiling without TERMCAP, we use tputs() and tgoto() dummies.
- X */
- X
- X#include "vim.h"
- X#include "globals.h"
- X#include "param.h"
- X#include "proto.h"
- X#ifdef TERMCAP
- X# ifdef linux
- X# include <termcap.h>
- X# if 0 /* only required for old versions, it's now in termcap.h */
- X typedef int (*outfuntype) (int);
- X# endif
- X# define TPUTSFUNCAST (outfuntype)
- X# else
- X# define TPUTSFUNCAST
- X# ifdef AMIGA
- X# include "proto/termlib.pro"
- X# endif
- X# endif
- X#endif
- X
- Xstatic void parse_builtin_tcap __ARGS((Tcarr *tc, char_u *s));
- X
- X/*
- X * Builtin_tcaps must always contain DFLT_TCAP as the first entry!
- X * DFLT_TCAP is used, when no terminal is specified with -T option or $TERM.
- X * The entries are compact, therefore they normally are included even when
- X * TERMCAP is defined.
- X * When TERMCAP is defined, the builtin entries can be accessed with
- X * "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
- X */
- Xstatic char_u *builtin_tcaps[] =
- X{
- X#ifndef NO_BUILTIN_TCAPS
- X (char_u *)DFLT_TCAP, /* almost allways included */
- X# if !defined(UNIX) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
- X (char_u *)ANSI_TCAP, /* default for unix */
- X# endif
- X# if !defined(AMIGA) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
- X (char_u *)AMIGA_TCAP, /* default for amiga */
- X# endif
- X# if !defined(MSDOS) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
- X (char_u *)PCTERM_TCAP, /* default for MSdos */
- X# endif
- X# if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS)
- X (char_u *)PCANSI_TCAP,
- X# endif
- X# if !defined(ATARI) && defined(ALL_BUILTIN_TCAPS)
- X (char_u *)ATARI_TCAP, /* default for Atari */
- X# endif
- X# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
- X (char_u *)XTERM_TCAP, /* always included on unix */
- X# endif
- X# ifdef ALL_BUILTIN_TCAPS
- X (char_u *)VT52_TCAP,
- X# endif
- X# if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
- X (char_u *)DEBUG_TCAP, /* always included when debugging */
- X# endif
- X#else /* NO_BUILTIN_TCAPS */
- X (char_u *)DUMB_TCAP, /* minimal termcap, used when everything else fails */
- X#endif /* NO_BUILTIN_TCAPS */
- X NULL,
- X};
- X
- X/*
- X * Term_strings contains currently used terminal strings.
- X * It is initialized with the default values by parse_builtin_tcap().
- X * The values can be changed by setting the parameter with the same name.
- X */
- XTcarr term_strings;
- X
- X/*
- X * Parsing of the builtin termcap entries.
- X * The terminal's name is not set, as this is already done in termcapinit().
- X * Chop builtin termcaps, string entries are already '\0' terminated.
- X * not yet implemented:
- X * boolean entries could be empty strings;
- X * numeric entries would need a flag (e.g. high bit of the skip byte),
- X * so that parse_builtin_tcap can handle them.
- X */
- X static void
- Xparse_builtin_tcap(tc, s)
- X Tcarr *tc;
- X char_u *s;
- X{
- X char_u **p = &tc->t_name;
- X
- X p++;
- X for (;;)
- X {
- X while (*s++)
- X ;
- X p += *s++;
- X if (!*s)
- X return;
- X *p++ = s;
- X }
- X}
- X
- X#ifdef TERMCAP
- X# ifndef linux /* included in <termlib.h> */
- X# ifndef AMIGA /* included in proto/termlib.pro */
- Xint tgetent();
- Xint tgetnum();
- Xchar *tgetstr();
- Xint tgetflag();
- Xint tputs();
- X# endif /* AMIGA */
- X# ifndef hpux
- Xextern short ospeed;
- X# endif
- X# endif /* linux */
- X# ifndef hpux
- Xchar *UP, *BC, PC; /* should be extern, but some don't have them */
- X# endif
- X#endif /* TERMCAP */
- X
- X#ifdef linux
- X# define TGETSTR(s, p) (char_u *)tgetstr((s), (char **)(p))
- X#else
- X# define TGETSTR(s, p) (char_u *)tgetstr((s), (char *)(p))
- X#endif
- X
- X void
- Xset_term(term)
- X char_u *term;
- X{
- X char_u **p = builtin_tcaps;
- X#ifdef TERMCAP
- X int builtin = 0;
- X#endif
- X int width = 0, height = 0;
- X
- X if (!STRNCMP(term, "builtin_", (size_t)8))
- X {
- X term += 8;
- X#ifdef TERMCAP
- X builtin = 1;
- X#endif
- X }
- X#ifdef TERMCAP
- X else
- X {
- X char_u *p;
- X static char_u tstrbuf[TBUFSZ];
- X char_u tbuf[TBUFSZ];
- X char_u *tp = tstrbuf;
- X int i;
- X
- X i = tgetent(tbuf, term);
- X if (i == -1)
- X {
- X EMSG("Cannot open termcap file");
- X builtin = 1;
- X }
- X else if (i == 0)
- X {
- X EMSG("terminal entry not found");
- X builtin = 1;
- X }
- X else
- X {
- X clear_termparam(); /* clear old parameters */
- X /* output strings */
- X T_EL = TGETSTR("ce", &tp);
- X T_IL = TGETSTR("al", &tp);
- X T_CIL = TGETSTR("AL", &tp);
- X T_DL = TGETSTR("dl", &tp);
- X T_CDL = TGETSTR("DL", &tp);
- X T_CS = TGETSTR("cs", &tp);
- X T_ED = TGETSTR("cl", &tp);
- X T_CI = TGETSTR("vi", &tp);
- X T_CV = TGETSTR("ve", &tp);
- X T_CVV = TGETSTR("vs", &tp);
- X T_TP = TGETSTR("me", &tp);
- X T_TI = TGETSTR("mr", &tp);
- X T_TB = TGETSTR("md", &tp);
- X T_SE = TGETSTR("se", &tp);
- X T_SO = TGETSTR("so", &tp);
- X T_CM = TGETSTR("cm", &tp);
- X T_SR = TGETSTR("sr", &tp);
- X T_CRI = TGETSTR("RI", &tp);
- X T_VB = TGETSTR("vb", &tp);
- X T_KS = TGETSTR("ks", &tp);
- X T_KE = TGETSTR("ke", &tp);
- X T_TS = TGETSTR("ti", &tp);
- X T_TE = TGETSTR("te", &tp);
- X
- X /* key codes */
- X term_strings.t_ku = TGETSTR("ku", &tp);
- X term_strings.t_kd = TGETSTR("kd", &tp);
- X term_strings.t_kl = TGETSTR("kl", &tp);
- X /* if cursor-left == backspace, ignore it (televideo 925) */
- X if (term_strings.t_kl != NULL && *term_strings.t_kl == Ctrl('H'))
- X term_strings.t_kl = NULL;
- X term_strings.t_kr = TGETSTR("kr", &tp);
- X /* term_strings.t_sku = TGETSTR("", &tp); termcap code unknown */
- X /* term_strings.t_skd = TGETSTR("", &tp); termcap code unknown */
- X#ifdef ARCHIE
- X /* Termcap code made up! */
- X term_strings.t_sku = tgetstr("su", &tp);
- X term_strings.t_skd = tgetstr("sd", &tp);
- X#else
- X term_strings.t_sku = NULL;
- X term_strings.t_skd = NULL;
- X#endif
- X term_strings.t_skl = TGETSTR("#4", &tp);
- X term_strings.t_skr = TGETSTR("%i", &tp);
- X term_strings.t_f1 = TGETSTR("k1", &tp);
- X term_strings.t_f2 = TGETSTR("k2", &tp);
- X term_strings.t_f3 = TGETSTR("k3", &tp);
- X term_strings.t_f4 = TGETSTR("k4", &tp);
- X term_strings.t_f5 = TGETSTR("k5", &tp);
- X term_strings.t_f6 = TGETSTR("k6", &tp);
- X term_strings.t_f7 = TGETSTR("k7", &tp);
- X term_strings.t_f8 = TGETSTR("k8", &tp);
- X term_strings.t_f9 = TGETSTR("k9", &tp);
- X term_strings.t_f10 = TGETSTR("k;", &tp);
- X term_strings.t_sf1 = TGETSTR("F1", &tp); /* really function keys 11-20 */
- X term_strings.t_sf2 = TGETSTR("F2", &tp);
- X term_strings.t_sf3 = TGETSTR("F3", &tp);
- X term_strings.t_sf4 = TGETSTR("F4", &tp);
- X term_strings.t_sf5 = TGETSTR("F5", &tp);
- X term_strings.t_sf6 = TGETSTR("F6", &tp);
- X term_strings.t_sf7 = TGETSTR("F7", &tp);
- X term_strings.t_sf8 = TGETSTR("F8", &tp);
- X term_strings.t_sf9 = TGETSTR("F9", &tp);
- X term_strings.t_sf10 = TGETSTR("FA", &tp);
- X term_strings.t_help = TGETSTR("%1", &tp);
- X term_strings.t_undo = TGETSTR("&8", &tp);
- X
- X height = tgetnum("li");
- X width = tgetnum("co");
- X
- X T_MS = tgetflag("ms") ? (char_u *)"yes" : (char_u *)NULL;
- X
- X# ifndef hpux
- X BC = (char *)TGETSTR("bc", &tp);
- X UP = (char *)TGETSTR("up", &tp);
- X p = TGETSTR("pc", &tp);
- X if (p)
- X PC = *p;
- X ospeed = 0;
- X# endif
- X }
- X }
- X if (builtin)
- X#endif
- X {
- X while (*p && STRCMP(term, *p))
- X p++;
- X if (!*p)
- X {
- X fprintf(stderr, "'%s' not builtin. Available terminals are:\r\n", term);
- X for (p = builtin_tcaps; *p; p++)
- X#ifdef TERMCAP
- X fprintf(stderr, "\tbuiltin_%s\r\n", *p);
- X#else
- X fprintf(stderr, "\t%s\r\n", *p);
- X#endif
- X if (!starting) /* when user typed :set term=xxx, quit here */
- X {
- X wait_return(TRUE);
- X return;
- X }
- X sleep(2);
- X fprintf(stderr, "defaulting to '%s'\r\n", *builtin_tcaps);
- X sleep(2);
- X p = builtin_tcaps;
- X free(term_strings.t_name);
- X term_strings.t_name = strsave(term = *p);
- X }
- X clear_termparam(); /* clear old parameters */
- X parse_builtin_tcap(&term_strings, *p);
- X }
- X/*
- X * special: There is no info in the termcap about whether the cursor positioning
- X * is relative to the start of the screen or to the start of the scrolling region.
- X * We just guess here. Only msdos pcterm is known to do it relative.
- X */
- X if (STRCMP(term, "pcterm") == 0)
- X T_CSC = (char_u *)"yes";
- X else
- X T_CSC = NULL;
- X
- X#if defined(AMIGA) || defined(MSDOS)
- X /* DFLT_TCAP indicates that it is the machine console. */
- X if (STRCMP(term, *builtin_tcaps))
- X term_console = FALSE;
- X else
- X {
- X term_console = TRUE;
- X# ifdef AMIGA
- X win_resize_on(); /* enable window resizing reports */
- X# endif
- X }
- X#endif
- X ttest(TRUE);
- X /* display initial screen after ttest() checking. jw. */
- X if (width <= 0 || height <= 0)
- X {
- X /* termcap failed to report size */
- X /* set defaults, in case mch_get_winsize also fails */
- X width = 80;
- X#ifdef MSDOS
- X height = 25; /* console is often 25 lines */
- X#else
- X height = 24; /* most terminals are 24 lines */
- X#endif
- X }
- X set_winsize(width, height, FALSE); /* may change Rows */
- X}
- X
- X#if defined(TERMCAP) && defined(UNIX)
- X/*
- X * Get Columns and Rows from the termcap. Used after a window signal if the
- X * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
- X * and "li" entries never change. But this may happen on some systems.
- X */
- X void
- Xgetlinecol()
- X{
- X char_u tbuf[TBUFSZ];
- X
- X if (term_strings.t_name != NULL && tgetent(tbuf, term_strings.t_name) > 0)
- X {
- X if (Columns == 0)
- X Columns = tgetnum("co");
- X if (Rows == 0)
- X Rows = tgetnum("li");
- X }
- X}
- X#endif
- X
- Xstatic char_u *tltoa __PARMS((unsigned long));
- X
- X static char_u *
- Xtltoa(i)
- X unsigned long i;
- X{
- X static char_u buf[16];
- X char_u *p;
- X
- X p = buf + 15;
- X *p = '\0';
- X do
- X {
- X --p;
- X *p = i % 10 + '0';
- X i /= 10;
- X }
- X while (i > 0 && p > buf);
- X return p;
- X}
- X
- X#ifndef TERMCAP
- X
- X/*
- X * minimal tgoto() implementation.
- X * no padding and we only parse for %i %d and %+char
- X */
- X
- X char *
- Xtgoto(cm, x, y)
- X char *cm;
- X int x, y;
- X{
- X static char buf[30];
- X char *p, *s, *e;
- X
- X if (!cm)
- X return "OOPS";
- X e = buf + 29;
- X for (s = buf; s < e && *cm; cm++)
- X {
- X if (*cm != '%')
- X {
- X *s++ = *cm;
- X continue;
- X }
- X switch (*++cm)
- X {
- X case 'd':
- X p = (char *)tltoa((unsigned long)y);
- X y = x;
- X while (*p)
- X *s++ = *p++;
- X break;
- X case 'i':
- X x++;
- X y++;
- X break;
- X case '+':
- X *s++ = (char)(*++cm + y);
- X y = x;
- X break;
- X case '%':
- X *s++ = *cm;
- X break;
- X default:
- X return "OOPS";
- X }
- X }
- X *s = '\0';
- X return buf;
- X}
- X
- X#endif /* TERMCAP */
- X
- X/*
- X * Termcapinit is called from main() to initialize the terminal.
- X * The optional argument is given with the -T command line option.
- X */
- X void
- Xtermcapinit(term)
- X char_u *term;
- X{
- X if (!term)
- X term = vimgetenv((char_u *)"TERM");
- X if (!term || !*term)
- X term = *builtin_tcaps;
- X term_strings.t_name = strsave(term);
- X set_term(term);
- X}
- X
- X/*
- X * the number of calls to mch_write is reduced by using the buffer "outbuf"
- X */
- X#undef BSIZE /* hpux has BSIZE in sys/param.h */
- X#define BSIZE 2048
- Xstatic char_u outbuf[BSIZE];
- Xstatic int bpos = 0; /* number of chars in outbuf */
- X
- X/*
- X * flushbuf(): flush the output buffer
- X */
- X void
- Xflushbuf()
- X{
- X if (bpos != 0)
- X {
- X mch_write(outbuf, bpos);
- X bpos = 0;
- X }
- X}
- X
- X/*
- X * outchar(c): put a character into the output buffer.
- X * Flush it if it becomes full.
- X */
- X void
- Xoutchar(c)
- X unsigned c;
- X{
- X#ifdef UNIX
- X if (c == '\n') /* turn LF into CR-LF (CRMOD does not seem to do this) */
- X outchar('\r');
- X#endif
- X
- X outbuf[bpos] = c;
- X
- X if (p_nb) /* for testing: unbuffered screen output (not for MSDOS) */
- X mch_write(outbuf, 1);
- X else
- X ++bpos;
- X
- X if (bpos >= BSIZE)
- X flushbuf();
- X}
- X
- X/*
- X * a never-padding outstr.
- X * use this whenever you don't want to run the string through tputs.
- X * tputs above is harmless, but tputs from the termcap library
- X * is likely to strip off leading digits, that it mistakes for padding
- X * information. (jw)
- X */
- X void
- Xoutstrn(s)
- X char_u *s;
- X{
- X if (bpos > BSIZE - 20) /* avoid terminal strings being split up */
- X flushbuf();
- X while (*s)
- X outchar(*s++);
- X}
- X
- X/*
- X * outstr(s): put a string character at a time into the output buffer.
- X * If TERMCAP is defined use the termcap parser. (jw)
- X */
- X void
- Xoutstr(s)
- X register char_u *s;
- X{
- X if (bpos > BSIZE - 20) /* avoid terminal strings being split up */
- X flushbuf();
- X if (s)
- X#ifdef TERMCAP
- X tputs(s, 1, TPUTSFUNCAST outchar);
- X#else
- X while (*s)
- X outchar(*s++);
- X#endif
- X}
- X
- X/*
- X * cursor positioning using termcap parser. (jw)
- X */
- X void
- Xwindgoto(row, col)
- X int row;
- X int col;
- X{
- X OUTSTR(tgoto((char *)T_CM, col, row));
- X}
- X
- X/*
- X * Set cursor to current position.
- X * Should be optimized for minimal terminal output.
- X */
- X
- X void
- Xsetcursor()
- X{
- X if (!RedrawingDisabled)
- X windgoto(curwin->w_winpos + curwin->w_row, curwin->w_col);
- X}
- X
- X void
- Xttest(pairs)
- X int pairs;
- X{
- X char buf[70];
- X char *s = "terminal capability %s required.\n";
- X char *t = NULL;
- X
- X /* hard requirements */
- X if (!T_ED || !*T_ED) /* erase display */
- X t = "cl";
- X if (!T_CM || !*T_CM) /* cursor motion */
- X t = "cm";
- X
- X if (t)
- X {
- X sprintf(buf, s, t);
- X EMSG(buf);
- X }
- X
- X/*
- X * if "cs" defined, use a scroll region, it's faster.
- X */
- X if (T_CS && *T_CS != NUL)
- X scroll_region = TRUE;
- X else
- X scroll_region = FALSE;
- X
- X if (pairs)
- X {
- X /* optional pairs */
- X /* TP goes to normal mode for TI (invert) and TB (bold) */
- X if ((!T_TP || !*T_TP))
- X T_TP = T_TI = T_TB = NULL;
- X if ((!T_SO || !*T_SO) ^ (!T_SE || !*T_SE))
- X T_SO = T_SE = NULL;
- X /* T_CV is needed even though T_CI is not defined */
- X if ((!T_CV || !*T_CV))
- X T_CI = NULL;
- X /* if 'mr' or 'me' is not defined use 'so' and 'se' */
- X if (T_TP == NULL || *T_TP == NUL)
- X {
- X T_TP = T_SE;
- X T_TI = T_SO;
- X T_TB = T_SO;
- X }
- X /* if 'so' or 'se' is not defined use 'mr' and 'me' */
- X if (T_SO == NULL || *T_SO == NUL)
- X {
- X T_SE = T_TP;
- X if (T_TI == NULL)
- X T_SO = T_TB;
- X else
- X T_SO = T_TI;
- X }
- X }
- X}
- X
- X/*
- X * inchar() - get one character from
- X * 1. a scriptfile
- X * 2. the keyboard
- X *
- X * As much characters as we can get (upto 'maxlen') are put in buf and
- X * NUL terminated (buffer length must be 'maxlen' + 1).
- X *
- X * If we got an interrupt all input is read until none is available.
- X *
- X * If time == 0 there is no waiting for the char.
- X * If time == n we wait for n msec for a character to arrive.
- X * If time == -1 we wait forever for a character to arrive.
- X *
- X * Return the number of obtained characters.
- X */
- X
- X int
- Xinchar(buf, maxlen, time)
- X char_u *buf;
- X int maxlen;
- X int time; /* milli seconds */
- X{
- X int len;
- X int retesc = FALSE; /* return ESC with gotint */
- X register int c;
- X register int i;
- X
- X if (time == -1 || time > 100) /* flush output before waiting */
- X {
- X cursor_on();
- X flushbuf();
- X }
- X did_outofmem_msg = FALSE; /* display out of memory message (again) */
- X
- X/*
- X * first try script file
- X * If interrupted: Stop reading script files.
- X */
- Xretry:
- X if (scriptin[curscript] != NULL)
- X {
- X if (got_int || (c = getc(scriptin[curscript])) < 0) /* reached EOF */
- X {
- X /* when reading script file is interrupted, return an ESC to
- X get back to normal mode */
- X if (got_int)
- X retesc = TRUE;
- X fclose(scriptin[curscript]);
- X scriptin[curscript] = NULL;
- X if (curscript > 0)
- X --curscript;
- X goto retry; /* may read other script if this one was nested */
- X }
- X if (c == 0)
- X c = K_ZERO; /* replace ^@ with special code */
- X *buf++ = c;
- X *buf = NUL;
- X return 1;
- X }
- X
- X/*
- X * If we got an interrupt, skip all previously typed characters and
- X * return TRUE if quit reading script file.
- X */
- X if (got_int) /* skip typed characters */
- X {
- X while (GetChars(buf, maxlen, T_PEEK))
- X ;
- X return retesc;
- X }
- X len = GetChars(buf, maxlen, time);
- X
- X for (i = len; --i >= 0; ++buf)
- X if (*buf == 0)
- X *(char_u *)buf = K_ZERO; /* replace ^@ with special code */
- X *buf = NUL; /* add trailing NUL */
- X return len;
- X}
- X
- X/*
- X * Check if buf[] begins with a terminal key code.
- X * Return 0 for no match, -1 for partial match, > 0 for full match.
- X * With a match the replacement code is put in buf[0], the match is
- X * removed and the number characters in buf is returned.
- X *
- X * Note: should always be called with buf == typestr!
- X */
- X int
- Xcheck_termcode(buf)
- X char_u *buf;
- X{
- X char_u **p;
- X int slen;
- X int len;
- X
- X len = STRLEN(buf);
- X for (p = (char_u **)&term_strings.t_ku; p != (char_u **)&term_strings.t_undo + 1; ++p)
- X {
- X if (*p == NULL || (slen = STRLEN(*p)) == 0) /* empty entry */
- X continue;
- X if (STRNCMP(*p, buf, (size_t)(slen > len ? len : slen)) == 0)
- X {
- X if (len >= slen) /* got the complete sequence */
- X {
- X len -= slen;
- X /* remove matched chars, taking care of noremap */
- X del_typestr(slen - 1);
- X /* this relies on the Key numbers to be consecutive! */
- X buf[0] = K_UARROW + (p - (char_u **)&term_strings.t_ku);
- X return (len + 1);
- X }
- X return -1; /* got a partial sequence */
- X }
- X }
- X return 0; /* no match found */
- X}
- X
- X/*
- X * outnum - output a (big) number fast
- X */
- X void
- Xoutnum(n)
- X register long n;
- X{
- X OUTSTRN(tltoa((unsigned long)n));
- X}
- X
- X void
- Xcheck_winsize()
- X{
- X if (Columns < MIN_COLUMNS)
- X Columns = MIN_COLUMNS;
- X else if (Columns > MAX_COLUMNS)
- X Columns = MAX_COLUMNS;
- X if (Rows < MIN_ROWS + 1) /* need room for one window and command line */
- X Rows = MIN_ROWS + 1;
- X screen_new_rows(); /* may need to update window sizes */
- X}
- X
- X/*
- X * set window size
- X * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
- X * window size (this is used for the :win command).
- X * If 'mustset' is FALSE, we may try to get the real window size and if
- X * it fails use 'width' and 'height'.
- X */
- X void
- Xset_winsize(width, height, mustset)
- X int width, height;
- X int mustset;
- X{
- X register int tmp;
- X
- X if (width < 0 || height < 0) /* just checking... */
- X return;
- X
- X if (State == HITRETURN || State == SETWSIZE) /* postpone the resizing */
- X {
- X State = SETWSIZE;
- X return;
- X }
- X screenclear();
- X#ifdef AMIGA
- X flushbuf(); /* must do this before mch_get_winsize for some obscure reason */
- X#endif /* AMIGA */
- X if (mustset || mch_get_winsize() == FAIL)
- X {
- X Rows = height;
- X Columns = width;
- X check_winsize(); /* always check, to get p_scroll right */
- X mch_set_winsize();
- X }
- X else
- X check_winsize(); /* always check, to get p_scroll right */
- X if (State == HELP)
- X (void)redrawhelp();
- X else if (!starting)
- X {
- X tmp = RedrawingDisabled;
- X RedrawingDisabled = FALSE;
- X comp_Botline_all();
- X updateScreen(CURSUPD);
- X RedrawingDisabled = tmp;
- X if (State == CMDLINE)
- X redrawcmdline();
- X else
- X setcursor();
- X }
- X flushbuf();
- X}
- X
- X void
- Xsettmode(raw)
- X int raw;
- X{
- X static int oldraw = FALSE;
- X
- X if (oldraw == raw) /* skip if already in desired mode */
- X return;
- X oldraw = raw;
- X
- X mch_settmode(raw); /* machine specific function */
- X}
- X
- X void
- Xstarttermcap()
- X{
- X outstr(T_TS); /* start termcap mode */
- X outstr(T_KS); /* start "keypad transmit" mode */
- X flushbuf();
- X termcap_active = TRUE;
- X}
- X
- X void
- Xstoptermcap()
- X{
- X outstr(T_KE); /* stop "keypad transmit" mode */
- X flushbuf();
- X termcap_active = FALSE;
- X cursor_on(); /* just in case it is still off */
- X outstr(T_TE); /* stop termcap mode */
- X}
- X
- X/*
- X * enable cursor, unless in Visual mode or no inversion possible
- X */
- Xstatic int cursor_is_off = FALSE;
- X
- X void
- Xcursor_on()
- X{
- X if (cursor_is_off && (!VIsual.lnum || highlight == NULL))
- X {
- X outstr(T_CV);
- X cursor_is_off = FALSE;
- X }
- X}
- X
- X void
- Xcursor_off()
- X{
- X if (!cursor_is_off)
- X outstr(T_CI); /* disable cursor */
- X cursor_is_off = TRUE;
- X}
- X
- X/*
- X * set scrolling region for window 'wp'
- X */
- X void
- Xscroll_region_set(wp)
- X WIN *wp;
- X{
- X OUTSTR(tgoto((char *)T_CS, wp->w_winpos + wp->w_height - 1, wp->w_winpos));
- X}
- X
- X/*
- X * reset scrolling region to the whole screen
- X */
- X void
- Xscroll_region_reset()
- X{
- X OUTSTR(tgoto((char *)T_CS, (int)Rows - 1, 0));
- X}
- END_OF_FILE
- if test 19580 -ne `wc -c <'vim/src/term.c'`; then
- echo shar: \"'vim/src/term.c'\" unpacked with wrong size!
- fi
- # end of 'vim/src/term.c'
- fi
- echo shar: End of archive 12 \(of 26\).
- cp /dev/null ark12isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 26 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-