home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / vim / part12 < prev    next >
Encoding:
Internet Message Format  |  1994-08-16  |  68.7 KB

  1. From: mool@oce.nl (Bram Moolenaar)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i031:  vim - Vi IMproved editor, v3.0, Part12/26
  4. Date: 16 Aug 1994 21:18:23 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <32rs1f$keu@sparky.sterling.com>
  9. X-Md4-Signature: 6e4b8a9e175c9588805902d12a2cfbec
  10.  
  11. Submitted-by: mool@oce.nl (Bram Moolenaar)
  12. Posting-number: Volume 44, Issue 31
  13. Archive-name: vim/part12
  14. Environment: UNIX, AMIGA, MS-DOS, Windows NT
  15. Supersedes: vim: Volume 41, Issue 50-75
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  vim/doc/vim.1 vim/src/ops.c vim/src/proto/normal.pro
  22. #   vim/src/term.c
  23. # Wrapped by kent@sparky on Mon Aug 15 21:44:05 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 12 (of 26)."'
  27. if test -f 'vim/doc/vim.1' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'vim/doc/vim.1'\"
  29. else
  30.   echo shar: Extracting \"'vim/doc/vim.1'\" \(5252 characters\)
  31.   sed "s/^X//" >'vim/doc/vim.1' <<'END_OF_FILE'
  32. X.TH VIM 1 "1994 August 12"
  33. X.SH NAME
  34. Xvim \- Vi IMproved, a programmers text editor
  35. X.SH SYNOPSIS
  36. X.B vim
  37. X[options] [file ..]
  38. X.br
  39. X.B vim
  40. X[options] \-t tag
  41. X.br
  42. X.B vim
  43. X[options] \-e [errorfile]
  44. X.SH DESCRIPTION
  45. X.B Vim
  46. Xis a text editor that is upwards compatible to vi. It can be used to edit any 
  47. XASCII text. It is especially useful for editing programs.
  48. X.PP
  49. XThere are a lot of enhancements above vi: multi level undo,
  50. Xmulti windows and buffers, command line 
  51. Xediting, filename completion, on-line help, visual selection, etc..
  52. XRead difference.doc 
  53. Xfor a summary of the differences between vi and Vim.
  54. X.PP
  55. XMost often
  56. X.B Vim
  57. Xis started to edit a single file with the command
  58. X.PP
  59. X    vim file
  60. X.PP
  61. XMore generally VIM is started with:
  62. X.PP
  63. X    vim [options] [filelist]
  64. X.PP
  65. XIf the filelist is missing, the editor will start with an empty buffer.
  66. XOtherwise exactly one out of the following three may be used to choose one or
  67. Xmore files to be edited.
  68. X.TP 12
  69. Xfile ..
  70. XA list of file names. The first one (alphabetically) will be
  71. Xthe current file and read into the buffer. The cursor will be
  72. Xpositioned on the first line of the buffer. You can get to the other files
  73. Xwith the ":next" command.
  74. X.TP
  75. X-t {tag}
  76. XThe file to edit and the initial cursor position depends on a "tag", a sort 
  77. Xof goto label. {tag} is looked up in the tags file, the associated file 
  78. Xbecomes the current file and the associated command is executed. Mostly this 
  79. Xis used for C programs. {tag} then should be a function name. The effect is 
  80. Xthat the file containing that function becomes the current file and the 
  81. Xcursor is positioned on the start of the function (see reference.doc, 
  82. Xsection "tag searches").
  83. X.TP
  84. X-e [errorfile]
  85. XStart in quickFix mode. The file [errorfile]
  86. Xis read and the first error is displayed. If [errorfile] is omitted the file
  87. Xname is obtained from the 'errorfile' option (defaults to "AztecC.Err" for
  88. Xthe Amiga, "errors" on other systems). Further errors can be jumped to 
  89. Xwith the ":cn" command. See reference.doc section 5.5.
  90. X.SH OPTIONS
  91. XThe options, if present, must precede the filelist. The options may be given 
  92. Xin any order.
  93. X.TP 12
  94. X-r
  95. XRecovery mode. The swap file is used to recover a crashed editing session. The
  96. Xswap file is a file with the same file name as the text file with ".swp"
  97. Xappended. See reference.doc, chapter "Recovery after a crash".
  98. X.TP
  99. X-v
  100. XView mode. The 'readonly' option will be set. You can still 
  101. Xedit the buffer, but will be prevented from accidently 
  102. Xoverwriting a file. If you do want to overwrite a file, add 
  103. Xan exclamation mark to the Ex command, as in ":w!".
  104. XThe -v option also implies the -n option (see below).
  105. XThe 'readonly' option can be reset with ":set noro" (see reference.doc, 
  106. Xoptions chapter).
  107. X.TP
  108. X-b
  109. XBinary. A few options will be set that makes it possible to edit a binary or
  110. Xexecutable file.
  111. X.TP
  112. X+[num]
  113. XFor the first file the cursor will be positioned on line
  114. X"num". If "num" is missing, the cursor will be positioned on
  115. Xthe last line.
  116. X.TP
  117. X+/pat
  118. XFor the first file the cursor will be positioned on the
  119. Xfirst occurrence of "pat" (see reference.doc, 
  120. Xsection "pattern searches" for the available search 
  121. Xpatterns).
  122. X.TP
  123. X+{command}
  124. X.TP
  125. X-c {command}
  126. X{command} will be executed after the 
  127. Xfirst file has been read. {command} is interpreted as an Ex 
  128. Xcommand. If the {command} contains spaces it must 
  129. Xbe enclosed in double quotes (this depends on the shell that 
  130. Xis used).
  131. XExample: Vim "+set si" main.c
  132. X.TP
  133. X-x
  134. X(Amiga only) Vim is not restarted to open a new window. This option should 
  135. Xbe used when Vim is executed by a program that will wait for the edit 
  136. Xsession to finish (e.g. mail). The ":sh" and ":!" commands will not work.
  137. X.TP
  138. X-o[N]
  139. XOpen N windows. When N is omitted, open one window for each file.
  140. X.TP
  141. X-n
  142. XNo swap file will be used. Recovery after a crash 
  143. Xwill be impossible. Handy if you want to edit a file on a 
  144. Xvery slow medium (e.g. floppy). Can also be done with ":set 
  145. Xuc=0". Can be undone with ":set uc=200".
  146. X.TP
  147. X-s {scriptin}
  148. XThe script file {scriptin} is read. The characters in the 
  149. Xfile are interpreted as if you had typed them. The same can 
  150. Xbe done with the command ":source! {scriptin}". If the end 
  151. Xof the file is reached before the editor exits, further 
  152. Xcharacters are read from the keyboard.
  153. X.TP
  154. X-w {scriptout}
  155. XAll the characters that you type are recorded in the file
  156. X{scriptout}, until you exit VIM. This is useful if you want 
  157. Xto create a script file to be used with "vim -s" or 
  158. X":source!".
  159. X.TP
  160. X-T terminal
  161. XTells Vim the name of the terminal you are using. Should be a terminal known 
  162. Xto Vim (builtin) or defined in the termcap file.
  163. X.TP
  164. X-d device
  165. XOpen "device" for use as a terminal. Only on the Amiga. Example:
  166. X"\-d con:20/30/600/150".
  167. X.SH SEE ALSO
  168. XVim documentation:
  169. X.TP 12
  170. Xreference.doc:
  171. XA complete reference of Vim (long)
  172. X.TP
  173. Xwindows.doc:
  174. XExplanation of the multi windows and buffers commands and options
  175. X.TP
  176. Xindex:
  177. XOverview of all command characters (useful when adding new mappings)
  178. X.TP
  179. Xdifference.doc:
  180. XOverview of the differences between vi and Vim
  181. X.TP
  182. Xunix.doc:
  183. XUnix-specific comments
  184. X.TP
  185. Xvim.hlp:
  186. XFile used by the on-line help (short)
  187. X.SH AUTHOR
  188. XMost of VIM was made by Bram Moolenaar.
  189. X.br
  190. XVIM is based on Stevie, worked on by: Tim Thompson,
  191. XTony Andrews and G.R. (Fred) Walter
  192. X.SH BUGS
  193. XProbably.
  194. END_OF_FILE
  195.   if test 5252 -ne `wc -c <'vim/doc/vim.1'`; then
  196.     echo shar: \"'vim/doc/vim.1'\" unpacked with wrong size!
  197.   fi
  198.   # end of 'vim/doc/vim.1'
  199. fi
  200. if test -f 'vim/src/ops.c' -a "${1}" != "-c" ; then 
  201.   echo shar: Will not clobber existing file \"'vim/src/ops.c'\"
  202. else
  203.   echo shar: Extracting \"'vim/src/ops.c'\" \(39495 characters\)
  204.   sed "s/^X//" >'vim/src/ops.c' <<'END_OF_FILE'
  205. X/* vi:ts=4:sw=4
  206. X *
  207. X * VIM - Vi IMproved        by Bram Moolenaar
  208. X *
  209. X * Read the file "credits.txt" for a list of people who contributed.
  210. X * Read the file "uganda.txt" for copying and usage conditions.
  211. X */
  212. X
  213. X/*
  214. X * ops.c: implementation of various operators: doshift, dodelete, dotilde,
  215. X *          dochange, doyank, doput, dojoin
  216. X */
  217. X
  218. X#include "vim.h"
  219. X#include "globals.h"
  220. X#include "proto.h"
  221. X#include "param.h"
  222. X#include "ops.h"
  223. X
  224. X/*
  225. X * We have one yank buffer for normal yanks and puts, nine yank buffers for
  226. X * deletes and 26 yank buffers for use by name.
  227. X * Each yank buffer is an array of pointers to lines.
  228. X */
  229. Xstatic struct yankbuf
  230. X{
  231. X    char_u        **y_array;        /* pointer to array of line pointers */
  232. X    linenr_t     y_size;         /* number of lines in y_array */
  233. X    char_u        y_type;         /* MLINE, MCHAR or MBLOCK */
  234. X} y_buf[36];                    /* 0..9 = number buffers, 10..35 = char buffers */
  235. X
  236. Xstatic struct    yankbuf *y_current;        /* ptr to current yank buffer */
  237. Xstatic int        yankappend;                /* TRUE when appending */
  238. Xstatic struct    yankbuf *y_previous = NULL; /* ptr to last written yank buffer */
  239. X
  240. Xstatic void        get_yank_buffer __ARGS((int));
  241. Xstatic int        stuff_yank __ARGS((int, char_u *));
  242. Xstatic void        free_yank __ARGS((long));
  243. Xstatic void        free_yank_all __ARGS((void));
  244. Xstatic void        block_prep __ARGS((linenr_t, int));
  245. X
  246. X/* variables use by block_prep, dodelete and doyank */
  247. Xstatic int        startspaces;
  248. Xstatic int        endspaces;
  249. Xstatic int        textlen;
  250. Xstatic char_u        *textstart;
  251. Xstatic colnr_t    textcol;
  252. X
  253. X/*
  254. X * doshift - handle a shift operation
  255. X */
  256. X    void
  257. Xdoshift(op, curs_top, amount)
  258. X    int             op;
  259. X    int                curs_top;
  260. X    int                amount;
  261. X{
  262. X    register long    i;
  263. X    int                first_char;
  264. X
  265. X    if (!u_save((linenr_t)(curwin->w_cursor.lnum - 1), (linenr_t)(curwin->w_cursor.lnum + nlines)))
  266. X        return;
  267. X
  268. X    for (i = nlines; --i >= 0; )
  269. X    {
  270. X        first_char = *ml_get(curwin->w_cursor.lnum);
  271. X        if (first_char == NUL)                            /* empty line */
  272. X            curwin->w_cursor.col = 0;
  273. X        /*
  274. X         * Don't move the line right if it starts with # and p_si is set.
  275. X         */
  276. X        else if (!curbuf->b_p_si || first_char != '#')
  277. X        {
  278. X            /* if (Visual_block)
  279. X                    shift the block, not the whole line
  280. X            else */
  281. X                shift_line(op == LSHIFT, p_sr, amount);
  282. X        }
  283. X        ++curwin->w_cursor.lnum;
  284. X    }
  285. X
  286. X    if (curs_top)            /* put cursor on first line, for ">>" */
  287. X        curwin->w_cursor.lnum -= nlines;
  288. X    else
  289. X        --curwin->w_cursor.lnum;        /* put cursor on last line, for ":>" */
  290. X    updateScreen(CURSUPD);
  291. X
  292. X    if (nlines > p_report)
  293. X        smsg((char_u *)"%ld line%s %ced", nlines, plural(nlines),
  294. X                                    (op == RSHIFT) ? '>' : '<');
  295. X}
  296. X
  297. X/*
  298. X * shift the current line one shiftwidth left (if left != 0) or right
  299. X * leaves cursor on first blank in the line
  300. X */
  301. X    void
  302. Xshift_line(left, round, amount)
  303. X    int left;
  304. X    int    round;
  305. X    int    amount;
  306. X{
  307. X    register int count;
  308. X    register int i, j;
  309. X    int p_sw = (int)curbuf->b_p_sw;
  310. X
  311. X    count = get_indent();            /* get current indent */
  312. X
  313. X    if (round)                        /* round off indent */
  314. X    {
  315. X        i = count / p_sw;            /* number of p_sw rounded down */
  316. X        j = count % p_sw;            /* extra spaces */
  317. X        if (j && left)                /* first remove extra spaces */
  318. X            --amount;
  319. X        if (left)
  320. X        {
  321. X            i -= amount;
  322. X            if (i < 0)
  323. X                i = 0;
  324. X        }
  325. X        else
  326. X            i += amount;
  327. X        count = i * p_sw;
  328. X    }
  329. X    else                /* original vi indent */
  330. X    {
  331. X        if (left)
  332. X        {
  333. X            count -= p_sw * amount;
  334. X            if (count < 0)
  335. X                count = 0;
  336. X        }
  337. X        else
  338. X            count += p_sw * amount;
  339. X    }
  340. X    set_indent(count, TRUE);        /* set new indent */
  341. X}
  342. X
  343. X/*
  344. X * check if character is name of yank buffer
  345. X * Note: There is no check for 0 (default register), caller should do this
  346. X */
  347. X     int
  348. Xis_yank_buffer(c, write)
  349. X    int        c;
  350. X    int        write;        /* if TRUE check for writable buffers */
  351. X{
  352. X    if (isalnum(c) || (!write && strchr(".%:", c) != NULL) || c == '"')
  353. X        return TRUE;
  354. X    return FALSE;
  355. X}
  356. X
  357. X/*
  358. X * Set y_current and yankappend, according to the value of yankbuffer.
  359. X *
  360. X * If yankbuffer is 0 and writing, use buffer 0
  361. X * If yankbuffer is 0 and reading, use previous buffer
  362. X */
  363. X    static void
  364. Xget_yank_buffer(writing)
  365. X    int        writing;
  366. X{
  367. X    register int i;
  368. X
  369. X    yankappend = FALSE;
  370. X    if (((yankbuffer == 0 && !writing) || yankbuffer == '"') && y_previous != NULL)
  371. X    {
  372. X        y_current = y_previous;
  373. X        return;
  374. X    }
  375. X    i = yankbuffer;
  376. X    if (isdigit(i))
  377. X        i -= '0';
  378. X    else if (islower(i))
  379. X        i -= 'a' - 10;
  380. X    else if (isupper(i))
  381. X    {
  382. X        i -= 'A' - 10;
  383. X        yankappend = TRUE;
  384. X    }
  385. X    else            /* not 0-9, a-z or A-Z: use buffer 0 */
  386. X        i = 0;
  387. X    y_current = &(y_buf[i]);
  388. X    if (writing)        /* remember the buffer we write into for doput() */
  389. X        y_previous = y_current;
  390. X}
  391. X
  392. X/*
  393. X * start or stop recording into a yank buffer
  394. X *
  395. X * return FAIL for failure, OK otherwise
  396. X */
  397. X    int
  398. Xdorecord(c)
  399. X    int c;
  400. X{
  401. X    char_u        *p;
  402. X    static int    bufname;
  403. X    int            retval;
  404. X
  405. X    if (Recording == FALSE)         /* start recording */
  406. X    {
  407. X        if (!isalnum(c) && c != '"')    /* registers 0-9, a-z and " are allowed */
  408. X            retval = FAIL;
  409. X        else
  410. X        {
  411. X            Recording = TRUE;
  412. X            showmode();
  413. X            bufname = c;
  414. X            retval = OK;
  415. X        }
  416. X    }
  417. X    else                            /* stop recording */
  418. X    {
  419. X        Recording = FALSE;
  420. X        MSG("");
  421. X            /* the trailing 'q' command will not have been put in the buffer */
  422. X        p = get_recorded();
  423. X        if (p == NULL)
  424. X            retval = FAIL;
  425. X        else
  426. X            retval = (stuff_yank(bufname, p));
  427. X    }
  428. X    return retval;
  429. X}
  430. X
  431. X/*
  432. X * stuff string 'p' into yank buffer 'bufname' (append if uppercase)
  433. X * 'p' is assumed to be alloced.
  434. X *
  435. X * return FAIL for failure, OK otherwise
  436. X */
  437. X    static int
  438. Xstuff_yank(bufname, p)
  439. X    int bufname;
  440. X    char_u *p;
  441. X{
  442. X    char_u *lp;
  443. X    char_u **pp;
  444. X
  445. X    yankbuffer = bufname;
  446. X                                            /* check for read-only buffer */
  447. X    if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
  448. X        return FAIL;
  449. X    get_yank_buffer(TRUE);
  450. X    if (yankappend && y_current->y_array != NULL)
  451. X    {
  452. X        pp = &(y_current->y_array[y_current->y_size - 1]);
  453. X        lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
  454. X        if (lp == NULL)
  455. X        {
  456. X            free(p);
  457. X            return FAIL;
  458. X        }
  459. X        STRCPY(lp, *pp);
  460. X        STRCAT(lp, p);
  461. X        free(p);
  462. X        free(*pp);
  463. X        *pp = lp;
  464. X    }
  465. X    else
  466. X    {
  467. X        free_yank_all();
  468. X        if ((y_current->y_array = (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
  469. X        {
  470. X            free(p);
  471. X            return FAIL;
  472. X        }
  473. X        y_current->y_array[0] = p;
  474. X        y_current->y_size = 1;
  475. X        y_current->y_type = MCHAR;    /* used to be MLINE, why? */
  476. X    }
  477. X    return OK;
  478. X}
  479. X
  480. X/*
  481. X * execute a yank buffer (register): copy it into the stuff buffer
  482. X *
  483. X * return FAIL for failure, OK otherwise
  484. X */
  485. X    int
  486. Xdoexecbuf(c)
  487. X    int c;
  488. X{
  489. X    static int lastc = NUL;
  490. X    long i;
  491. X
  492. X    if (c == '@')                    /* repeat previous one */
  493. X        c = lastc;
  494. X    if (!is_yank_buffer(c, FALSE))    /* check for valid buffer */
  495. X        return FAIL;
  496. X    lastc = c;
  497. X
  498. X    if (c == ':')                    /* use last command line */
  499. X    {
  500. X        if (last_cmdline == NULL)
  501. X        {
  502. X            EMSG(e_nolastcmd);
  503. X            return FAIL;
  504. X        }
  505. X        free(new_last_cmdline);        /* don't keep the command line containing @: */
  506. X        new_last_cmdline = NULL;
  507. X        if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
  508. X            return FAIL;
  509. X        if (ins_typestr(last_cmdline, FALSE) == FAIL)
  510. X            return FAIL;
  511. X    }
  512. X    else
  513. X    {
  514. X        yankbuffer = c;
  515. X        get_yank_buffer(FALSE);
  516. X        if (y_current->y_array == NULL)
  517. X            return FAIL;
  518. X
  519. X        for (i = y_current->y_size; --i >= 0; )
  520. X        {
  521. X        /* insert newline between lines and after last line if type is MLINE */
  522. X            if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  523. X            {
  524. X                if (ins_typestr((char_u *)"\n", FALSE) == FAIL)
  525. X                    return FAIL;
  526. X            }
  527. X            if (ins_typestr(y_current->y_array[i], FALSE) == FAIL)
  528. X                return FAIL;
  529. X        }
  530. X        Exec_reg = TRUE;        /* disable the 'q' command */
  531. X    }
  532. X    return OK;
  533. X}
  534. X
  535. X/*
  536. X * insert a yank buffer: copy it into the Read buffer
  537. X * used by CTRL-R command in insert mode
  538. X *
  539. X * return FAIL for failure, OK otherwise
  540. X */
  541. X    int
  542. Xinsertbuf(c)
  543. X    int c;
  544. X{
  545. X    long i;
  546. X
  547. X    /*
  548. X     * It is possible to get into an endless loop by having CTRL-R a in
  549. X     * register a and then, in insert mode, doing CTRL-R a.
  550. X     * If you hit CTRL-C, the loop will be broken here.
  551. X     */
  552. X    breakcheck();
  553. X    if (got_int)
  554. X        return FAIL;
  555. X
  556. X    if (!is_yank_buffer(c, FALSE))        /* check for valid buffer */
  557. X        return FAIL;
  558. X
  559. X    if (c == '.')                        /* insert last inserted text */
  560. X    {
  561. X        stuff_inserted(NUL, 1L, TRUE);
  562. X        return OK;
  563. X    }
  564. X
  565. X    if (c == '%')                        /* insert file name */
  566. X    {
  567. X        if (check_fname() == FAIL)
  568. X            return FAIL;
  569. X        stuffReadbuff(curbuf->b_xfilename);
  570. X        return OK;
  571. X    }
  572. X
  573. X    if (c == ':')                        /* insert last command line */
  574. X    {
  575. X        if (last_cmdline == NULL)
  576. X        {
  577. X            EMSG(e_nolastcmd);
  578. X            return FAIL;
  579. X        }
  580. X        stuffReadbuff(last_cmdline);
  581. X        return OK;
  582. X    }
  583. X
  584. X    yankbuffer = c;
  585. X    get_yank_buffer(FALSE);
  586. X    if (y_current->y_array == NULL)
  587. X        return FAIL;
  588. X
  589. X    for (i = 0; i < y_current->y_size; ++i)
  590. X    {
  591. X        stuffReadbuff(y_current->y_array[i]);
  592. X    /* insert newline between lines and after last line if type is MLINE */
  593. X        if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  594. X            stuffReadbuff((char_u *)"\n");
  595. X    }
  596. X    return OK;
  597. X}
  598. X
  599. X/*
  600. X * dodelete - handle a delete operation
  601. X */
  602. X    void
  603. Xdodelete()
  604. X{
  605. X    register int    n;
  606. X    linenr_t        lnum;
  607. X    char_u            *ptr;
  608. X    char_u            *new, *old;
  609. X    linenr_t        old_lcount = curbuf->b_ml.ml_line_count;
  610. X    int                did_yank = FALSE;
  611. X
  612. X    /*
  613. X     * Imitate the strange Vi behaviour: If the delete spans more than one line
  614. X     * and mtype == MCHAR and the result is a blank line, make the delete
  615. X     * linewise. Don't do this for the change command.
  616. X     */
  617. X    if (mtype == MCHAR && nlines > 1 && operator == DELETE)
  618. X    {
  619. X        ptr = ml_get(curbuf->b_endop.lnum) + curbuf->b_endop.col + mincl;
  620. X        skipspace(&ptr);
  621. X        if (*ptr == NUL && inindent())
  622. X            mtype = MLINE;
  623. X    }
  624. X
  625. X/*
  626. X * If a yank buffer was specified, put the deleted text into that buffer
  627. X */
  628. X    if (yankbuffer != 0)
  629. X    {
  630. X                                        /* check for read-only buffer */
  631. X        if (!is_yank_buffer(yankbuffer, TRUE))
  632. X        {
  633. X            beep();
  634. X            return;
  635. X        }
  636. X        get_yank_buffer(TRUE);            /* yank into specified buffer */
  637. X        if (doyank(TRUE) == OK)
  638. X            did_yank = TRUE;
  639. X    }
  640. X
  641. X/*
  642. X * Put deleted text into register 1 and shift number buffers if
  643. X * the delete contains a line break.
  644. X * Overruled when a yankbuffer has been specified!
  645. X */
  646. X    if (yankbuffer != 0 || mtype == MLINE || nlines > 1)
  647. X    {
  648. X        y_current = &y_buf[9];
  649. X        free_yank_all();                /* free buffer nine */
  650. X        for (n = 9; n > 1; --n)
  651. X            y_buf[n] = y_buf[n - 1];
  652. X        y_previous = y_current = &y_buf[1];
  653. X        y_buf[1].y_array = NULL;        /* set buffer one to empty */
  654. X        yankbuffer = 0;
  655. X    }
  656. X    else if (yankbuffer == 0)            /* yank into unnamed buffer */
  657. X        get_yank_buffer(TRUE);
  658. X
  659. X    /*
  660. X     * Do a yank of whatever we're about to delete. If there's too much stuff
  661. X     * to fit in the yank buffer, then get a confirmation before doing the
  662. X     * delete. This is crude, but simple. And it avoids doing a delete of
  663. X     * something we can't put back if we want.
  664. X     */
  665. X    if (yankbuffer == 0 && doyank(TRUE) == OK)
  666. X        did_yank = TRUE;
  667. X
  668. X    if (!did_yank)
  669. X    {
  670. X        if (ask_yesno((char_u *)"cannot yank; delete anyway") != 'y')
  671. X        {
  672. X            emsg(e_abort);
  673. X            return;
  674. X        }
  675. X    }
  676. X
  677. X/*
  678. X * block mode
  679. X */
  680. X    if (Visual_block)
  681. X    {
  682. X        if (!u_save((linenr_t)(curbuf->b_startop.lnum - 1), (linenr_t)(curbuf->b_endop.lnum + 1)))
  683. X            return;
  684. X
  685. X        for (lnum = curwin->w_cursor.lnum; curwin->w_cursor.lnum <= curbuf->b_endop.lnum; ++curwin->w_cursor.lnum)
  686. X        {
  687. X            block_prep(curwin->w_cursor.lnum, TRUE);
  688. X            if (textlen == 0)        /* nothing to delete */
  689. X                continue;
  690. X
  691. X        /*
  692. X         * If we delete a TAB, it may be replaced by several characters.
  693. X         * Thus the number of characters may increase!
  694. X         */
  695. X            n = textlen - startspaces - endspaces;        /* number of chars deleted */
  696. X            old = ml_get(curwin->w_cursor.lnum);
  697. X            new = alloc((unsigned)STRLEN(old) + 1 - n);
  698. X            if (new == NULL)
  699. X                continue;
  700. X        /* copy up to deleted part */
  701. X            memmove((char *)new, (char *)old, (size_t)textcol);
  702. X        /* insert spaces */
  703. X            copy_spaces(new + textcol, (size_t)(startspaces + endspaces));
  704. X        /* copy the part after the deleted part */
  705. X            old += textcol + textlen;
  706. X            memmove((char *)new + textcol + startspaces + endspaces,
  707. X                                    (char *)old, STRLEN(old) + 1);
  708. X        /* replace the line */
  709. X            ml_replace(curwin->w_cursor.lnum, new, FALSE);
  710. X        }
  711. X        curwin->w_cursor.lnum = lnum;
  712. X        CHANGED;
  713. X        updateScreen(VALID_TO_CURSCHAR);
  714. X        nlines = 0;        /* no lines deleted */
  715. X    }
  716. X    else if (mtype == MLINE)
  717. X    {
  718. X        if (operator == CHANGE)
  719. X        {
  720. X            dellines((long)(nlines - 1), TRUE, TRUE);
  721. X            if (!u_save_cursor())
  722. X                return;
  723. X            if (curbuf->b_p_ai)                /* don't delete indent */
  724. X            {
  725. X                beginline(TRUE);            /* put cursor on first non-white */
  726. X                did_ai = TRUE;                /* delete the indent when ESC hit */
  727. X            }
  728. X            while (delchar(FALSE) == OK)    /* slow but simple */
  729. X                ;
  730. X            if (curwin->w_cursor.col > 0)
  731. X                --curwin->w_cursor.col;        /* put cursor on last char in line */
  732. X        }
  733. X        else
  734. X        {
  735. X            dellines(nlines, TRUE, TRUE);
  736. X        }
  737. X        u_clearline();    /* "U" command should not be possible after "dd" */
  738. X        beginline(TRUE);
  739. X    }
  740. X    else if (nlines == 1)        /* delete characters within one line */
  741. X    {
  742. X        if (!u_save_cursor())
  743. X            return;
  744. X        n = curbuf->b_endop.col - curbuf->b_startop.col + 1 - !mincl;
  745. X        while (n-- > 0)
  746. X            if (delchar(TRUE) == FAIL)
  747. X                break;
  748. X    }
  749. X    else                        /* delete characters between lines */
  750. X    {
  751. X        if (!u_save_cursor())    /* save first line for undo */
  752. X            return;
  753. X        n = curwin->w_cursor.col;
  754. X        while (curwin->w_cursor.col >= n)    /* delete from cursor to end of line */
  755. X            if (delchar(TRUE) == FAIL)
  756. X                break;
  757. X
  758. X        curbuf->b_startop = curwin->w_cursor;        /* remember curwin->w_cursor */
  759. X        ++curwin->w_cursor.lnum;
  760. X        dellines((long)(nlines - 2), TRUE, TRUE);    /* includes save for undo */
  761. X
  762. X        if (!u_save_cursor())    /* save last line for undo */
  763. X            return;
  764. X        n = curbuf->b_endop.col - !mincl;
  765. X        curwin->w_cursor.col = 0;
  766. X        while (n-- >= 0)        /* delete from start of line until endop */
  767. X            if (delchar(TRUE) == FAIL)
  768. X                break;
  769. X        curwin->w_cursor = curbuf->b_startop;        /* restore curwin->w_cursor */
  770. X        (void)dojoin(FALSE, TRUE);
  771. X    }
  772. X
  773. X    if ((mtype == MCHAR && nlines == 1) || operator == CHANGE)
  774. X    {
  775. X        cursupdate();
  776. X        updateline();
  777. X    }
  778. X    else
  779. X        updateScreen(CURSUPD);
  780. X
  781. X    msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  782. X
  783. X        /* correct endop for deleted text (for "']" command) */
  784. X    if (Visual_block)
  785. X        curbuf->b_endop.col = curbuf->b_startop.col;
  786. X    else
  787. X        curbuf->b_endop = curbuf->b_startop;
  788. X}
  789. X
  790. X/*
  791. X * dotilde - handle the (non-standard vi) tilde operator
  792. X */
  793. X    void
  794. Xdotilde()
  795. X{
  796. X    FPOS pos;
  797. X
  798. X    if (!u_save((linenr_t)(curbuf->b_startop.lnum - 1), (linenr_t)(curbuf->b_endop.lnum + 1)))
  799. X        return;
  800. X
  801. X    pos = curbuf->b_startop;
  802. X    if (Visual_block)        /* block mode */
  803. X    {
  804. X        for (; pos.lnum <= curbuf->b_endop.lnum; ++pos.lnum)
  805. X        {
  806. X            block_prep(pos.lnum, FALSE);
  807. X            pos.col = textcol;
  808. X            while (--textlen >= 0)
  809. X            {
  810. X                swapchar(&pos);
  811. X                if (inc(&pos) == -1)    /* at end of file */
  812. X                    break;
  813. X            }
  814. X        }
  815. X    }
  816. X    else            /* not block mode */
  817. X    {
  818. X        if (mtype == MLINE)
  819. X        {
  820. X                pos.col = 0;
  821. X                curbuf->b_endop.col = STRLEN(ml_get(curbuf->b_endop.lnum));
  822. X                if (curbuf->b_endop.col)
  823. X                        --curbuf->b_endop.col;
  824. X        }
  825. X        else if (!mincl)
  826. X            dec(&(curbuf->b_endop));
  827. X
  828. X        while (ltoreq(pos, curbuf->b_endop))
  829. X        {
  830. X            swapchar(&pos);
  831. X            if (inc(&pos) == -1)    /* at end of file */
  832. X                break;
  833. X        }
  834. X    }
  835. X
  836. X    if (mtype == MCHAR && nlines == 1 && !Visual_block)
  837. X    {
  838. X        cursupdate();
  839. X        updateline();
  840. X    }
  841. X    else
  842. X        updateScreen(CURSUPD);
  843. X
  844. X    if (nlines > p_report)
  845. X            smsg((char_u *)"%ld line%s ~ed", nlines, plural(nlines));
  846. X}
  847. X
  848. X/*
  849. X * If operator == UPPER: make uppercase,
  850. X * if operator == LOWER: make lowercase,
  851. X * else swap case of character at 'pos'
  852. X */
  853. X    void
  854. Xswapchar(pos)
  855. X    FPOS    *pos;
  856. X{
  857. X    int        c;
  858. X
  859. X    c = gchar(pos);
  860. X    if (islower(c) && operator != LOWER)
  861. X    {
  862. X        pchar(*pos, toupper(c));
  863. X        CHANGED;
  864. X    }
  865. X    else if (isupper(c) && operator != UPPER)
  866. X    {
  867. X        pchar(*pos, tolower(c));
  868. X        CHANGED;
  869. X    }
  870. X}
  871. X
  872. X/*
  873. X * dochange - handle a change operation
  874. X */
  875. X    void
  876. Xdochange()
  877. X{
  878. X    register colnr_t            l;
  879. X
  880. X    l = curbuf->b_startop.col;
  881. X
  882. X    if (!no_op)
  883. X        dodelete();
  884. X
  885. X    if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum))
  886. X        inc_cursor();
  887. X
  888. X    startinsert(NUL, FALSE, (linenr_t)1);
  889. X}
  890. X
  891. X/*
  892. X * set all the yank buffers to empty (called from main())
  893. X */
  894. X    void
  895. Xinit_yank()
  896. X{
  897. X        register int i;
  898. X
  899. X        for (i = 0; i < 36; ++i)
  900. X                y_buf[i].y_array = NULL;
  901. X}
  902. X
  903. X/*
  904. X * Free "n" lines from the current yank buffer.
  905. X * Called for normal freeing and in case of error.
  906. X */
  907. X    static void
  908. Xfree_yank(n)
  909. X    long n;
  910. X{
  911. X    if (y_current->y_array != NULL)
  912. X    {
  913. X        register long i;
  914. X
  915. X        for (i = n; --i >= 0; )
  916. X        {
  917. X            if (i % 1000 == 999)                    /* this may take a while */
  918. X                smsg((char_u *)"freeing %ld lines", i + 1);
  919. X            free(y_current->y_array[i]);
  920. X        }
  921. X        free(y_current->y_array);
  922. X        y_current->y_array = NULL;
  923. X        if (n >= 1000)
  924. X            MSG("");
  925. X    }
  926. X}
  927. X
  928. X    static void
  929. Xfree_yank_all()
  930. X{
  931. X        free_yank(y_current->y_size);
  932. X}
  933. X
  934. X/*
  935. X * Yank the text between curwin->w_cursor and startpos into a yank buffer.
  936. X * If we are to append ("uppercase), we first yank into a new yank buffer and
  937. X * then concatenate the old and the new one (so we keep the old one in case
  938. X * of out-of-memory).
  939. X *
  940. X * return FAIL for failure, OK otherwise
  941. X */
  942. X    int
  943. Xdoyank(deleting)
  944. X    int deleting;
  945. X{
  946. X    long                 i;                /* index in y_array[] */
  947. X    struct yankbuf        *curr;            /* copy of y_current */
  948. X    struct yankbuf        new;             /* new yank buffer when appending */
  949. X    char_u                **new_ptr;
  950. X    register linenr_t    lnum;            /* current line number */
  951. X    long                 j;
  952. X    int                    yanktype = mtype;
  953. X    long                yanklines = nlines;
  954. X    linenr_t            yankendlnum = curbuf->b_endop.lnum;
  955. X
  956. X    char_u                *pnew;
  957. X
  958. X                                    /* check for read-only buffer */
  959. X    if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
  960. X    {
  961. X        beep();
  962. X        return FAIL;
  963. X    }
  964. X    if (!deleting)                    /* dodelete() already set y_current */
  965. X        get_yank_buffer(TRUE);
  966. X
  967. X    curr = y_current;
  968. X    if (yankappend && y_current->y_array != NULL) /* append to existing contents */
  969. X        y_current = &new;
  970. X    else
  971. X        free_yank_all();        /* free previously yanked lines */
  972. X
  973. X/*
  974. X * If the cursor was in column 1 before and after the movement, the
  975. X * yank is always linewise.
  976. X */
  977. X    if (mtype == MCHAR && curbuf->b_startop.col == 0 && curbuf->b_endop.col == 0 && nlines > 1)
  978. X    {
  979. X        yanktype = MLINE;
  980. X        if (mincl == FALSE && yankendlnum > curbuf->b_startop.lnum)
  981. X        {
  982. X            --yankendlnum;
  983. X            --yanklines;
  984. X        }
  985. X    }
  986. X
  987. X    y_current->y_size = yanklines;
  988. X    y_current->y_type = yanktype;    /* set the yank buffer type */
  989. X    y_current->y_array = (char_u **)lalloc((long_u)(sizeof(char_u *) * yanklines), TRUE);
  990. X
  991. X    if (y_current->y_array == NULL)
  992. X    {
  993. X        y_current = curr;
  994. X        return FAIL;
  995. X    }
  996. X
  997. X    i = 0;
  998. X    lnum = curbuf->b_startop.lnum;
  999. X
  1000. X    if (Visual_block)
  1001. X    {
  1002. X/*
  1003. X * block mode
  1004. X */
  1005. X        y_current->y_type = MBLOCK;    /* set the yank buffer type */
  1006. X        for ( ; lnum <= yankendlnum; ++lnum)
  1007. X        {
  1008. X            block_prep(lnum, FALSE);
  1009. X            if ((pnew = alloc(startspaces + endspaces + textlen + 1)) == NULL)
  1010. X                goto fail;
  1011. X            y_current->y_array[i++] = pnew;
  1012. X            copy_spaces(pnew, (size_t)startspaces);
  1013. X            pnew += startspaces;
  1014. X            STRNCPY(pnew, textstart, (size_t)textlen);
  1015. X            pnew += textlen;
  1016. X            copy_spaces(pnew, (size_t)endspaces);
  1017. X            pnew += endspaces;
  1018. X            *pnew = NUL;
  1019. X        }
  1020. X    }
  1021. X    else
  1022. X    {
  1023. X/*
  1024. X * there are three parts for non-block mode:
  1025. X * 1. if yanktype != MLINE yank last part of the top line
  1026. X * 2. yank the lines between startop and endop, inclusive when yanktype == MLINE
  1027. X * 3. if yanktype != MLINE yank first part of the bot line
  1028. X */
  1029. X        if (yanktype != MLINE)
  1030. X        {
  1031. X            if (yanklines == 1)        /* startop and endop on same line */
  1032. X            {
  1033. X                    j = curbuf->b_endop.col - curbuf->b_startop.col + 1 - !mincl;
  1034. X                    if ((y_current->y_array[0] = strnsave(ml_get(lnum) + curbuf->b_startop.col, (int)j)) == NULL)
  1035. X                    {
  1036. X    fail:
  1037. X                            free_yank(i);    /* free the lines that we allocated */
  1038. X                            y_current = curr;
  1039. X                            return FAIL;
  1040. X                    }
  1041. X                    goto success;
  1042. X            }
  1043. X            if ((y_current->y_array[0] = strsave(ml_get(lnum++) + curbuf->b_startop.col)) == NULL)
  1044. X                    goto fail;
  1045. X            ++i;
  1046. X        }
  1047. X
  1048. X        while (yanktype == MLINE ? (lnum <= yankendlnum) : (lnum < yankendlnum))
  1049. X        {
  1050. X            if ((y_current->y_array[i] = strsave(ml_get(lnum++))) == NULL)
  1051. X                    goto fail;
  1052. X            ++i;
  1053. X        }
  1054. X        if (yanktype != MLINE)
  1055. X        {
  1056. X            if ((y_current->y_array[i] = strnsave(ml_get(yankendlnum), curbuf->b_endop.col + 1 - !mincl)) == NULL)
  1057. X                    goto fail;
  1058. X        }
  1059. X    }
  1060. X
  1061. Xsuccess:
  1062. X    if (curr != y_current)        /* append the new block to the old block */
  1063. X    {
  1064. X        new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) * (curr->y_size + y_current->y_size)), TRUE);
  1065. X        if (new_ptr == NULL)
  1066. X                goto fail;
  1067. X        for (j = 0; j < curr->y_size; ++j)
  1068. X                new_ptr[j] = curr->y_array[j];
  1069. X        free(curr->y_array);
  1070. X        curr->y_array = new_ptr;
  1071. X
  1072. X        if (yanktype == MLINE)     /* MLINE overrides MCHAR and MBLOCK */
  1073. X                curr->y_type = MLINE;
  1074. X        if (curr->y_type == MCHAR)        /* concatenate the last line of the old
  1075. X                                        block with the first line of the new block */
  1076. X        {
  1077. X                pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1]) + STRLEN(y_current->y_array[0]) + 1), TRUE);
  1078. X                if (pnew == NULL)
  1079. X                {
  1080. X                        i = y_current->y_size - 1;
  1081. X                        goto fail;
  1082. X                }
  1083. X                STRCPY(pnew, curr->y_array[--j]);
  1084. X                STRCAT(pnew, y_current->y_array[0]);
  1085. X                free(curr->y_array[j]);
  1086. X                free(y_current->y_array[0]);
  1087. X                curr->y_array[j++] = pnew;
  1088. X                i = 1;
  1089. X        }
  1090. X        else
  1091. X                i = 0;
  1092. X        while (i < y_current->y_size)
  1093. X                curr->y_array[j++] = y_current->y_array[i++];
  1094. X        curr->y_size = j;
  1095. X        free(y_current->y_array);
  1096. X        y_current = curr;
  1097. X    }
  1098. X    if (operator == YANK)        /* don't do this when deleting */
  1099. X    {
  1100. X        if (yanktype == MCHAR && !Visual_block)
  1101. X            --yanklines;
  1102. X        if (yanklines > p_report)
  1103. X        {
  1104. X            cursupdate();        /* redisplay now, so message is not deleted */
  1105. X            smsg((char_u *)"%ld line%s yanked", yanklines, plural(yanklines));
  1106. X        }
  1107. X    }
  1108. X
  1109. X    return OK;
  1110. X}
  1111. X
  1112. X/*
  1113. X * put contents of register into the text
  1114. X */
  1115. X    void
  1116. Xdoput(dir, count, fix_indent)
  1117. X    int        dir;                /* BACKWARD for 'P', FORWARD for 'p' */
  1118. X    long    count;
  1119. X    int        fix_indent;            /* make indent look nice */
  1120. X{
  1121. X    char_u        *ptr;
  1122. X    char_u        *new, *old;
  1123. X    int         yanklen;
  1124. X    int            oldlen;
  1125. X    int            totlen = 0;        /* init for gcc */
  1126. X    linenr_t    lnum;
  1127. X    int            col;
  1128. X    long         i;        /* index in y_array[] */
  1129. X    int         y_type;
  1130. X    long         y_size;
  1131. X    char_u        **y_array;
  1132. X    long         nlines = 0;
  1133. X    int            vcol;
  1134. X    int            delchar;
  1135. X    int            incr = 0;
  1136. X    long        j;
  1137. X    FPOS        new_cursor;
  1138. X    int            commandchar;
  1139. X    char_u        temp[2];
  1140. X    int            indent;
  1141. X    int            orig_indent = 0;            /* init for gcc */
  1142. X    int            indent_diff = 0;            /* init for gcc */
  1143. X    int            first_indent = TRUE;
  1144. X
  1145. X    if (fix_indent)
  1146. X        orig_indent = get_indent();
  1147. X
  1148. X    curbuf->b_startop = curwin->w_cursor;            /* default for "'[" command */
  1149. X    if (dir == FORWARD)
  1150. X        curbuf->b_startop.col++;
  1151. X    curbuf->b_endop = curwin->w_cursor;                /* default for "']" command */
  1152. X    commandchar = (dir == FORWARD ? (count == -1 ? 'o' : 'a') : (count == -1 ? 'O' : 'i'));
  1153. X    if (yankbuffer == '.')        /* use inserted text */
  1154. X    {
  1155. X        stuff_inserted(commandchar, count, FALSE);
  1156. X        return;
  1157. X    }
  1158. X    else if (yankbuffer == '%')    /* use file name */
  1159. X    {
  1160. X        if (check_fname() == OK)
  1161. X        {
  1162. X            stuffcharReadbuff(commandchar);
  1163. X            stuffReadbuff(curbuf->b_xfilename);
  1164. X            stuffcharReadbuff(ESC);
  1165. X        }
  1166. X        return;
  1167. X    }
  1168. X    else if (yankbuffer == ':')    /* use last command line */
  1169. X    {
  1170. X        if (last_cmdline == NULL)
  1171. X            EMSG(e_nolastcmd);
  1172. X        else
  1173. X        {
  1174. X            stuffcharReadbuff(commandchar);
  1175. X            stuffReadbuff(last_cmdline);
  1176. X            stuffcharReadbuff(ESC);
  1177. X        }
  1178. X        return;
  1179. X    }
  1180. X
  1181. X    get_yank_buffer(FALSE);
  1182. X
  1183. X    y_type = y_current->y_type;
  1184. X    y_size = y_current->y_size;
  1185. X    y_array = y_current->y_array;
  1186. X
  1187. X    if (count == -1)        /* :put command */
  1188. X    {
  1189. X        y_type = MLINE;
  1190. X        count = 1;
  1191. X    }
  1192. X
  1193. X    if (y_size == 0 || y_array == NULL)
  1194. X    {
  1195. X        temp[0] = yankbuffer;
  1196. X        temp[1] = NUL;
  1197. X        EMSG2("Nothing in register %s", temp);
  1198. X        return;
  1199. X    }
  1200. X
  1201. X    if (y_type == MBLOCK)
  1202. X    {
  1203. X        lnum = curwin->w_cursor.lnum + y_size + 1;
  1204. X        if (lnum > curbuf->b_ml.ml_line_count)
  1205. X            lnum = curbuf->b_ml.ml_line_count + 1;
  1206. X        if (!u_save(curwin->w_cursor.lnum - 1, lnum))
  1207. X            return;
  1208. X    }
  1209. X    else if (!u_save_cursor())
  1210. X        return;
  1211. X
  1212. X    yanklen = STRLEN(y_array[0]);
  1213. X    CHANGED;
  1214. X
  1215. X    lnum = curwin->w_cursor.lnum;
  1216. X    col = curwin->w_cursor.col;
  1217. X
  1218. X/*
  1219. X * block mode
  1220. X */
  1221. X    if (y_type == MBLOCK)
  1222. X    {
  1223. X        if (dir == FORWARD && gchar_cursor() != NUL)
  1224. X        {
  1225. X            col = getvcol(curwin, &curwin->w_cursor, 3) + 1;
  1226. X            ++curwin->w_cursor.col;
  1227. X        }
  1228. X        else
  1229. X            col = getvcol(curwin, &curwin->w_cursor, 2);
  1230. X        for (i = 0; i < y_size; ++i)
  1231. X        {
  1232. X            startspaces = 0;
  1233. X            endspaces = 0;
  1234. X            textcol = 0;
  1235. X            vcol = 0;
  1236. X            delchar = 0;
  1237. X
  1238. X        /* add a new line */
  1239. X            if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  1240. X            {
  1241. X                ml_append(curbuf->b_ml.ml_line_count, (char_u *)"", (colnr_t)1, FALSE);
  1242. X                ++nlines;
  1243. X            }
  1244. X            old = ml_get(curwin->w_cursor.lnum);
  1245. X            oldlen = STRLEN(old);
  1246. X            for (ptr = old; vcol < col && *ptr; ++ptr)
  1247. X            {
  1248. X                /* Count a tab for what it's worth (if list mode not on) */
  1249. X                incr = chartabsize(*ptr, (long)vcol);
  1250. X                vcol += incr;
  1251. X                ++textcol;
  1252. X            }
  1253. X            if (vcol < col)    /* line too short, padd with spaces */
  1254. X            {
  1255. X                startspaces = col - vcol;
  1256. X            }
  1257. X            else if (vcol > col)
  1258. X            {
  1259. X                endspaces = vcol - col;
  1260. X                startspaces = incr - endspaces;
  1261. X                --textcol;
  1262. X                delchar = 1;
  1263. X            }
  1264. X            yanklen = STRLEN(y_array[i]);
  1265. X            totlen = count * yanklen + startspaces + endspaces;
  1266. X            new = alloc((unsigned)totlen + oldlen + 1);
  1267. X            if (new == NULL)
  1268. X                break;
  1269. X        /* copy part up to cursor to new line */
  1270. X            ptr = new;
  1271. X            memmove((char *)ptr, (char *)old, (size_t)textcol);
  1272. X            ptr += textcol;
  1273. X        /* may insert some spaces before the new text */
  1274. X            copy_spaces(ptr, (size_t)startspaces);
  1275. X            ptr += startspaces;
  1276. X        /* insert the new text */
  1277. X            for (j = 0; j < count; ++j)
  1278. X            {
  1279. X                    STRNCPY(ptr, y_array[i], (size_t)yanklen);
  1280. X                    ptr += yanklen;
  1281. X            }
  1282. X        /* may insert some spaces after the new text */
  1283. X            copy_spaces(ptr, (size_t)endspaces);
  1284. X            ptr += endspaces;
  1285. X        /* move the text after the cursor to the end of the line. */
  1286. X            memmove((char *)ptr, (char *)old + textcol + delchar,
  1287. X                            (size_t)(oldlen - textcol - delchar + 1));
  1288. X            ml_replace(curwin->w_cursor.lnum, new, FALSE);
  1289. X
  1290. X            ++curwin->w_cursor.lnum;
  1291. X            if (i == 0)
  1292. X                curwin->w_cursor.col += startspaces;
  1293. X        }
  1294. X        curbuf->b_endop.lnum = curwin->w_cursor.lnum - 1;        /* for "']" command */
  1295. X        curbuf->b_endop.col = textcol + totlen - 1;
  1296. X        curwin->w_cursor.lnum = lnum;
  1297. X        cursupdate();
  1298. X        updateScreen(VALID_TO_CURSCHAR);
  1299. X    }
  1300. X    else        /* not block mode */
  1301. X    {
  1302. X        if (y_type == MCHAR)
  1303. X        {
  1304. X    /* if type is MCHAR, FORWARD is the same as BACKWARD on the next character */
  1305. X            if (dir == FORWARD && gchar_cursor() != NUL)
  1306. X            {
  1307. X                ++col;
  1308. X                if (yanklen)
  1309. X                {
  1310. X                    ++curwin->w_cursor.col;
  1311. X                    ++curbuf->b_endop.col;
  1312. X                }
  1313. X            }
  1314. X            new_cursor = curwin->w_cursor;
  1315. X        }
  1316. X        else if (dir == BACKWARD)
  1317. X    /* if type is MLINE, BACKWARD is the same as FORWARD on the previous line */
  1318. X            --lnum;
  1319. X
  1320. X/*
  1321. X * simple case: insert into current line
  1322. X */
  1323. X        if (y_type == MCHAR && y_size == 1)
  1324. X        {
  1325. X            totlen = count * yanklen;
  1326. X            if (totlen)
  1327. X            {
  1328. X                old = ml_get(lnum);
  1329. X                new = alloc((unsigned)(STRLEN(old) + totlen + 1));
  1330. X                if (new == NULL)
  1331. X                    return;                 /* alloc() will give error message */
  1332. X                memmove((char *)new, (char *)old, (size_t)col);
  1333. X                ptr = new + col;
  1334. X                for (i = 0; i < count; ++i)
  1335. X                {
  1336. X                    memmove((char *)ptr, (char *)y_array[0], (size_t)yanklen);
  1337. X                    ptr += yanklen;
  1338. X                }
  1339. X                memmove((char *)ptr, (char *)old + col, STRLEN(old + col) + 1);
  1340. X                ml_replace(lnum, new, FALSE);
  1341. X                curwin->w_cursor.col += (colnr_t)(totlen - 1);    /* put cursor on last putted char */
  1342. X            }
  1343. X            curbuf->b_endop = curwin->w_cursor;
  1344. X            updateline();
  1345. X        }
  1346. X        else
  1347. X        {
  1348. X            if (y_type == MCHAR)
  1349. X                --y_size;
  1350. X            while (--count >= 0)
  1351. X            {
  1352. X                i = 0;
  1353. X                if (y_type == MCHAR)
  1354. X                {
  1355. X                    /*
  1356. X                     * Split the current line in two at the insert position.
  1357. X                     * First insert y_array[size - 1] in front of second line.
  1358. X                     * Then append y_array[0] to first line.
  1359. X                     */
  1360. X                    ptr = ml_get(lnum) + col;
  1361. X                    totlen = STRLEN(y_array[y_size]);
  1362. X                    new = alloc((unsigned)(STRLEN(ptr) + totlen + 1));
  1363. X                    if (new == NULL)
  1364. X                        goto error;
  1365. X                    STRCPY(new, y_array[y_size]);
  1366. X                    STRCAT(new, ptr);
  1367. X                    ml_append(lnum, new, (colnr_t)0, FALSE);    /* insert second line */
  1368. X                    free(new);
  1369. X                    ++nlines;
  1370. X
  1371. X                    old = ml_get(lnum);
  1372. X                    new = alloc((unsigned)(col + yanklen + 1));
  1373. X                    if (new == NULL)
  1374. X                        goto error;
  1375. X                                            /* copy first part of line */
  1376. X                    memmove((char *)new, (char *)old, (size_t)col);
  1377. X                                            /* append to first line */
  1378. X                    memmove((char *)new + col, (char *)y_array[0],
  1379. X                                            (size_t)(yanklen + 1));
  1380. X                    ml_replace(lnum, new, FALSE);
  1381. X
  1382. X                    curwin->w_cursor.lnum = lnum;
  1383. X                    i = 1;
  1384. X                }
  1385. X
  1386. X                while (i < y_size)
  1387. X                {
  1388. X                    if (ml_append(lnum++, y_array[i++], (colnr_t)0, FALSE) == FAIL)
  1389. X                        goto error;
  1390. X                    if (fix_indent)
  1391. X                    {
  1392. X                        curwin->w_cursor.lnum = lnum;
  1393. X                        if (curbuf->b_p_si && *ml_get(lnum) == '#')
  1394. X                            indent = 0;        /* Leave # lines at start */
  1395. X                        else if (first_indent)
  1396. X                        {
  1397. X                            indent_diff = orig_indent - get_indent();
  1398. X                            indent = orig_indent;
  1399. X                            first_indent = FALSE;
  1400. X                        }
  1401. X                        else if ((indent = get_indent() + indent_diff) < 0)
  1402. X                            indent = 0;
  1403. X                        set_indent(indent, TRUE);
  1404. X                    }
  1405. X                    ++nlines;
  1406. X                }
  1407. X                if (y_type == MCHAR)
  1408. X                    ++lnum;     /* lnum is now number of line below inserted lines */
  1409. X            }
  1410. X
  1411. X            curbuf->b_endop.lnum = lnum;        /* for "']" command */
  1412. X            if (y_type == MLINE)
  1413. X            {
  1414. X                curwin->w_cursor.col = 0;
  1415. X                curbuf->b_endop.col = 0;
  1416. X                if (dir == FORWARD)
  1417. X                {
  1418. X                    updateScreen(NOT_VALID);        /* recompute curwin->w_botline */
  1419. X                    ++curwin->w_cursor.lnum;
  1420. X                }
  1421. X                    /* put cursor on first non-blank in last inserted line */
  1422. X                beginline(TRUE);
  1423. X            }
  1424. X            else        /* put cursor on first inserted character */
  1425. X            {
  1426. X                if (col > 1)
  1427. X                    curbuf->b_endop.col = col - 1;
  1428. X                else
  1429. X                    curbuf->b_endop.col = 0;
  1430. X                curwin->w_cursor = new_cursor;
  1431. X            }
  1432. X
  1433. Xerror:
  1434. X            if (y_type == MLINE)        /* for '[ */
  1435. X            {
  1436. X                curbuf->b_startop.col = 0;
  1437. X                if (dir == FORWARD)
  1438. X                    curbuf->b_startop.lnum++;
  1439. X            }
  1440. X            mark_adjust(curbuf->b_startop.lnum + (y_type == MCHAR), MAXLNUM, nlines);
  1441. X            updateScreen(CURSUPD);
  1442. X        }
  1443. X    }
  1444. X
  1445. X    msgmore(nlines);
  1446. X    curwin->w_set_curswant = TRUE;
  1447. X}
  1448. X
  1449. X/*
  1450. X * display the contents of the yank buffers
  1451. X */
  1452. X    void
  1453. Xdodis()
  1454. X{
  1455. X    register int            i, n;
  1456. X    register long            j;
  1457. X    register char_u            *p;
  1458. X    register struct yankbuf *yb;
  1459. X
  1460. X    gotocmdline(TRUE, NUL);
  1461. X
  1462. X    msg_outstr((char_u *)"--- Registers ---");
  1463. X    for (i = -1; i < 36; ++i)
  1464. X    {
  1465. X        if (i == -1)
  1466. X        {
  1467. X            if (y_previous != NULL)
  1468. X                yb = y_previous;
  1469. X            else
  1470. X                yb = &(y_buf[0]);
  1471. X        }
  1472. X        else
  1473. X            yb = &(y_buf[i]);
  1474. X        if (yb->y_array != NULL)
  1475. X        {
  1476. X            msg_outchar('\n');
  1477. X            if (i == -1)
  1478. X                msg_outstr((char_u *)"\"\"");
  1479. X            else
  1480. X            {
  1481. X                msg_outchar('"');
  1482. X                if (i < 10)
  1483. X                    msg_outchar(i + '0');
  1484. X                else
  1485. X                    msg_outchar(i + 'a' - 10);
  1486. X            }
  1487. X            msg_outstr((char_u *)"   ");
  1488. X
  1489. X            n = (int)Columns - 6;
  1490. X            for (j = 0; j < yb->y_size && n > 1; ++j)
  1491. X            {
  1492. X                if (j)
  1493. X                {
  1494. X                    msg_outstr((char_u *)"^J");
  1495. X                    n -= 2;
  1496. X                }
  1497. X                for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
  1498. X                    msg_outtrans(p, 1);
  1499. X            }
  1500. X            flushbuf();                /* show one line at a time */
  1501. X        }
  1502. X    }
  1503. X
  1504. X    /*
  1505. X     * display last inserted text
  1506. X     */
  1507. X    if ((p = get_last_insert()) != NULL)
  1508. X    {
  1509. X        msg_outstr((char_u *)"\n\".   ");
  1510. X        dis_msg(p, TRUE);
  1511. X    }
  1512. X
  1513. X    /*
  1514. X     * display last command line
  1515. X     */
  1516. X    if (last_cmdline != NULL)
  1517. X    {
  1518. X        msg_outstr((char_u *)"\n\":   ");
  1519. X        dis_msg(last_cmdline, FALSE);
  1520. X    }
  1521. X
  1522. X    /*
  1523. X     * display current file name
  1524. X     */
  1525. X    if (curbuf->b_xfilename != NULL)
  1526. X    {
  1527. X        msg_outstr((char_u *)"\n\"%   ");
  1528. X        dis_msg(curbuf->b_xfilename, FALSE);
  1529. X    }
  1530. X
  1531. X    msg_end();
  1532. X}
  1533. X
  1534. X/*
  1535. X * display a string for dodis()
  1536. X * truncate at end of screen line
  1537. X */
  1538. X    void
  1539. Xdis_msg(p, skip_esc)
  1540. X    char_u        *p;
  1541. X    int            skip_esc;            /* if TRUE, ignore trailing ESC */
  1542. X{
  1543. X    int        n;
  1544. X
  1545. X    n = (int)Columns - 6;
  1546. X    while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
  1547. X                        (n -= charsize(*p)) >= 0)
  1548. X        msg_outtrans(p++, 1);
  1549. X}
  1550. X
  1551. X/*
  1552. X * join 'count' lines (minimal 2), including u_save()
  1553. X */
  1554. X    void
  1555. Xdodojoin(count, insert_space, redraw)
  1556. X    long    count;
  1557. X    int        insert_space;
  1558. X    int        redraw;
  1559. X{
  1560. X    if (!u_save((linenr_t)(curwin->w_cursor.lnum - 1), (linenr_t)(curwin->w_cursor.lnum + count)))
  1561. X        return;
  1562. X
  1563. X    while (--count > 0)
  1564. X        if (dojoin(insert_space, redraw) == FAIL)
  1565. X        {
  1566. X                beep();
  1567. X                break;
  1568. X        }
  1569. X
  1570. X    if (redraw)
  1571. X        updateScreen(VALID_TO_CURSCHAR);
  1572. X}
  1573. X
  1574. X/*
  1575. X * join two lines at the cursor position
  1576. X *
  1577. X * return FAIL for failure, OK ohterwise
  1578. X */
  1579. X    int
  1580. Xdojoin(insert_space, redraw)
  1581. X    int            insert_space;
  1582. X    int            redraw;
  1583. X{
  1584. X    char_u        *curr;
  1585. X    char_u        *next;
  1586. X    char_u        *new;
  1587. X    int            endcurr1, endcurr2;
  1588. X    int         currsize;        /* size of the current line */
  1589. X    int         nextsize;        /* size of the next line */
  1590. X    int            spaces;            /* number of spaces to insert */
  1591. X    int            rows_to_del;    /* number of rows on screen to delete */
  1592. X    linenr_t    t;
  1593. X
  1594. X    if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)        /* on last line */
  1595. X        return FAIL;
  1596. X
  1597. X    rows_to_del = plines_m(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1);
  1598. X
  1599. X    curr = ml_get(curwin->w_cursor.lnum);
  1600. X    currsize = STRLEN(curr);
  1601. X    endcurr1 = endcurr2 = NUL;
  1602. X    if (currsize > 0)
  1603. X    {
  1604. X        endcurr1 = *(curr + currsize - 1);
  1605. X        if (currsize > 1)
  1606. X            endcurr2 = *(curr + currsize - 2);
  1607. X    }
  1608. X
  1609. X    next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
  1610. X    spaces = 0;
  1611. X    if (insert_space)
  1612. X    {
  1613. X        skipspace(&next);
  1614. X        spaces = 1;
  1615. X        if (*next == ')' || currsize == 0)
  1616. X            spaces = 0;
  1617. X        else
  1618. X        {
  1619. X            if (endcurr1 == ' ' || endcurr1 == TAB)
  1620. X            {
  1621. X                spaces = 0;
  1622. X                if (currsize > 1)
  1623. X                    endcurr1 = endcurr2;
  1624. X            }
  1625. X            if (p_js && strchr(".!?", endcurr1) != NULL)
  1626. X                spaces = 2;
  1627. X        }
  1628. X    }
  1629. X    nextsize = STRLEN(next);
  1630. X
  1631. X    new = alloc((unsigned)(currsize + nextsize + spaces + 1));
  1632. X    if (new == NULL)
  1633. X        return FAIL;
  1634. X
  1635. X    /*
  1636. X     * Insert the next line first, because we already have that pointer.
  1637. X     * Curr has to be obtained again, because getting next will have
  1638. X     * invalidated it.
  1639. X     */
  1640. X    memmove((char *)new + currsize + spaces, (char *)next, (size_t)(nextsize + 1));
  1641. X
  1642. X    curr = ml_get(curwin->w_cursor.lnum);
  1643. X    memmove((char *)new, (char *)curr, (size_t)currsize);
  1644. X
  1645. X    copy_spaces(new + currsize, (size_t)spaces);
  1646. X
  1647. X    ml_replace(curwin->w_cursor.lnum, new, FALSE);
  1648. X
  1649. X    /*
  1650. X     * Delete the following line. To do this we move the cursor there
  1651. X     * briefly, and then move it back. After dellines() the cursor may
  1652. X     * have moved up (last line deleted), so the current lnum is kept in t.
  1653. X     */
  1654. X    t = curwin->w_cursor.lnum;
  1655. X    ++curwin->w_cursor.lnum;
  1656. X    dellines(1L, FALSE, FALSE);
  1657. X    curwin->w_cursor.lnum = t;
  1658. X
  1659. X    /*
  1660. X     * the number of rows on the screen is reduced by the difference
  1661. X     * in number of rows of the two old lines and the one new line
  1662. X     */
  1663. X    if (redraw)
  1664. X    {
  1665. X        rows_to_del -= plines(curwin->w_cursor.lnum);
  1666. X        if (rows_to_del > 0)
  1667. X            win_del_lines(curwin, curwin->w_row, rows_to_del, TRUE, TRUE);
  1668. X    }
  1669. X
  1670. X     /*
  1671. X     * go to first character of the joined line
  1672. X     */
  1673. X    if (currsize == 0)
  1674. X        curwin->w_cursor.col = 0;
  1675. X    else
  1676. X    {
  1677. X        curwin->w_cursor.col = currsize - 1;
  1678. X        (void)oneright();
  1679. X    }
  1680. X    CHANGED;
  1681. X
  1682. X    return OK;
  1683. X}
  1684. X
  1685. X/*
  1686. X * implementation of the format operator 'Q'
  1687. X */
  1688. X    void
  1689. Xdoformat()
  1690. X{
  1691. X        /* prepare undo and join the lines */
  1692. X    dodojoin((long)nlines, TRUE, FALSE);
  1693. X
  1694. X        /* put cursor on last non-space */
  1695. X    coladvance(MAXCOL);
  1696. X    while (curwin->w_cursor.col && isspace(gchar_cursor()))
  1697. X        dec_cursor();
  1698. X    curs_columns(FALSE);            /* update curwin->w_virtcol */
  1699. X
  1700. X        /* do the formatting */
  1701. X    State = INSERT;        /* for Opencmd() */
  1702. X    insertchar(NUL);
  1703. X    State = NORMAL;
  1704. X    updateScreen(NOT_VALID);
  1705. X}
  1706. X
  1707. X    void
  1708. Xstartinsert(initstr, startln, count)
  1709. X    int            initstr;
  1710. X    int         startln;        /* if set, insert at start of line */
  1711. X    long         count;
  1712. X{
  1713. X    Insstart = curwin->w_cursor;
  1714. X    if (startln)
  1715. X        Insstart.col = 0;
  1716. X
  1717. X    if (initstr != NUL)
  1718. X    {
  1719. X            ResetRedobuff();
  1720. X            AppendNumberToRedobuff(count);
  1721. X            AppendCharToRedobuff(initstr);
  1722. X    }
  1723. X
  1724. X    if (initstr == 'R')
  1725. X        State = REPLACE;
  1726. X    else
  1727. X        State = INSERT;
  1728. X
  1729. X    if (p_smd)
  1730. X        showmode();
  1731. X
  1732. X    change_warning();        /* give a warning if readonly */
  1733. X    edit(count);
  1734. X}
  1735. X
  1736. X/*
  1737. X * prepare a few things for block mode yank/delete/tilde
  1738. X *
  1739. X * for delete:
  1740. X * - textlen includes the first/last char to be (partly) deleted
  1741. X * - start/endspaces is the number of columns that are taken by the
  1742. X *     first/last deleted char minus the number of columns that have to be deleted.
  1743. X * for yank and tilde:
  1744. X * - textlen includes the first/last char to be wholly yanked
  1745. X * - start/endspaces is the number of columns of the first/last yanked char
  1746. X *   that are to be yanked.
  1747. X */
  1748. X    static void
  1749. Xblock_prep(lnum, delete)
  1750. X    linenr_t    lnum;
  1751. X    int            delete;
  1752. X{
  1753. X    int            vcol;
  1754. X    int            incr = 0;
  1755. X    char_u        *pend;
  1756. X
  1757. X    startspaces = 0;
  1758. X    endspaces = 0;
  1759. X    textlen = 0;
  1760. X    textcol = 0;
  1761. X    vcol = 0;
  1762. X    textstart = ml_get(lnum);
  1763. X    while (vcol < startvcol && *textstart)
  1764. X    {
  1765. X        /* Count a tab for what it's worth (if list mode not on) */
  1766. X        incr = chartabsize(*textstart, (long)vcol);
  1767. X        vcol += incr;
  1768. X        ++textstart;
  1769. X        ++textcol;
  1770. X    }
  1771. X    if (vcol < startvcol)    /* line too short */
  1772. X    {
  1773. X        if (!delete)
  1774. X            endspaces = endvcol - startvcol + 1;
  1775. X    }
  1776. X    else /* vcol >= startvcol */
  1777. X    {
  1778. X        startspaces = vcol - startvcol;
  1779. X        if (delete && vcol > startvcol)
  1780. X            startspaces = incr - startspaces;
  1781. X        pend = textstart;
  1782. X        if (vcol > endvcol)        /* it's all in one character */
  1783. X        {
  1784. X            startspaces = endvcol - startvcol + 1;
  1785. X            if (delete)
  1786. X                startspaces = incr - startspaces;
  1787. X        }
  1788. X        else
  1789. X        {
  1790. X            while (vcol <= endvcol && *pend)
  1791. X            {
  1792. X                /* Count a tab for what it's worth (if list mode not on) */
  1793. X                incr = chartabsize(*pend, (long)vcol);
  1794. X                vcol += incr;
  1795. X                ++pend;
  1796. X            }
  1797. X            if (vcol < endvcol && !delete)    /* line too short */
  1798. X            {
  1799. X                endspaces = endvcol - vcol;
  1800. X            }
  1801. X            else if (vcol > endvcol)
  1802. X            {
  1803. X                endspaces = vcol - endvcol - 1;
  1804. X                if (!delete && pend != textstart && endspaces)
  1805. X                    --pend;
  1806. X            }
  1807. X        }
  1808. X        if (delete && startspaces)
  1809. X        {
  1810. X            --textstart;
  1811. X            --textcol;
  1812. X        }
  1813. X        textlen = (int)(pend - textstart);
  1814. X    }
  1815. X}
  1816. X
  1817. X#define NUMBUFLEN 30
  1818. X
  1819. X/*
  1820. X * add or subtract 'Prenum1' from a number in a line
  1821. X * 'command' is CTRL-A for add, CTRL-X for subtract
  1822. X *
  1823. X * return FAIL for failure, OK otherwise
  1824. X */
  1825. X    int
  1826. Xdoaddsub(command, Prenum1)
  1827. X    int            command;
  1828. X    linenr_t    Prenum1;
  1829. X{
  1830. X    register int     col;
  1831. X    char_u            buf[NUMBUFLEN];
  1832. X    int                hex;        /* 'x' or 'X': hexadecimal; '0': octal */
  1833. X    static int        hexupper = FALSE;    /* 0xABC */
  1834. X    long            n;
  1835. X    char_u            *ptr;
  1836. X    int                i;
  1837. X    int                c;
  1838. X
  1839. X    ptr = ml_get(curwin->w_cursor.lnum);
  1840. X    col = curwin->w_cursor.col;
  1841. X
  1842. X        /* first check if we are on a hexadecimal number */
  1843. X    while (col > 0 && isxdigit(ptr[col]))
  1844. X        --col;
  1845. X    if (col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') &&
  1846. X                        ptr[col - 1] == '0' && isxdigit(ptr[col + 1]))
  1847. X        --col;        /* found hexadecimal number */
  1848. X    else
  1849. X    {
  1850. X        /* first search forward and then backward for start of number */
  1851. X        col = curwin->w_cursor.col;
  1852. X
  1853. X        while (ptr[col] != NUL && !isdigit(ptr[col]))
  1854. X            ++col;
  1855. X
  1856. X        while (col > 0 && isdigit(ptr[col - 1]))
  1857. X            --col;
  1858. X    }
  1859. X
  1860. X    if (isdigit(ptr[col]) && u_save_cursor())
  1861. X    {
  1862. X        ptr = ml_get(curwin->w_cursor.lnum);    /* get it again, because of undo */
  1863. X        curwin->w_set_curswant = TRUE;
  1864. X
  1865. X        hex = 0;                                /* default is decimal */
  1866. X        if (ptr[col] == '0')                    /* could be hex or octal */
  1867. X        {
  1868. X            hex = TO_UPPER(ptr[col + 1]);        /* assume hexadecimal */
  1869. X            if (hex != 'X' || !isxdigit(ptr[col + 2]))
  1870. X            {
  1871. X                if (isdigit(hex))
  1872. X                    hex = '0';                    /* octal */
  1873. X                else
  1874. X                    hex = 0;                    /* 0 by itself is decimal */
  1875. X            }
  1876. X        }
  1877. X
  1878. X        if (!hex && col > 0 && ptr[col - 1] == '-')
  1879. X            --col;
  1880. X
  1881. X        ptr += col;
  1882. X        /*
  1883. X         * we copy the number into a buffer because some versions of sscanf
  1884. X         * cannot handle characters with the upper bit set, making some special
  1885. X         * characters handled like digits.
  1886. X         */
  1887. X        for (i = 0; *ptr && !(*ptr & 0x80) && i < NUMBUFLEN - 1; ++i)
  1888. X            buf[i] = *ptr++;
  1889. X        buf[i] = NUL;
  1890. X
  1891. X        if (hex == '0')
  1892. X            sscanf((char *)buf, "%lo", &n);
  1893. X        else if (hex)
  1894. X            sscanf((char *)buf + 2, "%lx", &n);    /* "%X" doesn't work! */
  1895. X        else
  1896. X            n = atol((char *)buf);
  1897. X
  1898. X        if (command == Ctrl('A'))
  1899. X            n += Prenum1;
  1900. X        else
  1901. X            n -= Prenum1;
  1902. X
  1903. X        if (hex == 'X')                    /* skip the '0x' */
  1904. X            col += 2;
  1905. X        curwin->w_cursor.col = col;
  1906. X        c = gchar_cursor();
  1907. X        do                                /* delete the old number */
  1908. X        {
  1909. X            if (isalpha(c))
  1910. X            {
  1911. X                if (isupper(c))
  1912. X                    hexupper = TRUE;
  1913. X                else
  1914. X                    hexupper = FALSE;
  1915. X            }
  1916. X            (void)delchar(FALSE);
  1917. X            c = gchar_cursor();
  1918. X        }
  1919. X        while (hex ? (hex == '0' ? c >= '0' && c <= '7' : isxdigit(c)) : isdigit(c));
  1920. X
  1921. X        if (hex == '0')
  1922. X            sprintf((char *)buf, "0%lo", n);
  1923. X        else if (hex && hexupper)
  1924. X            sprintf((char *)buf, "%lX", n);
  1925. X        else if (hex)
  1926. X            sprintf((char *)buf, "%lx", n);
  1927. X        else
  1928. X            sprintf((char *)buf, "%ld", n);
  1929. X        insstr(buf);                    /* insert the new number */
  1930. X        --curwin->w_cursor.col;
  1931. X        updateline();
  1932. X        return OK;
  1933. X    }
  1934. X    else
  1935. X    {
  1936. X        beep();
  1937. X        return FAIL;
  1938. X    }
  1939. X}
  1940. END_OF_FILE
  1941.   if test 39495 -ne `wc -c <'vim/src/ops.c'`; then
  1942.     echo shar: \"'vim/src/ops.c'\" unpacked with wrong size!
  1943.   fi
  1944.   # end of 'vim/src/ops.c'
  1945. fi
  1946. if test -f 'vim/src/proto/normal.pro' -a "${1}" != "-c" ; then 
  1947.   echo shar: Will not clobber existing file \"'vim/src/proto/normal.pro'\"
  1948. else
  1949.   echo shar: Extracting \"'vim/src/proto/normal.pro'\" \(44 characters\)
  1950.   sed "s/^X//" >'vim/src/proto/normal.pro' <<'END_OF_FILE'
  1951. X/* normal.c */
  1952. Xvoid normal __PARMS((void));
  1953. END_OF_FILE
  1954.   if test 44 -ne `wc -c <'vim/src/proto/normal.pro'`; then
  1955.     echo shar: \"'vim/src/proto/normal.pro'\" unpacked with wrong size!
  1956.   fi
  1957.   # end of 'vim/src/proto/normal.pro'
  1958. fi
  1959. if test -f 'vim/src/term.c' -a "${1}" != "-c" ; then 
  1960.   echo shar: Will not clobber existing file \"'vim/src/term.c'\"
  1961. else
  1962.   echo shar: Extracting \"'vim/src/term.c'\" \(19580 characters\)
  1963.   sed "s/^X//" >'vim/src/term.c' <<'END_OF_FILE'
  1964. X/* vi:ts=4:sw=4
  1965. X *
  1966. X * VIM - Vi IMproved        by Bram Moolenaar
  1967. X *
  1968. X * Read the file "credits.txt" for a list of people who contributed.
  1969. X * Read the file "uganda.txt" for copying and usage conditions.
  1970. X */
  1971. X/*
  1972. X *
  1973. X * term.c: functions for controlling the terminal
  1974. X *
  1975. X * primitive termcap support for Amiga and MSDOS included
  1976. X *
  1977. X * NOTE: padding and variable substitution is not performed,
  1978. X * when compiling without TERMCAP, we use tputs() and tgoto() dummies.
  1979. X */
  1980. X
  1981. X#include "vim.h"
  1982. X#include "globals.h"
  1983. X#include "param.h"
  1984. X#include "proto.h"
  1985. X#ifdef TERMCAP
  1986. X# ifdef linux
  1987. X#  include <termcap.h>
  1988. X#  if 0        /* only required for old versions, it's now in termcap.h */
  1989. X    typedef int (*outfuntype) (int);
  1990. X#  endif
  1991. X#  define TPUTSFUNCAST (outfuntype)
  1992. X# else
  1993. X#  define TPUTSFUNCAST
  1994. X#  ifdef AMIGA
  1995. X#   include "proto/termlib.pro"
  1996. X#  endif
  1997. X# endif
  1998. X#endif
  1999. X
  2000. Xstatic void parse_builtin_tcap __ARGS((Tcarr *tc, char_u *s));
  2001. X
  2002. X/*
  2003. X * Builtin_tcaps must always contain DFLT_TCAP as the first entry!
  2004. X * DFLT_TCAP is used, when no terminal is specified with -T option or $TERM.
  2005. X * The entries are compact, therefore they normally are included even when
  2006. X * TERMCAP is defined.
  2007. X * When TERMCAP is defined, the builtin entries can be accessed with
  2008. X * "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
  2009. X */
  2010. Xstatic char_u *builtin_tcaps[] =
  2011. X{
  2012. X#ifndef NO_BUILTIN_TCAPS
  2013. X  (char_u *)DFLT_TCAP,        /* almost allways included */
  2014. X# if !defined(UNIX) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  2015. X  (char_u *)ANSI_TCAP,        /* default for unix */
  2016. X# endif
  2017. X# if !defined(AMIGA) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  2018. X  (char_u *)AMIGA_TCAP,        /* default for amiga */
  2019. X# endif
  2020. X# if !defined(MSDOS) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  2021. X  (char_u *)PCTERM_TCAP,        /* default for MSdos */
  2022. X# endif
  2023. X# if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS)
  2024. X  (char_u *)PCANSI_TCAP,
  2025. X# endif
  2026. X# if !defined(ATARI) && defined(ALL_BUILTIN_TCAPS)
  2027. X  (char_u *)ATARI_TCAP,        /* default for Atari */
  2028. X# endif
  2029. X# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
  2030. X  (char_u *)XTERM_TCAP,        /* always included on unix */
  2031. X# endif
  2032. X# ifdef ALL_BUILTIN_TCAPS
  2033. X  (char_u *)VT52_TCAP,
  2034. X# endif
  2035. X# if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
  2036. X  (char_u *)DEBUG_TCAP,        /* always included when debugging */
  2037. X# endif
  2038. X#else /* NO_BUILTIN_TCAPS */
  2039. X  (char_u *)DUMB_TCAP,        /* minimal termcap, used when everything else fails */
  2040. X#endif /* NO_BUILTIN_TCAPS */
  2041. X  NULL,
  2042. X};
  2043. X
  2044. X/*
  2045. X * Term_strings contains currently used terminal strings.
  2046. X * It is initialized with the default values by parse_builtin_tcap().
  2047. X * The values can be changed by setting the parameter with the same name.
  2048. X */
  2049. XTcarr term_strings;
  2050. X
  2051. X/*
  2052. X * Parsing of the builtin termcap entries.
  2053. X * The terminal's name is not set, as this is already done in termcapinit().
  2054. X * Chop builtin termcaps, string entries are already '\0' terminated.
  2055. X * not yet implemented:
  2056. X *   boolean entries could be empty strings;
  2057. X *   numeric entries would need a flag (e.g. high bit of the skip byte),
  2058. X *   so that parse_builtin_tcap can handle them.
  2059. X */
  2060. X    static void
  2061. Xparse_builtin_tcap(tc, s)
  2062. X    Tcarr *tc;
  2063. X    char_u *s;
  2064. X{
  2065. X    char_u **p = &tc->t_name;
  2066. X
  2067. X    p++;
  2068. X    for (;;)
  2069. X    {
  2070. X        while (*s++)
  2071. X            ;
  2072. X        p += *s++;
  2073. X        if (!*s)
  2074. X            return;
  2075. X        *p++ = s;
  2076. X    }
  2077. X}
  2078. X
  2079. X#ifdef TERMCAP
  2080. X# ifndef linux        /* included in <termlib.h> */
  2081. X#  ifndef AMIGA        /* included in proto/termlib.pro */
  2082. Xint                tgetent();
  2083. Xint                tgetnum();
  2084. Xchar            *tgetstr();
  2085. Xint                tgetflag();
  2086. Xint                tputs();
  2087. X#  endif /* AMIGA */
  2088. X#  ifndef hpux
  2089. Xextern short    ospeed;
  2090. X#  endif
  2091. X# endif /* linux */
  2092. X# ifndef hpux
  2093. Xchar        *UP, *BC, PC;        /* should be extern, but some don't have them */
  2094. X# endif
  2095. X#endif /* TERMCAP */
  2096. X
  2097. X#ifdef linux
  2098. X# define TGETSTR(s, p)    (char_u *)tgetstr((s), (char **)(p))
  2099. X#else
  2100. X# define TGETSTR(s, p)    (char_u *)tgetstr((s), (char *)(p))
  2101. X#endif
  2102. X
  2103. X    void
  2104. Xset_term(term)
  2105. X    char_u *term;
  2106. X{
  2107. X    char_u **p = builtin_tcaps;
  2108. X#ifdef TERMCAP
  2109. X    int builtin = 0;
  2110. X#endif
  2111. X    int width = 0, height = 0;
  2112. X
  2113. X    if (!STRNCMP(term, "builtin_", (size_t)8))
  2114. X    {
  2115. X        term += 8;
  2116. X#ifdef TERMCAP
  2117. X        builtin = 1;
  2118. X#endif
  2119. X    }
  2120. X#ifdef TERMCAP
  2121. X    else
  2122. X    {
  2123. X        char_u            *p;
  2124. X        static char_u    tstrbuf[TBUFSZ];
  2125. X        char_u            tbuf[TBUFSZ];
  2126. X        char_u            *tp = tstrbuf;
  2127. X        int                i;
  2128. X
  2129. X        i = tgetent(tbuf, term);
  2130. X        if (i == -1)
  2131. X        {
  2132. X            EMSG("Cannot open termcap file");
  2133. X            builtin = 1;
  2134. X        }
  2135. X        else if (i == 0)
  2136. X        {
  2137. X            EMSG("terminal entry not found");
  2138. X            builtin = 1;
  2139. X        }
  2140. X        else
  2141. X        {
  2142. X            clear_termparam();        /* clear old parameters */
  2143. X        /* output strings */
  2144. X            T_EL = TGETSTR("ce", &tp);
  2145. X            T_IL = TGETSTR("al", &tp);
  2146. X            T_CIL = TGETSTR("AL", &tp);
  2147. X            T_DL = TGETSTR("dl", &tp);
  2148. X            T_CDL = TGETSTR("DL", &tp);
  2149. X            T_CS = TGETSTR("cs", &tp);
  2150. X            T_ED = TGETSTR("cl", &tp);
  2151. X            T_CI = TGETSTR("vi", &tp);
  2152. X            T_CV = TGETSTR("ve", &tp);
  2153. X            T_CVV = TGETSTR("vs", &tp);
  2154. X            T_TP = TGETSTR("me", &tp);
  2155. X            T_TI = TGETSTR("mr", &tp);
  2156. X            T_TB = TGETSTR("md", &tp);
  2157. X            T_SE = TGETSTR("se", &tp);
  2158. X            T_SO = TGETSTR("so", &tp);
  2159. X            T_CM = TGETSTR("cm", &tp);
  2160. X            T_SR = TGETSTR("sr", &tp);
  2161. X            T_CRI = TGETSTR("RI", &tp);
  2162. X            T_VB = TGETSTR("vb", &tp);
  2163. X            T_KS = TGETSTR("ks", &tp);
  2164. X            T_KE = TGETSTR("ke", &tp);
  2165. X            T_TS = TGETSTR("ti", &tp);
  2166. X            T_TE = TGETSTR("te", &tp);
  2167. X
  2168. X        /* key codes */
  2169. X            term_strings.t_ku = TGETSTR("ku", &tp);
  2170. X            term_strings.t_kd = TGETSTR("kd", &tp);
  2171. X            term_strings.t_kl = TGETSTR("kl", &tp);
  2172. X                /* if cursor-left == backspace, ignore it (televideo 925) */
  2173. X            if (term_strings.t_kl != NULL && *term_strings.t_kl == Ctrl('H'))
  2174. X                term_strings.t_kl = NULL;
  2175. X            term_strings.t_kr = TGETSTR("kr", &tp);
  2176. X            /* term_strings.t_sku = TGETSTR("", &tp); termcap code unknown */
  2177. X            /* term_strings.t_skd = TGETSTR("", &tp); termcap code unknown */
  2178. X#ifdef ARCHIE
  2179. X            /* Termcap code made up! */
  2180. X            term_strings.t_sku = tgetstr("su", &tp);
  2181. X            term_strings.t_skd = tgetstr("sd", &tp);
  2182. X#else
  2183. X            term_strings.t_sku = NULL;
  2184. X            term_strings.t_skd = NULL;
  2185. X#endif
  2186. X            term_strings.t_skl = TGETSTR("#4", &tp);
  2187. X            term_strings.t_skr = TGETSTR("%i", &tp);
  2188. X            term_strings.t_f1 = TGETSTR("k1", &tp);
  2189. X            term_strings.t_f2 = TGETSTR("k2", &tp);
  2190. X            term_strings.t_f3 = TGETSTR("k3", &tp);
  2191. X            term_strings.t_f4 = TGETSTR("k4", &tp);
  2192. X            term_strings.t_f5 = TGETSTR("k5", &tp);
  2193. X            term_strings.t_f6 = TGETSTR("k6", &tp);
  2194. X            term_strings.t_f7 = TGETSTR("k7", &tp);
  2195. X            term_strings.t_f8 = TGETSTR("k8", &tp);
  2196. X            term_strings.t_f9 = TGETSTR("k9", &tp);
  2197. X            term_strings.t_f10 = TGETSTR("k;", &tp);
  2198. X            term_strings.t_sf1 = TGETSTR("F1", &tp);    /* really function keys 11-20 */
  2199. X            term_strings.t_sf2 = TGETSTR("F2", &tp);
  2200. X            term_strings.t_sf3 = TGETSTR("F3", &tp);
  2201. X            term_strings.t_sf4 = TGETSTR("F4", &tp);
  2202. X            term_strings.t_sf5 = TGETSTR("F5", &tp);
  2203. X            term_strings.t_sf6 = TGETSTR("F6", &tp);
  2204. X            term_strings.t_sf7 = TGETSTR("F7", &tp);
  2205. X            term_strings.t_sf8 = TGETSTR("F8", &tp);
  2206. X            term_strings.t_sf9 = TGETSTR("F9", &tp);
  2207. X            term_strings.t_sf10 = TGETSTR("FA", &tp);
  2208. X            term_strings.t_help = TGETSTR("%1", &tp);
  2209. X            term_strings.t_undo = TGETSTR("&8", &tp);
  2210. X
  2211. X            height = tgetnum("li");
  2212. X            width = tgetnum("co");
  2213. X
  2214. X            T_MS = tgetflag("ms") ? (char_u *)"yes" : (char_u *)NULL;
  2215. X
  2216. X# ifndef hpux
  2217. X            BC = (char *)TGETSTR("bc", &tp);
  2218. X            UP = (char *)TGETSTR("up", &tp);
  2219. X            p = TGETSTR("pc", &tp);
  2220. X            if (p)
  2221. X                PC = *p;
  2222. X            ospeed = 0;
  2223. X# endif
  2224. X        }
  2225. X    }
  2226. X    if (builtin)
  2227. X#endif
  2228. X    {
  2229. X        while (*p && STRCMP(term, *p))
  2230. X            p++;
  2231. X        if (!*p)
  2232. X        {
  2233. X            fprintf(stderr, "'%s' not builtin. Available terminals are:\r\n", term);
  2234. X            for (p = builtin_tcaps; *p; p++)
  2235. X#ifdef TERMCAP
  2236. X                fprintf(stderr, "\tbuiltin_%s\r\n", *p);
  2237. X#else
  2238. X                fprintf(stderr, "\t%s\r\n", *p);
  2239. X#endif
  2240. X            if (!starting)        /* when user typed :set term=xxx, quit here */
  2241. X            {
  2242. X                wait_return(TRUE);
  2243. X                return;
  2244. X            }
  2245. X            sleep(2);
  2246. X            fprintf(stderr, "defaulting to '%s'\r\n", *builtin_tcaps);
  2247. X            sleep(2);
  2248. X            p = builtin_tcaps;
  2249. X            free(term_strings.t_name);
  2250. X            term_strings.t_name = strsave(term = *p);
  2251. X        }
  2252. X        clear_termparam();        /* clear old parameters */
  2253. X        parse_builtin_tcap(&term_strings, *p);
  2254. X    }
  2255. X/*
  2256. X * special: There is no info in the termcap about whether the cursor positioning
  2257. X * is relative to the start of the screen or to the start of the scrolling region.
  2258. X * We just guess here. Only msdos pcterm is known to do it relative.
  2259. X */
  2260. X    if (STRCMP(term, "pcterm") == 0)
  2261. X        T_CSC = (char_u *)"yes";
  2262. X    else
  2263. X        T_CSC = NULL;
  2264. X
  2265. X#if defined(AMIGA) || defined(MSDOS)
  2266. X        /* DFLT_TCAP indicates that it is the machine console. */
  2267. X    if (STRCMP(term, *builtin_tcaps))
  2268. X        term_console = FALSE;
  2269. X    else
  2270. X    {
  2271. X        term_console = TRUE;
  2272. X# ifdef AMIGA
  2273. X        win_resize_on();        /* enable window resizing reports */
  2274. X# endif
  2275. X    }
  2276. X#endif
  2277. X    ttest(TRUE);
  2278. X        /* display initial screen after ttest() checking. jw. */
  2279. X    if (width <= 0 || height <= 0)
  2280. X    {
  2281. X        /* termcap failed to report size */
  2282. X        /* set defaults, in case mch_get_winsize also fails */
  2283. X        width = 80;
  2284. X#ifdef MSDOS
  2285. X        height = 25;        /* console is often 25 lines */
  2286. X#else
  2287. X        height = 24;        /* most terminals are 24 lines */
  2288. X#endif
  2289. X    }
  2290. X    set_winsize(width, height, FALSE);    /* may change Rows */
  2291. X}
  2292. X
  2293. X#if defined(TERMCAP) && defined(UNIX)
  2294. X/*
  2295. X * Get Columns and Rows from the termcap. Used after a window signal if the
  2296. X * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
  2297. X * and "li" entries never change. But this may happen on some systems.
  2298. X */
  2299. X    void
  2300. Xgetlinecol()
  2301. X{
  2302. X    char_u            tbuf[TBUFSZ];
  2303. X
  2304. X    if (term_strings.t_name != NULL && tgetent(tbuf, term_strings.t_name) > 0)
  2305. X    {
  2306. X        if (Columns == 0)
  2307. X            Columns = tgetnum("co");
  2308. X        if (Rows == 0)
  2309. X            Rows = tgetnum("li");
  2310. X    }
  2311. X}
  2312. X#endif
  2313. X
  2314. Xstatic char_u *tltoa __PARMS((unsigned long));
  2315. X
  2316. X    static char_u *
  2317. Xtltoa(i)
  2318. X    unsigned long i;
  2319. X{
  2320. X    static char_u buf[16];
  2321. X    char_u        *p;
  2322. X
  2323. X    p = buf + 15;
  2324. X    *p = '\0';
  2325. X    do
  2326. X    {
  2327. X        --p;
  2328. X        *p = i % 10 + '0';
  2329. X        i /= 10;
  2330. X    }
  2331. X    while (i > 0 && p > buf);
  2332. X    return p;
  2333. X}
  2334. X
  2335. X#ifndef TERMCAP
  2336. X
  2337. X/*
  2338. X * minimal tgoto() implementation.
  2339. X * no padding and we only parse for %i %d and %+char
  2340. X */
  2341. X
  2342. X    char *
  2343. Xtgoto(cm, x, y)
  2344. X    char *cm;
  2345. X    int x, y;
  2346. X{
  2347. X    static char buf[30];
  2348. X    char *p, *s, *e;
  2349. X
  2350. X    if (!cm)
  2351. X        return "OOPS";
  2352. X    e = buf + 29;
  2353. X    for (s = buf; s < e && *cm; cm++)
  2354. X    {
  2355. X        if (*cm != '%')
  2356. X        {
  2357. X            *s++ = *cm;
  2358. X            continue;
  2359. X        }
  2360. X        switch (*++cm)
  2361. X        {
  2362. X        case 'd':
  2363. X            p = (char *)tltoa((unsigned long)y);
  2364. X            y = x;
  2365. X            while (*p)
  2366. X                *s++ = *p++;
  2367. X            break;
  2368. X        case 'i':
  2369. X            x++;
  2370. X            y++;
  2371. X            break;
  2372. X        case '+':
  2373. X            *s++ = (char)(*++cm + y);
  2374. X            y = x;
  2375. X            break;
  2376. X        case '%':
  2377. X            *s++ = *cm;
  2378. X            break;
  2379. X        default:
  2380. X            return "OOPS";
  2381. X        }
  2382. X    }
  2383. X    *s = '\0';
  2384. X    return buf;
  2385. X}
  2386. X
  2387. X#endif /* TERMCAP */
  2388. X
  2389. X/*
  2390. X * Termcapinit is called from main() to initialize the terminal.
  2391. X * The optional argument is given with the -T command line option.
  2392. X */
  2393. X    void
  2394. Xtermcapinit(term)
  2395. X    char_u *term;
  2396. X{
  2397. X    if (!term)
  2398. X        term = vimgetenv((char_u *)"TERM");
  2399. X    if (!term || !*term)
  2400. X        term = *builtin_tcaps;
  2401. X    term_strings.t_name = strsave(term);
  2402. X    set_term(term);
  2403. X}
  2404. X
  2405. X/*
  2406. X * the number of calls to mch_write is reduced by using the buffer "outbuf"
  2407. X */
  2408. X#undef BSIZE            /* hpux has BSIZE in sys/param.h */
  2409. X#define BSIZE    2048
  2410. Xstatic char_u            outbuf[BSIZE];
  2411. Xstatic int                bpos = 0;        /* number of chars in outbuf */
  2412. X
  2413. X/*
  2414. X * flushbuf(): flush the output buffer
  2415. X */
  2416. X    void
  2417. Xflushbuf()
  2418. X{
  2419. X    if (bpos != 0)
  2420. X    {
  2421. X        mch_write(outbuf, bpos);
  2422. X        bpos = 0;
  2423. X    }
  2424. X}
  2425. X
  2426. X/*
  2427. X * outchar(c): put a character into the output buffer.
  2428. X *               Flush it if it becomes full.
  2429. X */
  2430. X    void
  2431. Xoutchar(c)
  2432. X    unsigned    c;
  2433. X{
  2434. X#ifdef UNIX
  2435. X    if (c == '\n')        /* turn LF into CR-LF (CRMOD does not seem to do this) */
  2436. X        outchar('\r');
  2437. X#endif
  2438. X
  2439. X    outbuf[bpos] = c;
  2440. X
  2441. X    if (p_nb)            /* for testing: unbuffered screen output (not for MSDOS) */
  2442. X        mch_write(outbuf, 1);
  2443. X    else
  2444. X        ++bpos;
  2445. X
  2446. X    if (bpos >= BSIZE)
  2447. X        flushbuf();
  2448. X}
  2449. X
  2450. X/*
  2451. X * a never-padding outstr.
  2452. X * use this whenever you don't want to run the string through tputs.
  2453. X * tputs above is harmless, but tputs from the termcap library 
  2454. X * is likely to strip off leading digits, that it mistakes for padding
  2455. X * information. (jw)
  2456. X */
  2457. X    void
  2458. Xoutstrn(s)
  2459. X    char_u *s;
  2460. X{
  2461. X    if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  2462. X        flushbuf();
  2463. X    while (*s)
  2464. X        outchar(*s++);
  2465. X}
  2466. X
  2467. X/*
  2468. X * outstr(s): put a string character at a time into the output buffer.
  2469. X * If TERMCAP is defined use the termcap parser. (jw)
  2470. X */
  2471. X    void
  2472. Xoutstr(s)
  2473. X    register char_u             *s;
  2474. X{
  2475. X    if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  2476. X        flushbuf();
  2477. X    if (s)
  2478. X#ifdef TERMCAP
  2479. X        tputs(s, 1, TPUTSFUNCAST outchar);
  2480. X#else
  2481. X        while (*s)
  2482. X            outchar(*s++);
  2483. X#endif
  2484. X}
  2485. X
  2486. X/* 
  2487. X * cursor positioning using termcap parser. (jw)
  2488. X */
  2489. X    void
  2490. Xwindgoto(row, col)
  2491. X    int        row;
  2492. X    int        col;
  2493. X{
  2494. X    OUTSTR(tgoto((char *)T_CM, col, row));
  2495. X}
  2496. X
  2497. X/*
  2498. X * Set cursor to current position.
  2499. X * Should be optimized for minimal terminal output.
  2500. X */
  2501. X
  2502. X    void
  2503. Xsetcursor()
  2504. X{
  2505. X    if (!RedrawingDisabled)
  2506. X        windgoto(curwin->w_winpos + curwin->w_row, curwin->w_col);
  2507. X}
  2508. X
  2509. X    void
  2510. Xttest(pairs)
  2511. X    int    pairs;
  2512. X{
  2513. X    char buf[70];
  2514. X    char *s = "terminal capability %s required.\n";
  2515. X    char *t = NULL;
  2516. X
  2517. X  /* hard requirements */
  2518. X    if (!T_ED || !*T_ED)    /* erase display */
  2519. X        t = "cl";
  2520. X    if (!T_CM || !*T_CM)    /* cursor motion */
  2521. X        t = "cm";
  2522. X
  2523. X    if (t)
  2524. X    {
  2525. X        sprintf(buf, s, t);
  2526. X        EMSG(buf);
  2527. X    }
  2528. X
  2529. X/*
  2530. X * if "cs" defined, use a scroll region, it's faster.
  2531. X */
  2532. X    if (T_CS && *T_CS != NUL)
  2533. X        scroll_region = TRUE;
  2534. X    else
  2535. X        scroll_region = FALSE;
  2536. X
  2537. X    if (pairs)
  2538. X    {
  2539. X      /* optional pairs */
  2540. X            /* TP goes to normal mode for TI (invert) and TB (bold) */
  2541. X        if ((!T_TP || !*T_TP))
  2542. X            T_TP = T_TI = T_TB = NULL;
  2543. X        if ((!T_SO || !*T_SO) ^ (!T_SE || !*T_SE))
  2544. X            T_SO = T_SE = NULL;
  2545. X            /* T_CV is needed even though T_CI is not defined */
  2546. X        if ((!T_CV || !*T_CV))
  2547. X            T_CI = NULL;
  2548. X            /* if 'mr' or 'me' is not defined use 'so' and 'se' */
  2549. X        if (T_TP == NULL || *T_TP == NUL)
  2550. X        {
  2551. X            T_TP = T_SE;
  2552. X            T_TI = T_SO;
  2553. X            T_TB = T_SO;
  2554. X        }
  2555. X            /* if 'so' or 'se' is not defined use 'mr' and 'me' */
  2556. X        if (T_SO == NULL || *T_SO == NUL)
  2557. X        {
  2558. X            T_SE = T_TP;
  2559. X            if (T_TI == NULL)
  2560. X                T_SO = T_TB;
  2561. X            else
  2562. X                T_SO = T_TI;
  2563. X        }
  2564. X    }
  2565. X}
  2566. X
  2567. X/*
  2568. X * inchar() - get one character from
  2569. X *        1. a scriptfile
  2570. X *        2. the keyboard
  2571. X *
  2572. X *  As much characters as we can get (upto 'maxlen') are put in buf and
  2573. X *  NUL terminated (buffer length must be 'maxlen' + 1).
  2574. X *
  2575. X *    If we got an interrupt all input is read until none is available.
  2576. X *
  2577. X *  If time == 0  there is no waiting for the char.
  2578. X *  If time == n  we wait for n msec for a character to arrive.
  2579. X *  If time == -1 we wait forever for a character to arrive.
  2580. X *
  2581. X *  Return the number of obtained characters.
  2582. X */
  2583. X
  2584. X    int
  2585. Xinchar(buf, maxlen, time)
  2586. X    char_u    *buf;
  2587. X    int        maxlen;
  2588. X    int        time;                        /* milli seconds */
  2589. X{
  2590. X    int                len;
  2591. X    int                retesc = FALSE;        /* return ESC with gotint */
  2592. X    register int     c;
  2593. X    register int    i;
  2594. X
  2595. X    if (time == -1 || time > 100)    /* flush output before waiting */
  2596. X    {
  2597. X        cursor_on();
  2598. X        flushbuf();
  2599. X    }
  2600. X    did_outofmem_msg = FALSE;    /* display out of memory message (again) */
  2601. X
  2602. X/*
  2603. X * first try script file
  2604. X *    If interrupted: Stop reading script files.
  2605. X */
  2606. Xretry:
  2607. X    if (scriptin[curscript] != NULL)
  2608. X    {
  2609. X        if (got_int || (c = getc(scriptin[curscript])) < 0)    /* reached EOF */
  2610. X        {
  2611. X                /* when reading script file is interrupted, return an ESC to
  2612. X                                    get back to normal mode */
  2613. X            if (got_int)
  2614. X                retesc = TRUE;
  2615. X            fclose(scriptin[curscript]);
  2616. X            scriptin[curscript] = NULL;
  2617. X            if (curscript > 0)
  2618. X                --curscript;
  2619. X            goto retry;        /* may read other script if this one was nested */
  2620. X        }
  2621. X        if (c == 0)
  2622. X            c = K_ZERO;        /* replace ^@ with special code */
  2623. X        *buf++ = c;
  2624. X        *buf = NUL;
  2625. X        return 1;
  2626. X    }
  2627. X
  2628. X/*
  2629. X * If we got an interrupt, skip all previously typed characters and
  2630. X * return TRUE if quit reading script file.
  2631. X */
  2632. X    if (got_int)            /* skip typed characters */
  2633. X    {
  2634. X        while (GetChars(buf, maxlen, T_PEEK))
  2635. X            ;
  2636. X        return retesc;
  2637. X    }
  2638. X    len = GetChars(buf, maxlen, time);
  2639. X
  2640. X    for (i = len; --i >= 0; ++buf)
  2641. X        if (*buf == 0)
  2642. X            *(char_u *)buf = K_ZERO;        /* replace ^@ with special code */
  2643. X    *buf = NUL;                                /* add trailing NUL */
  2644. X    return len;
  2645. X}
  2646. X
  2647. X/*
  2648. X * Check if buf[] begins with a terminal key code.
  2649. X * Return 0 for no match, -1 for partial match, > 0 for full match.
  2650. X * With a match the replacement code is put in buf[0], the match is
  2651. X * removed and the number characters in buf is returned.
  2652. X *
  2653. X * Note: should always be called with buf == typestr!
  2654. X */
  2655. X    int
  2656. Xcheck_termcode(buf)
  2657. X    char_u    *buf;
  2658. X{
  2659. X    char_u     **p;
  2660. X    int        slen;
  2661. X    int        len;
  2662. X
  2663. X    len = STRLEN(buf);
  2664. X    for (p = (char_u **)&term_strings.t_ku; p != (char_u **)&term_strings.t_undo + 1; ++p)
  2665. X    {
  2666. X        if (*p == NULL || (slen = STRLEN(*p)) == 0)        /* empty entry */
  2667. X            continue;
  2668. X        if (STRNCMP(*p, buf, (size_t)(slen > len ? len : slen)) == 0)
  2669. X        {
  2670. X            if (len >= slen)        /* got the complete sequence */
  2671. X            {
  2672. X                len -= slen;
  2673. X                    /* remove matched chars, taking care of noremap */
  2674. X                del_typestr(slen - 1);
  2675. X                    /* this relies on the Key numbers to be consecutive! */
  2676. X                buf[0] = K_UARROW + (p - (char_u **)&term_strings.t_ku);
  2677. X                return (len + 1);
  2678. X            }
  2679. X            return -1;                /* got a partial sequence */
  2680. X        }
  2681. X    }
  2682. X    return 0;                        /* no match found */
  2683. X}
  2684. X
  2685. X/*
  2686. X * outnum - output a (big) number fast
  2687. X */
  2688. X    void
  2689. Xoutnum(n)
  2690. X    register long n;
  2691. X{
  2692. X    OUTSTRN(tltoa((unsigned long)n));
  2693. X}
  2694. X    void
  2695. Xcheck_winsize()
  2696. X{
  2697. X    if (Columns < MIN_COLUMNS)
  2698. X        Columns = MIN_COLUMNS;
  2699. X    else if (Columns > MAX_COLUMNS)
  2700. X        Columns = MAX_COLUMNS;
  2701. X    if (Rows < MIN_ROWS + 1)    /* need room for one window and command line */
  2702. X        Rows = MIN_ROWS + 1;
  2703. X    screen_new_rows();            /* may need to update window sizes */
  2704. X}
  2705. X
  2706. X/*
  2707. X * set window size
  2708. X * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
  2709. X * window size (this is used for the :win command).
  2710. X * If 'mustset' is FALSE, we may try to get the real window size and if
  2711. X * it fails use 'width' and 'height'.
  2712. X */
  2713. X    void
  2714. Xset_winsize(width, height, mustset)
  2715. X    int        width, height;
  2716. X    int        mustset;
  2717. X{
  2718. X    register int         tmp;
  2719. X
  2720. X    if (width < 0 || height < 0)    /* just checking... */
  2721. X        return;
  2722. X
  2723. X    if (State == HITRETURN || State == SETWSIZE)    /* postpone the resizing */
  2724. X    {
  2725. X        State = SETWSIZE;
  2726. X        return;
  2727. X    }
  2728. X    screenclear();
  2729. X#ifdef AMIGA
  2730. X    flushbuf();         /* must do this before mch_get_winsize for some obscure reason */
  2731. X#endif /* AMIGA */
  2732. X    if (mustset || mch_get_winsize() == FAIL)
  2733. X    {
  2734. X        Rows = height;
  2735. X        Columns = width;
  2736. X        check_winsize();        /* always check, to get p_scroll right */
  2737. X        mch_set_winsize();
  2738. X    }
  2739. X    else
  2740. X        check_winsize();        /* always check, to get p_scroll right */
  2741. X    if (State == HELP)
  2742. X        (void)redrawhelp();
  2743. X    else if (!starting)
  2744. X    {
  2745. X        tmp = RedrawingDisabled;
  2746. X        RedrawingDisabled = FALSE;
  2747. X        comp_Botline_all();
  2748. X        updateScreen(CURSUPD);
  2749. X        RedrawingDisabled = tmp;
  2750. X        if (State == CMDLINE)
  2751. X            redrawcmdline();
  2752. X        else
  2753. X            setcursor();
  2754. X    }
  2755. X    flushbuf();
  2756. X}
  2757. X
  2758. X    void
  2759. Xsettmode(raw)
  2760. X    int     raw;
  2761. X{
  2762. X    static int        oldraw = FALSE;
  2763. X
  2764. X    if (oldraw == raw)        /* skip if already in desired mode */
  2765. X        return;
  2766. X    oldraw = raw;
  2767. X
  2768. X    mch_settmode(raw);    /* machine specific function */
  2769. X}
  2770. X
  2771. X    void
  2772. Xstarttermcap()
  2773. X{
  2774. X    outstr(T_TS);    /* start termcap mode */
  2775. X    outstr(T_KS);    /* start "keypad transmit" mode */
  2776. X    flushbuf();
  2777. X    termcap_active = TRUE;
  2778. X}
  2779. X
  2780. X    void
  2781. Xstoptermcap()
  2782. X{
  2783. X    outstr(T_KE);    /* stop "keypad transmit" mode */
  2784. X    flushbuf();
  2785. X    termcap_active = FALSE;
  2786. X    cursor_on();    /* just in case it is still off */
  2787. X    outstr(T_TE);    /* stop termcap mode */
  2788. X}
  2789. X
  2790. X/*
  2791. X * enable cursor, unless in Visual mode or no inversion possible
  2792. X */
  2793. Xstatic int cursor_is_off = FALSE;
  2794. X
  2795. X    void
  2796. Xcursor_on()
  2797. X{
  2798. X    if (cursor_is_off && (!VIsual.lnum || highlight == NULL))
  2799. X    {
  2800. X        outstr(T_CV);
  2801. X        cursor_is_off = FALSE;
  2802. X    }
  2803. X}
  2804. X
  2805. X    void
  2806. Xcursor_off()
  2807. X{
  2808. X    if (!cursor_is_off)
  2809. X        outstr(T_CI);            /* disable cursor */
  2810. X    cursor_is_off = TRUE;
  2811. X}
  2812. X
  2813. X/*
  2814. X * set scrolling region for window 'wp'
  2815. X */
  2816. X    void
  2817. Xscroll_region_set(wp)
  2818. X    WIN        *wp;
  2819. X{
  2820. X    OUTSTR(tgoto((char *)T_CS, wp->w_winpos + wp->w_height - 1, wp->w_winpos));
  2821. X}
  2822. X
  2823. X/*
  2824. X * reset scrolling region to the whole screen
  2825. X */
  2826. X    void
  2827. Xscroll_region_reset()
  2828. X{
  2829. X    OUTSTR(tgoto((char *)T_CS, (int)Rows - 1, 0));
  2830. X}
  2831. END_OF_FILE
  2832.   if test 19580 -ne `wc -c <'vim/src/term.c'`; then
  2833.     echo shar: \"'vim/src/term.c'\" unpacked with wrong size!
  2834.   fi
  2835.   # end of 'vim/src/term.c'
  2836. fi
  2837. echo shar: End of archive 12 \(of 26\).
  2838. cp /dev/null ark12isdone
  2839. MISSING=""
  2840. 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
  2841.     if test ! -f ark${I}isdone ; then
  2842.     MISSING="${MISSING} ${I}"
  2843.     fi
  2844. done
  2845. if test "${MISSING}" = "" ; then
  2846.     echo You have unpacked all 26 archives.
  2847.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2848. else
  2849.     echo You still must unpack the following archives:
  2850.     echo "        " ${MISSING}
  2851. fi
  2852. exit 0
  2853. exit 0 # Just in case...
  2854.