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

  1. From: mool@oce.nl (Bram Moolenaar)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i034:  vim - Vi IMproved editor, v3.0, Part15/26
  4. Date: 18 Aug 1994 14:02:42 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <330b8i$e58@sparky.sterling.com>
  9. X-Md4-Signature: a7e0c987abddaec7cefa150c153fa5c0
  10.  
  11. Submitted-by: mool@oce.nl (Bram Moolenaar)
  12. Posting-number: Volume 44, Issue 34
  13. Archive-name: vim/part15
  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/src/fileio.c vim/src/getchar.c
  22. # Wrapped by kent@sparky on Mon Aug 15 21:44:08 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 15 (of 26)."'
  26. if test -f 'vim/src/fileio.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'vim/src/fileio.c'\"
  28. else
  29.   echo shar: Extracting \"'vim/src/fileio.c'\" \(31526 characters\)
  30.   sed "s/^X//" >'vim/src/fileio.c' <<'END_OF_FILE'
  31. X/* vi:ts=4:sw=4
  32. X *
  33. X * VIM - Vi IMproved        by Bram Moolenaar
  34. X *
  35. X * Read the file "credits.txt" for a list of people who contributed.
  36. X * Read the file "uganda.txt" for copying and usage conditions.
  37. X */
  38. X
  39. X/*
  40. X * fileio.c: read from and write to a file
  41. X */
  42. X
  43. X/*
  44. X * special feature of this version: NUL characters in the file are
  45. X * replaced by newline characters in memory. This allows us to edit
  46. X * binary files!
  47. X */
  48. X
  49. X#ifdef MSDOS
  50. X# include <io.h>
  51. X#endif
  52. X
  53. X#include "vim.h"
  54. X#include "globals.h"
  55. X#include "proto.h"
  56. X#include "param.h"
  57. X#include "fcntl.h"
  58. X
  59. X#ifdef LATTICE
  60. X# include <proto/dos.h>        /* for Lock() and UnLock() */
  61. X#endif
  62. X
  63. X#define BUFSIZE        8192            /* size of normal write buffer */
  64. X#define SBUFSIZE    256                /* size of emergency write buffer */
  65. X
  66. Xstatic int  write_buf __ARGS((int, char_u *, int));
  67. Xstatic void do_mlines __ARGS((void));
  68. X
  69. X    void
  70. Xfilemess(name, s)
  71. X    char_u        *name;
  72. X    char_u        *s;
  73. X{
  74. X        /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  75. X    home_replace(name, IObuff + 1, IOSIZE - 1);
  76. X    IObuff[0] = '"';
  77. X    STRCAT(IObuff, "\" ");
  78. X    STRCAT(IObuff, s);
  79. X    /*
  80. X     * don't use msg(), because it sometimes outputs a newline
  81. X     */
  82. X    msg_start();
  83. X    msg_outstr(IObuff);
  84. X    msg_ceol();
  85. X    flushbuf();
  86. X}
  87. X
  88. X/*
  89. X * Read lines from file 'fname' into the buffer after line 'from'.
  90. X *
  91. X * 1. We allocate blocks with lalloc, as big as possible.
  92. X * 2. Each block is filled with characters from the file with a single read().
  93. X * 3. The lines are inserted in the buffer with ml_append().
  94. X *
  95. X * (caller must check that fname != NULL)
  96. X *
  97. X * skip_lnum is the number of lines that must be skipped
  98. X * nlines is the number of lines that are appended
  99. X * When not recovering skip_lnum is 0 and nlines MAXLNUM.
  100. X *
  101. X * return FAIL for failure, OK otherwise
  102. X */
  103. X    int
  104. Xreadfile(fname, sfname, from, newfile, skip_lnum, nlines)
  105. X    char_u           *fname;
  106. X    char_u           *sfname;
  107. X    linenr_t        from;
  108. X    int                newfile;
  109. X    linenr_t        skip_lnum;
  110. X    linenr_t        nlines;
  111. X{
  112. X#ifdef UNIX
  113. X    int                 fd = -1;
  114. X#else
  115. X    int                 fd;
  116. X#endif
  117. X    register char_u     c;
  118. X    register linenr_t    lnum = from;
  119. X    register char_u     *ptr = NULL;            /* pointer into read buffer */
  120. X    register char_u        *buffer = NULL;            /* read buffer */
  121. X    char_u                *new_buffer = NULL;        /* init to shut up gcc */
  122. X    char_u                *line_start = NULL;        /* init to shut up gcc */
  123. X    colnr_t                len;
  124. X    register long        size;
  125. X    register char_u        *p;
  126. X    long                filesize = 0;
  127. X    int                    split = 0;                /* number of split lines */
  128. X#define UNKNOWN        0x0fffffff                    /* file size is unknown */
  129. X    linenr_t            linecnt = curbuf->b_ml.ml_line_count;
  130. X    int                    incomplete = FALSE;     /* was the last line incomplete? */
  131. X    int                 error = FALSE;            /* errors encountered */
  132. X    long                linerest = 0;            /* remaining characters in line */
  133. X    int                    firstpart = TRUE;        /* reading first part */
  134. X#ifdef UNIX
  135. X    int                    perm;
  136. X#endif
  137. X    int                    textmode = curbuf->b_p_tx;        /* accept CR-LF for line break */
  138. X    struct stat            st;
  139. X    int                    readonly;
  140. X
  141. X    /*
  142. X     * If there is no file name yet, use the one for the read file.
  143. X     * b_notedited is set to reflect this.
  144. X     */
  145. X    if (curbuf->b_filename == NULL)
  146. X    {
  147. X        if (setfname(fname, sfname, FALSE) == OK)
  148. X            curbuf->b_notedited = TRUE;
  149. X    }
  150. X
  151. X    if (sfname == NULL)
  152. X        sfname = fname;
  153. X    /*
  154. X     * Use the short filename whenever possible.
  155. X     * Avoids problems with networks and when directory names are changed.
  156. X     */
  157. X    if (!did_cd)
  158. X        fname = sfname;
  159. X
  160. X    if (bufempty())        /* special case: buffer has no lines */
  161. X        linecnt = 0;
  162. X
  163. X#ifdef UNIX
  164. X    /*
  165. X     * On Unix it is possible to read a directory, so we have to
  166. X     * check for it before the open().
  167. X     */
  168. X    perm = getperm(fname);
  169. X# ifdef _POSIX_SOURCE
  170. X    if (perm >= 0 && !S_ISREG(perm))                /* not a regular file */
  171. X# else
  172. X    if (perm >= 0 && (perm & S_IFMT) != S_IFREG)    /* not a regular file */
  173. X# endif
  174. X    {
  175. X# ifdef _POSIX_SOURCE
  176. X        if (S_ISDIR(perm))
  177. X# else
  178. X        if ((perm & S_IFMT) == S_IFDIR)
  179. X# endif
  180. X            filemess(fname, (char_u *)"is a directory");
  181. X        else
  182. X            filemess(fname, (char_u *)"is not a file");
  183. X        return FAIL;
  184. X    }
  185. X#endif
  186. X
  187. X    if (newfile && !readonlymode)            /* default: set file not readonly */
  188. X        curbuf->b_p_ro = FALSE;
  189. X
  190. X    if (newfile && stat((char *)fname, &st) != -1)    /* remember time of file */
  191. X        curbuf->b_mtime = st.st_mtime;
  192. X    else
  193. X        curbuf->b_mtime = 0;
  194. X
  195. X/*
  196. X * for UNIX: check readonly with perm and access()
  197. X * for MSDOS and Amiga: check readonly by trying to open the file for writing
  198. X */
  199. X    readonly = FALSE;
  200. X#ifdef UNIX
  201. X    if (!(perm & 0222) || access((char *)fname, 2))
  202. X        readonly = TRUE;
  203. X    fd = open((char *)fname, O_RDONLY);
  204. X#else
  205. X    if (!newfile || readonlymode || (fd = open((char *)fname, O_RDWR)) < 0)
  206. X    {
  207. X        readonly = TRUE;
  208. X        fd = open((char *)fname, O_RDONLY);            /* try to open ro */
  209. X    }
  210. X#endif
  211. X
  212. X    if (fd < 0)                     /* cannot open at all */
  213. X    {
  214. X#ifdef MSDOS
  215. X    /*
  216. X     * The screen may be messed up by the "insert disk
  217. X     * in drive b: and hit return" message
  218. X     */
  219. X        screenclear();
  220. X#endif
  221. X
  222. X#ifndef UNIX
  223. X    /*
  224. X     * On MSDOS and Amiga we can't open a directory, check here.
  225. X     */
  226. X        if (isdir(fname) == TRUE)
  227. X            filemess(fname, (char_u *)"is a directory");
  228. X        else
  229. X#endif
  230. X            if (newfile)
  231. X#ifdef UNIX
  232. X                if (perm < 0)
  233. X#endif
  234. X                    filemess(fname, (char_u *)"[New File]");
  235. X#ifdef UNIX
  236. X                else
  237. X                    filemess(fname, (char_u *)"[Permission Denied]");
  238. X#endif
  239. X
  240. X        return FAIL;
  241. X    }
  242. X    if (newfile && readonly)                    /* set file readonly */
  243. X        curbuf->b_p_ro = TRUE;
  244. X
  245. X    if (newfile)
  246. X        curbuf->b_p_eol = TRUE;
  247. X
  248. X    ++no_wait_return;                            /* don't wait for return yet */
  249. X    if (!recoverymode)
  250. X        filemess(fname, (char_u *)"");            /* show that we are busy */
  251. X
  252. X    while (!error && !got_int)
  253. X    {
  254. X        /*
  255. X         * We allocate as much space for the file as we can get, plus
  256. X         * space for the old line plus room for one terminating NUL.
  257. X         * The amount is limited by the fact that read() only can read
  258. X         * upto max_unsigned characters (and other things).
  259. X         */
  260. X#if defined(AMIGA) || defined(MSDOS)
  261. X        if (sizeof(int) <= 2 && linerest >= 0x7ff0)
  262. X        {
  263. X            ++split;
  264. X            *ptr = NL;                /* split line by inserting a NL */
  265. X            size = 1;
  266. X        }
  267. X        else
  268. X#endif
  269. X        {
  270. X#if !(defined(AMIGA) || defined(MSDOS))
  271. X            if (sizeof(int) > 2)
  272. X                size = 0x10000L;                /* read 64K at a time */
  273. X            else
  274. X#endif
  275. X                size = 0x7ff0L - linerest;        /* limit buffer to 32K */
  276. X
  277. X            for ( ; size >= 10; size >>= 1)
  278. X            {
  279. X                if ((new_buffer = lalloc((long_u)(size + linerest + 1), FALSE)) != NULL)
  280. X                    break;
  281. X            }
  282. X            if (new_buffer == NULL)
  283. X            {
  284. X                emsg(e_outofmem);
  285. X                error = TRUE;
  286. X                break;
  287. X            }
  288. X            if (linerest)        /* copy characters from the previous buffer */
  289. X                memmove((char *)new_buffer, (char *)ptr - linerest, linerest);
  290. X            free(buffer);
  291. X            buffer = new_buffer;
  292. X            ptr = buffer + linerest;
  293. X            line_start = buffer;
  294. X            
  295. X            if ((size = read(fd, (char *)ptr, (size_t)size)) <= 0)
  296. X            {
  297. X                if (size < 0)                /* read error */
  298. X                    error = TRUE;
  299. X                break;
  300. X            }
  301. X            filesize += size;                /* count the number of characters */
  302. X
  303. X            /*
  304. X             * when reading the first part of a file: guess EOL type
  305. X             */
  306. X            if (firstpart && p_ta)
  307. X            {
  308. X                for (p = ptr; p < ptr + size; ++p)
  309. X                    if (*p == NL)
  310. X                    {
  311. X                        if (p > ptr && p[-1] == CR)    /* found CR-NL */
  312. X                            textmode = TRUE;
  313. X                        else                        /* found a single NL */
  314. X                            textmode = FALSE;
  315. X                            /* if editing a new file: may set p_tx */
  316. X                        if (newfile && curbuf->b_p_tx != textmode)
  317. X                        {
  318. X                            curbuf->b_p_tx = textmode;
  319. X                            paramchanged((char_u *)"tx");
  320. X                        }
  321. X                        break;
  322. X                    }
  323. X            }
  324. X        }
  325. X
  326. X        /*
  327. X         * This loop is executed once for every character read.
  328. X         * Keep it fast!
  329. X         */
  330. X        --ptr;
  331. X        while (++ptr, --size >= 0)
  332. X        {
  333. X            if ((c = *ptr) != NUL && c != NL)    /* catch most common case */
  334. X                continue;
  335. X            if (c == NUL)
  336. X                *ptr = NL;        /* NULs are replaced by newlines! */
  337. X            else
  338. X            {
  339. X                if (skip_lnum == 0)
  340. X                {
  341. X                    *ptr = NUL;        /* end of line */
  342. X                    len = ptr - line_start + 1;
  343. X                    if (textmode && ptr[-1] == CR)    /* remove CR */
  344. X                    {
  345. X                        ptr[-1] = NUL;
  346. X                        --len;
  347. X                    }
  348. X                    if (ml_append(lnum, line_start, len, newfile) == FAIL)
  349. X                    {
  350. X                        error = TRUE;
  351. X                        break;
  352. X                    }
  353. X                    ++lnum;
  354. X                    if (--nlines == 0)
  355. X                    {
  356. X                        error = TRUE;        /* break loop */
  357. X                        line_start = ptr;    /* nothing left to write */
  358. X                        break;
  359. X                    }
  360. X                }
  361. X                else
  362. X                    --skip_lnum;
  363. X                line_start = ptr + 1;
  364. X            }
  365. X        }
  366. X        linerest = ptr - line_start;
  367. X        firstpart = FALSE;
  368. X        breakcheck();
  369. X    }
  370. X
  371. X    if (error && nlines == 0)        /* not an error, max. number of lines reached */
  372. X        error = FALSE;
  373. X
  374. X    if (!error && !got_int && linerest != 0
  375. X#ifdef MSDOS
  376. X    /*
  377. X     * in MSDOS textmode ignore a trailing CTRL-Z
  378. X     */
  379. X        && !(!curbuf->b_p_bin && *line_start == Ctrl('Z') && ptr == line_start + 1)
  380. X#endif
  381. X                                    )
  382. X    {
  383. X        /*
  384. X         * If we get EOF in the middle of a line, note the fact and
  385. X         * complete the line ourselves.
  386. X         */
  387. X        incomplete = TRUE;
  388. X        if (newfile && curbuf->b_p_bin)        /* remember for when writing */
  389. X            curbuf->b_p_eol = FALSE;
  390. X        *ptr = NUL;
  391. X        if (ml_append(lnum, line_start, (colnr_t)(ptr - line_start + 1), newfile) == FAIL)
  392. X            error = TRUE;
  393. X        else
  394. X            ++lnum;
  395. X    }
  396. X    if (lnum != from && !newfile)    /* added at least one line */
  397. X        CHANGED;
  398. X
  399. X    close(fd);
  400. X    free(buffer);
  401. X
  402. X    --no_wait_return;                /* may wait for return now */
  403. X    if (recoverymode)                /* in recovery mode return here */
  404. X    {
  405. X        if (error)
  406. X            return FAIL;
  407. X        return OK;
  408. X    }
  409. X
  410. X#ifdef MSDOS                    /* the screen may be messed up by the "insert disk
  411. X                                    in drive b: and hit return" message */
  412. X    screenclear();
  413. X#endif
  414. X
  415. X    linecnt = curbuf->b_ml.ml_line_count - linecnt;
  416. X    if (!newfile)
  417. X        mark_adjust(from + 1, MAXLNUM, (long)linecnt);
  418. X
  419. X    if (got_int)
  420. X    {
  421. X        filemess(fname, e_interr);
  422. X        return OK;            /* an interrupt isn't really an error */
  423. X    }
  424. X
  425. X        /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  426. X    home_replace(fname, IObuff + 1, IOSIZE - 1);
  427. X    IObuff[0] = '"';
  428. X    sprintf((char *)IObuff + STRLEN(IObuff),
  429. X                    "\" %s%s%s%s%s%ld line%s, %ld character%s",
  430. X            curbuf->b_p_ro ? "[readonly] " : "",
  431. X            incomplete ? "[Incomplete last line] " : "",
  432. X            split ? "[long lines split] " : "",
  433. X            error ? "[READ ERRORS] " : "",
  434. X#ifdef MSDOS
  435. X            textmode ? "" : "[notextmode] ",
  436. X#else
  437. X            textmode ? "[textmode] " : "",
  438. X#endif
  439. X            (long)linecnt, plural((long)linecnt),
  440. X            filesize, plural(filesize));
  441. X    msg(IObuff);
  442. X
  443. X    if (error && newfile)    /* with errors we should not write the file */
  444. X    {
  445. X        curbuf->b_p_ro = TRUE;
  446. X        paramchanged((char_u *)"ro");
  447. X    }
  448. X
  449. X    u_clearline();        /* cannot use "U" command after adding lines */
  450. X
  451. X    if (newfile)        /* edit a new file: read mode from lines */
  452. X        do_mlines();
  453. X    if (from < curbuf->b_ml.ml_line_count)
  454. X    {
  455. X        curwin->w_cursor.lnum = from + 1;    /* put cursor at first new line */
  456. X        curwin->w_cursor.col = 0;
  457. X    }
  458. X
  459. X    return OK;
  460. X}
  461. X
  462. X/*
  463. X * writeit - write to file 'fname' lines 'start' through 'end'
  464. X *
  465. X * We do our own buffering here because fwrite() is so slow.
  466. X *
  467. X * If forceit is true, we don't care for errors when attempting backups (jw).
  468. X * In case of an error everything possible is done to restore the original file.
  469. X * But when forceit is TRUE, we risk loosing it.
  470. X * When reset_changed is TRUE and start == 1 and end ==
  471. X * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
  472. X *
  473. X * return FAIL for failure, OK otherwise
  474. X */
  475. X    int
  476. Xbuf_write(buf, fname, sfname, start, end, append, forceit, reset_changed)
  477. X    BUF                *buf;
  478. X    char_u            *fname;
  479. X    char_u            *sfname;
  480. X    linenr_t        start, end;
  481. X    int                append;
  482. X    int                forceit;
  483. X    int                reset_changed;
  484. X{
  485. X    int                 fd;
  486. X    char_u               *backup = NULL;
  487. X    char_u               *ffname;
  488. X    register char_u       *s;
  489. X    register char_u       *ptr;
  490. X    register char_u        c;
  491. X    register int        len;
  492. X    register linenr_t    lnum;
  493. X    long                nchars;
  494. X    char_u                *errmsg = NULL;
  495. X    char_u                *buffer;
  496. X    char_u                smallbuf[SBUFSIZE];
  497. X    int                    bufsize;
  498. X    long                 perm = -1;            /* file permissions */
  499. X    int                    retval = OK;
  500. X    int                    newfile = FALSE;    /* TRUE if file does not exist yet */
  501. X#ifdef UNIX
  502. X    struct stat            old;
  503. X    int                    made_writable = FALSE;    /* 'w' bit has been set */
  504. X#endif
  505. X#ifdef AMIGA
  506. X    BPTR                flock;
  507. X#endif
  508. X                                            /* writing everything */
  509. X    int                    whole = (start == 1 && end == buf->b_ml.ml_line_count);
  510. X
  511. X    if (fname == NULL || *fname == NUL)        /* safety check */
  512. X        return FAIL;
  513. X
  514. X    /*
  515. X     * If there is no file name yet, use the one for the written file.
  516. X     * b_notedited is set to reflect this (in case the write fails).
  517. X     */
  518. X    if (reset_changed && whole && buf == curbuf && curbuf->b_filename == NULL)
  519. X    {
  520. X        if (setfname(fname, sfname, FALSE) == OK)
  521. X            curbuf->b_notedited = TRUE;
  522. X    }
  523. X
  524. X    if (sfname == NULL)
  525. X        sfname = fname;
  526. X    /*
  527. X     * Use the short filename whenever possible.
  528. X     * Avoids problems with networks and when directory names are changed.
  529. X     */
  530. X    ffname = fname;                            /* remember full fname */
  531. X    if (!did_cd)
  532. X        fname = sfname;
  533. X
  534. X    /*
  535. X     * Disallow writing from .exrc and .vimrc in current directory for
  536. X     * security reasons.
  537. X     */
  538. X    if (secure)
  539. X    {
  540. X        secure = 2;
  541. X        emsg(e_curdir);
  542. X        return FAIL;
  543. X    }
  544. X
  545. X    if (exiting)
  546. X        settmode(0);                /* when exiting allow typahead now */
  547. X
  548. X    ++no_wait_return;                /* don't wait for return yet */
  549. X    filemess(fname, (char_u *)"");    /* show that we are busy */
  550. X
  551. X    buffer = alloc(BUFSIZE);
  552. X    if (buffer == NULL)                /* can't allocate big buffer, use small one */
  553. X    {
  554. X        buffer = smallbuf;
  555. X        bufsize = SBUFSIZE;
  556. X    }
  557. X    else
  558. X        bufsize = BUFSIZE;
  559. X
  560. X#if defined(UNIX) && !defined(ARCHIE)
  561. X        /* get information about original file (if there is one) */
  562. X    old.st_dev = old.st_ino = 0;
  563. X    if (stat((char *)fname, &old))
  564. X        newfile = TRUE;
  565. X    else
  566. X    {
  567. X#ifdef _POSIX_SOURCE
  568. X        if (!S_ISREG(old.st_mode))              /* not a file */
  569. X#else
  570. X        if ((old.st_mode & S_IFMT) != S_IFREG)    /* not a file */
  571. X#endif
  572. X        {
  573. X#ifdef _POSIX_SOURCE
  574. X            if (S_ISDIR(old.st_mode))
  575. X#else
  576. X            if ((old.st_mode & S_IFMT) == S_IFDIR)
  577. X#endif
  578. X                errmsg = (char_u *)"is a directory";
  579. X            else
  580. X                errmsg = (char_u *)"is not a file";
  581. X            goto fail;
  582. X        }
  583. X        perm = old.st_mode;
  584. X    }
  585. X/*
  586. X * If we are not appending, the file exists, and the 'writebackup', 'backup'
  587. X * or 'patchmode' option is set, try to make a backup copy of the file.
  588. X */
  589. X    if (!append && perm >= 0 && (p_wb || p_bk || (p_pm != NULL && *p_pm != NUL)) &&
  590. X                    (fd = open((char *)fname, O_RDONLY)) >= 0)
  591. X    {
  592. X        int                bfd, buflen;
  593. X        char_u            copybuf[BUFSIZE + 1], *wp;
  594. X        int                some_error = FALSE;
  595. X        struct stat        new;
  596. X
  597. X        new.st_dev = new.st_ino = 0;
  598. X
  599. X        /*
  600. X         * Unix semantics has it, that we may have a writable file, 
  601. X         * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
  602. X         *  - the directory is not writable, 
  603. X         *  - the file may be a symbolic link, 
  604. X         *  - the file may belong to another user/group, etc.
  605. X         *
  606. X         * For these reasons, the existing writable file must be truncated and
  607. X         * reused. Creation of a backup COPY will be attempted.
  608. X         */
  609. X        if (*p_bdir != '>')            /* try to put .bak in current dir */
  610. X        {
  611. X            if ((backup = modname(fname, ".bak")) == NULL)
  612. X            {
  613. X                some_error = TRUE;            /* out of memory */
  614. X                goto nobackup;
  615. X            }            
  616. X            if (!stat((char *)backup, &new) &&
  617. X                        new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  618. X            {
  619. X                /*
  620. X                 * may happen when modname gave the same file back.
  621. X                 * E.g. silly link, or filename-length reached.
  622. X                 * If we don't check here, we either ruin the file when
  623. X                 * copying or erase it after writing. jw.
  624. X                 */
  625. X                free(backup);
  626. X                backup = NULL;    /* there is no backup file to delete */
  627. X                if (*p_bdir == NUL)
  628. X                {
  629. X                    errmsg = (char_u *)"Invalid backup file (use ! to override)";
  630. X                    goto nobackup;
  631. X                }
  632. X            }
  633. X            else
  634. X                remove((char *)backup);        /* remove old backup, if present */
  635. X        }
  636. X        if (backup == NULL || (bfd = open((char *)backup, O_WRONLY | O_CREAT, 0666)) < 0)
  637. X        {
  638. X            /* 
  639. X             * 'backupdir' starts with '>' or  no write/create permission
  640. X             * in current dirr: try again in p_bdir directory. 
  641. X             */
  642. X            free(backup);
  643. X            wp = gettail(fname);
  644. X            sprintf((char *)copybuf, "%s/%s", *p_bdir == '>' ? p_bdir + 1 : p_bdir, wp);
  645. X            if ((backup = buf_modname(buf, copybuf, (char_u *)".bak")) == NULL)
  646. X            {
  647. X                some_error = TRUE;            /* out of memory */
  648. X                goto nobackup;
  649. X            }
  650. X            if (!stat((char *)backup, &new) &&
  651. X                        new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  652. X            {
  653. X                errmsg = (char_u *)"Invalid backup file (use ! to override)";
  654. X                free(backup);
  655. X                backup = NULL;    /* there is no backup file to delete */
  656. X                goto nobackup;
  657. X            }
  658. X            remove((char *)backup);
  659. X            if ((bfd = open((char *)backup, O_WRONLY | O_CREAT, 0666)) < 0)
  660. X            {
  661. X                free(backup);
  662. X                backup = NULL;    /* there is no backup file to delete */
  663. X                errmsg = (char_u *)"Can't make backup file (use ! to override)";
  664. X                goto nobackup;
  665. X            }
  666. X        }
  667. X        /* set file protection same as original file, but strip s-bit */
  668. X        (void)setperm(backup, perm & 0777);
  669. X
  670. X        /* copy the file. */
  671. X        while ((buflen = read(fd, (char *)copybuf, BUFSIZE)) > 0)
  672. X        {
  673. X            if (write_buf(bfd, copybuf, buflen) == FAIL)
  674. X            {
  675. X                errmsg = (char_u *)"Can't write to backup file (use ! to override)";
  676. X                goto writeerr;
  677. X            }
  678. X        }
  679. Xwriteerr:
  680. X        close(bfd);
  681. X        if (buflen < 0)
  682. X            errmsg = (char_u *)"Can't read file for backup (use ! to override)";
  683. Xnobackup:
  684. X        close(fd);
  685. X    /* ignore errors when forceit is TRUE */
  686. X        if ((some_error || errmsg) && !forceit)
  687. X        {
  688. X            retval = FAIL;
  689. X            goto fail;
  690. X        }
  691. X        errmsg = NULL;
  692. X    }
  693. X        /* if forceit and the file was read-only: make it writable */
  694. X    if (forceit && (old.st_uid == getuid()) && perm >= 0 && !(perm & 0200))
  695. X     {
  696. X        perm |= 0200;    
  697. X        (void)setperm(fname, perm);
  698. X        made_writable = TRUE;
  699. X            /* if we are writing to the current file, readonly makes no sense */
  700. X        if (fname == buf->b_filename || fname == buf->b_sfilename)
  701. X            buf->b_p_ro = FALSE;
  702. X     }
  703. X#else /* end of UNIX, start of the rest */
  704. X
  705. X/*
  706. X * If we are not appending, the file exists, and the 'writebackup' or
  707. X * 'backup' option is set, make a backup.
  708. X * Do not make any backup, if "writebackup" and "backup" are 
  709. X * both switched off. This helps when editing large files on
  710. X * almost-full disks. (jw)
  711. X */
  712. X    perm = getperm(fname);
  713. X    if (perm < 0)
  714. X        newfile = TRUE;
  715. X    else if (isdir(fname) == TRUE)
  716. X    {
  717. X        errmsg = (char_u *)"is a directory";
  718. X        goto fail;
  719. X    }
  720. X    if (!append && perm >= 0 && (p_wb || p_bk || (p_pm != NULL && *p_pm != NUL)))
  721. X    {
  722. X        /*
  723. X         * Form the backup file name - change path/fo.o.h to path/fo.o.h.bak
  724. X         */
  725. X        backup = buf_modname(buf, fname, (char_u *)".bak");
  726. X        if (backup == NULL)
  727. X        {
  728. X            if (!forceit)
  729. X                goto fail;
  730. X        }
  731. X        else
  732. X        {
  733. X            /*
  734. X             * Delete any existing backup and move the current version to the backup.
  735. X             * For safety, we don't remove the backup until the write has finished
  736. X             * successfully. And if the 'backup' option is set, leave it around.
  737. X             */
  738. X#ifdef AMIGA
  739. X            /*
  740. X             * With MSDOS-compatible filesystems (crossdos, messydos) it is
  741. X             * possible that the name of the backup file is the same as the
  742. X             * original file. To avoid the chance of accidently deleting the
  743. X             * original file (horror!) we lock it during the remove.
  744. X             * This should not happen with ":w", because startscript() should
  745. X             * detect this problem and set buf->b_shortname, causing modname to
  746. X             * return a correct ".bak" filename. This problem does exist with
  747. X             * ":w filename", but then the original file will be somewhere else
  748. X             * so the backup isn't really important. If autoscripting is off
  749. X             * the rename may fail.
  750. X             */
  751. X            flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  752. X#endif
  753. X            remove((char *)backup);
  754. X#ifdef AMIGA
  755. X            if (flock)
  756. X                UnLock(flock);
  757. X#endif
  758. X            len = rename((char *)fname, (char *)backup);
  759. X            if (len != 0)
  760. X            {
  761. X                if (forceit)
  762. X                {
  763. X                    free(backup);    /* don't do the rename below */
  764. X                    backup = NULL;
  765. X                }
  766. X                else
  767. X                {
  768. X                    errmsg = (char_u *)"Can't make backup file (use ! to override)";
  769. X                    goto fail;
  770. X                }
  771. X            }
  772. X        }
  773. X    }
  774. X#endif /* UNIX */
  775. X
  776. X    /*
  777. X     * If the original file is being overwritten, there is a small chance that
  778. X     * we crash in the middle of writing. Therefore the file is preserved now.
  779. X     * This makes all block numbers positive so that recovery does not need
  780. X     * the original file.
  781. X     * Don't do this if there is a backup file and we are exiting.
  782. X     */
  783. X    if (reset_changed && !newfile && !otherfile(ffname) && !(exiting && backup != NULL))
  784. X        ml_preserve(buf, FALSE);
  785. X
  786. X    /* 
  787. X     * We may try to open the file twice: If we can't write to the
  788. X     * file and forceit is TRUE we delete the existing file and try to create
  789. X     * a new one. If this still fails we may have lost the original file!
  790. X     * (this may happen when the user reached his quotum for number of files).
  791. X     * Appending will fail if the file does not exist and forceit is FALSE.
  792. X     */
  793. X    while ((fd = open((char *)fname, O_WRONLY | (append ?
  794. X                    (forceit ? (O_APPEND | O_CREAT) : O_APPEND) :
  795. X                    (O_CREAT | O_TRUNC)), 0666)) < 0)
  796. X     {
  797. X        /*
  798. X         * A forced write will try to create a new file if the old one is
  799. X         * still readonly. This may also happen when the directory is
  800. X         * read-only. In that case the remove() will fail.
  801. X         */
  802. X        if (!errmsg)
  803. X        {
  804. X            errmsg = (char_u *)"Can't open file for writing";
  805. X            if (forceit)
  806. X            {
  807. X#ifdef UNIX
  808. X                /* we write to the file, thus it should be marked
  809. X                                                    writable after all */
  810. X                perm |= 0200;        
  811. X                made_writable = TRUE;
  812. X                if (old.st_uid != getuid() || old.st_gid != getgid())
  813. X                    perm &= 0777;
  814. X#endif /* UNIX */
  815. X                if (!append)        /* don't remove when appending */
  816. X                    remove((char *)fname);
  817. X                continue;
  818. X            }
  819. X        }
  820. X/*
  821. X * If we failed to open the file, we don't need a backup. Throw it away.
  822. X * If we moved or removed the original file try to put the backup in its place.
  823. X */
  824. X         if (backup != NULL)
  825. X        {
  826. X#ifdef UNIX
  827. X            struct stat st;
  828. X
  829. X            /*
  830. X             * There is a small chance that we removed the original, try
  831. X             * to move the copy in its place.
  832. X             * This won't work if the backup is in another file system!
  833. X             * In that case we leave the copy around.
  834. X             */
  835. X            if (stat((char *)fname, &st) < 0)    /* file does not exist */
  836. X                rename((char *)backup, (char *)fname);    /* put the copy in its place */
  837. X            if (stat((char *)fname, &st) >= 0)    /* original file does exist */
  838. X                remove((char *)backup);    /* throw away the copy */
  839. X#else
  840. X             rename((char *)backup, (char *)fname);    /* try to put the original file back */
  841. X#endif
  842. X        }
  843. X         goto fail;
  844. X     }
  845. X    errmsg = NULL;
  846. X
  847. X    if (end > buf->b_ml.ml_line_count)
  848. X        end = buf->b_ml.ml_line_count;
  849. X    len = 0;
  850. X    s = buffer;
  851. X    nchars = 0;
  852. X    for (lnum = start; lnum <= end; ++lnum)
  853. X    {
  854. X        /*
  855. X         * The next while loop is done once for each character written.
  856. X         * Keep it fast!
  857. X         */
  858. X        ptr = ml_get_buf(buf, lnum, FALSE) - 1;
  859. X        while ((c = *++ptr) != NUL)
  860. X        {
  861. X            if (c == NL)
  862. X                *s = NUL;        /* replace newlines with NULs */
  863. X            else
  864. X                *s = c;
  865. X            ++s;
  866. X            if (++len != bufsize)
  867. X                continue;
  868. X            if (write_buf(fd, buffer, bufsize) == FAIL)
  869. X            {
  870. X                end = 0;                /* write error: break loop */
  871. X                break;
  872. X            }
  873. X            nchars += bufsize;
  874. X            s = buffer;
  875. X            len = 0;
  876. X        }
  877. X            /* write failed or last line has no EOL: stop here */
  878. X        if (end == 0 || (buf->b_p_bin && lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))
  879. X            break;
  880. X        if (buf->b_p_tx)        /* write CR-NL */
  881. X        {
  882. X            *s = CR;
  883. X            ++s;
  884. X            if (++len == bufsize)
  885. X            {
  886. X                if (write_buf(fd, buffer, bufsize) == FAIL)
  887. X                {
  888. X                    end = 0;                /* write error: break loop */
  889. X                    break;
  890. X                }
  891. X                nchars += bufsize;
  892. X                s = buffer;
  893. X                len = 0;
  894. X            }
  895. X        }
  896. X        *s = NL;
  897. X        ++s;
  898. X        if (++len == bufsize && end)
  899. X        {
  900. X            if (write_buf(fd, buffer, bufsize) == FAIL)
  901. X            {
  902. X                end = 0;                /* write error: break loop */
  903. X                break;
  904. X            }
  905. X            nchars += bufsize;
  906. X            s = buffer;
  907. X            len = 0;
  908. X        }
  909. X    }
  910. X    if (len && end)
  911. X    {
  912. X        if (write_buf(fd, buffer, len) == FAIL)
  913. X            end = 0;                /* write error */
  914. X        nchars += len;
  915. X    }
  916. X
  917. X    if (close(fd) != 0)
  918. X    {
  919. X        errmsg = (char_u *)"Close failed";
  920. X        goto fail;
  921. X    }
  922. X#ifdef UNIX
  923. X    if (made_writable)
  924. X        perm &= ~0200;            /* reset 'w' bit for security reasons */
  925. X#endif
  926. X    if (perm >= 0)
  927. X        (void)setperm(fname, perm);    /* set permissions of new file same as old file */
  928. X
  929. X    if (end == 0)
  930. X    {
  931. X        errmsg = (char_u *)"write error (file system full?)";
  932. X        goto fail;
  933. X    }
  934. X
  935. X#ifdef MSDOS        /* the screen may be messed up by the "insert disk
  936. X                            in drive b: and hit return" message */
  937. X    if (!exiting)
  938. X        screenclear();
  939. X#endif
  940. X
  941. X    lnum -= start;            /* compute number of written lines */
  942. X    --no_wait_return;        /* may wait for return now */
  943. X
  944. X        /* careful: home_replace calls vimgetenv(), which also uses IObuff! */
  945. X    home_replace(fname, IObuff + 1, IOSIZE - 1);
  946. X    IObuff[0] = '"';
  947. X    sprintf((char *)IObuff + STRLEN(IObuff),
  948. X                    "\"%s%s %ld line%s, %ld character%s",
  949. X            newfile ? " [New File]" : " ",
  950. X#ifdef MSDOS
  951. X            buf->b_p_tx ? "" : "[notextmode]",
  952. X#else
  953. X            buf->b_p_tx ? "[textmode]" : "",
  954. X#endif
  955. X            (long)lnum, plural((long)lnum),
  956. X            nchars, plural(nchars));
  957. X    msg(IObuff);
  958. X
  959. X    if (reset_changed && whole)            /* when written everything */
  960. X    {
  961. X        UNCHANGED(buf);
  962. X        u_unchanged(buf);
  963. X        /*
  964. X         * If written to the current file, update the timestamp of the swap file
  965. X         * and reset the 'notedited' flag.
  966. X         */
  967. X        if (!exiting && buf->b_filename != NULL &&
  968. X                            fnamecmp(ffname, buf->b_filename) == 0)
  969. X        {
  970. X            ml_timestamp(buf);
  971. X            buf->b_notedited = FALSE;
  972. X        }
  973. X    }
  974. X
  975. X    /*
  976. X     * If we kept a backup until now, and we are in patch mode, then we make
  977. X     * the backup file our 'original' file.
  978. X     */
  979. X    if (p_pm && *p_pm)
  980. X    {
  981. X        char *org = (char *)modname(fname, p_pm);
  982. X
  983. X        if (backup != NULL)
  984. X        {
  985. X            struct stat st;
  986. X
  987. X            /*
  988. X             * If the original file does not exist yet
  989. X             * the current backup file becomes the original file
  990. X             */
  991. X            if (org == NULL)
  992. X                EMSG("patchmode: can't save original file");
  993. X            else if (stat(org, &st) < 0)
  994. X            {
  995. X                rename((char *)backup, org);
  996. X                free(backup);            /* don't delete the file */
  997. X                backup = NULL;
  998. X            }
  999. X        }
  1000. X        /*
  1001. X         * If there is no backup file, remember that a (new) file was
  1002. X         * created.
  1003. X         */
  1004. X        else
  1005. X        {
  1006. X            int fd;
  1007. X
  1008. X            if (org == NULL || (fd = open(org, O_CREAT, 0666)) < 0)
  1009. X              EMSG("patchmode: can't touch empty original file");
  1010. X            else
  1011. X              close(fd);
  1012. X        }
  1013. X        if (org != NULL)
  1014. X        {
  1015. X            setperm((char_u *)org, getperm(fname) & 0777);
  1016. X            free(org);
  1017. X        }
  1018. X    }
  1019. X
  1020. X    /*
  1021. X     * Remove the backup unless 'backup' option is set
  1022. X     */
  1023. X    if (!p_bk && backup != NULL && remove((char *)backup) != 0)
  1024. X        EMSG("Can't delete backup file");
  1025. X    
  1026. X    goto nofail;
  1027. X
  1028. Xfail:
  1029. X    --no_wait_return;        /* may wait for return now */
  1030. X#ifdef MSDOS                /* the screen may be messed up by the "insert disk
  1031. X                                in drive b: and hit return" message */
  1032. X    screenclear();
  1033. X#endif
  1034. Xnofail:
  1035. X
  1036. X    free(backup);
  1037. X    free(buffer);
  1038. X
  1039. X    if (errmsg != NULL)
  1040. X    {
  1041. X        filemess(fname, errmsg);
  1042. X        retval = FAIL;
  1043. X    }
  1044. X    return retval;
  1045. X}
  1046. X
  1047. X/*
  1048. X * write_buf: call write() to write a buffer
  1049. X *
  1050. X * return FAIL for failure, OK otherwise
  1051. X */
  1052. X    static int
  1053. Xwrite_buf(fd, buf, len)
  1054. X    int        fd;
  1055. X    char_u    *buf;
  1056. X    int        len;
  1057. X{
  1058. X    int        wlen;
  1059. X
  1060. X    while (len)
  1061. X    {
  1062. X        wlen = write(fd, (char *)buf, (size_t)len);
  1063. X        if (wlen <= 0)                /* error! */
  1064. X            return FAIL;
  1065. X        len -= wlen;
  1066. X        buf += wlen;
  1067. X    }
  1068. X    return OK;
  1069. X}
  1070. X
  1071. X/*
  1072. X * do_mlines() - process mode lines for the current file
  1073. X *
  1074. X * Returns immediately if the "ml" parameter isn't set.
  1075. X */
  1076. Xstatic void     chk_mline __ARGS((linenr_t));
  1077. X
  1078. X    static void
  1079. Xdo_mlines()
  1080. X{
  1081. X    linenr_t        lnum;
  1082. X    int             nmlines;
  1083. X
  1084. X    if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
  1085. X        return;
  1086. X
  1087. X    for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines; ++lnum)
  1088. X        chk_mline(lnum);
  1089. X
  1090. X    for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines &&
  1091. X                            lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
  1092. X        chk_mline(lnum);
  1093. X}
  1094. X
  1095. X/*
  1096. X * chk_mline() - check a single line for a mode string
  1097. X */
  1098. X    static void
  1099. Xchk_mline(lnum)
  1100. X    linenr_t lnum;
  1101. X{
  1102. X    register char_u    *s;
  1103. X    register char_u    *e;
  1104. X    char_u            *cs;            /* local copy of any modeline found */
  1105. X    int                prev;
  1106. X    int                end;
  1107. X
  1108. X    prev = ' ';
  1109. X    for (s = ml_get(lnum); *s != NUL; ++s)
  1110. X    {
  1111. X        if (isspace(prev) && (STRNCMP(s, "vi:", (size_t)3) == 0 || STRNCMP(s, "ex:", (size_t)3) == 0 || STRNCMP(s, "vim:", (size_t)4) == 0))
  1112. X        {
  1113. X            do
  1114. X                ++s;
  1115. X            while (s[-1] != ':');
  1116. X            s = cs = strsave(s);
  1117. X            if (cs == NULL)
  1118. X                break;
  1119. X            end = FALSE;
  1120. X            while (end == FALSE)
  1121. X            {
  1122. X                while (*s == ' ' || *s == TAB)
  1123. X                    ++s;
  1124. X                if (*s == NUL)
  1125. X                    break;
  1126. X                for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
  1127. X                    ;
  1128. X                if (*e == NUL)
  1129. X                    end = TRUE;
  1130. X                *e = NUL;
  1131. X                if (STRNCMP(s, "set ", (size_t)4) == 0) /* "vi:set opt opt opt: foo" */
  1132. X                {
  1133. X                    (void)doset(s + 4);
  1134. X                    break;
  1135. X                }
  1136. X                if (doset(s) == FAIL)        /* stop if error found */
  1137. X                    break;
  1138. X                s = e + 1;
  1139. X            }
  1140. X            free(cs);
  1141. X            break;
  1142. X        }
  1143. X        prev = *s;
  1144. X    }
  1145. X}
  1146. X
  1147. X/*
  1148. X * add extention to filename - change path/fo.o.h to path/fo.o.h.ext or
  1149. X * fo_o_h.ext for MSDOS or when dotfname option reset.
  1150. X *
  1151. X * Assumed that fname is a valid name found in the filesystem we assure that
  1152. X * the return value is a different name and ends in ".ext".
  1153. X * "ext" MUST start with a "." and MUST be at most 4 characters long.
  1154. X * Space for the returned name is allocated, must be freed later.
  1155. X */
  1156. X
  1157. X    char_u *
  1158. Xmodname(fname, ext)
  1159. X    char_u *fname, *ext;
  1160. X{
  1161. X    return buf_modname(curbuf, fname, ext);
  1162. X}
  1163. X
  1164. X    char_u *
  1165. Xbuf_modname(buf, fname, ext)
  1166. X    BUF        *buf;
  1167. X    char_u *fname, *ext;
  1168. X{
  1169. X    char_u            *retval;
  1170. X    register char_u   *s;
  1171. X    register char_u   *ptr;
  1172. X    register int    fnamelen, extlen;
  1173. X    char_u            currentdir[512];
  1174. X
  1175. X    extlen = STRLEN(ext);
  1176. X
  1177. X    /*
  1178. X     * if there is no filename we must get the name of the current directory
  1179. X     * (we need the full path in case :cd is used)
  1180. X     */
  1181. X    if (fname == NULL || *fname == NUL)
  1182. X    {
  1183. X        if (vim_dirname(currentdir, 510) == FAIL || (fnamelen = STRLEN(currentdir)) == 0)
  1184. X            return NULL;
  1185. X        if (!ispathsep(currentdir[fnamelen - 1]))
  1186. X        {
  1187. X            currentdir[fnamelen++] = PATHSEP;
  1188. X            currentdir[fnamelen] = NUL;
  1189. X        }
  1190. X    }
  1191. X    else
  1192. X        fnamelen = STRLEN(fname);
  1193. X    retval = alloc((unsigned) (fnamelen + extlen + 1));
  1194. X    if (retval != NULL)
  1195. X    {
  1196. X        if (fname == NULL || *fname == NUL)
  1197. X            STRCPY(retval, currentdir);
  1198. X        else
  1199. X            STRCPY(retval, fname);
  1200. X        /*
  1201. X         * search backwards until we hit a '/', '\' or ':' replacing all '.' by '_'
  1202. X         * for MSDOS or when dotfname option reset.
  1203. X         * Then truncate what is after the '/', '\' or ':' to 8 characters for MSDOS
  1204. X         * and 26 characters for AMIGA and UNIX.
  1205. X         */
  1206. X        for (ptr = retval + fnamelen; ptr >= retval; ptr--)
  1207. X        {
  1208. X#ifndef MSDOS
  1209. X            if (buf->b_p_sn || buf->b_shortname)
  1210. X#endif
  1211. X                if (*ptr == '.')    /* replace '.' by '_' */
  1212. X                    *ptr = '_';
  1213. X            if (ispathsep(*ptr))
  1214. X                break;
  1215. X        }
  1216. X        ptr++;
  1217. X
  1218. X        /* the filename has at most BASENAMELEN characters. */
  1219. X        if (STRLEN(ptr) > (unsigned)BASENAMELEN)
  1220. X            ptr[BASENAMELEN] = '\0';
  1221. X#ifndef MSDOS
  1222. X        if ((buf->b_p_sn || buf->b_shortname) && STRLEN(ptr) > (unsigned)8)
  1223. X            ptr[8] = '\0';
  1224. X#endif
  1225. X        s = ptr + STRLEN(ptr);
  1226. X
  1227. X        /*
  1228. X         * Append the extention.
  1229. X         * ext must start with '.' and cannot exceed 3 more characters.
  1230. X         */
  1231. X        STRCPY(s, ext);
  1232. X#ifdef MSDOS
  1233. X        if (fname == NULL || *fname == NUL)        /* can't have just the extension */
  1234. X            *s = '_';
  1235. X#endif
  1236. X        if (fname != NULL && STRCMP(fname, retval) == 0)
  1237. X        {
  1238. X            /* after modification still the same name? */
  1239. X            /* we search for a character that can be replaced by '_' */
  1240. X            while (--s >= ptr)
  1241. X            {
  1242. X                if (*s != '_')
  1243. X                {
  1244. X                    *s = '_';
  1245. X                    break;
  1246. X                }
  1247. X            }
  1248. X            if (s < ptr)
  1249. X            {
  1250. X                /* fname was "________.<ext>" how tricky! */
  1251. X                *ptr = 'v';
  1252. X            }
  1253. X        }
  1254. X    }
  1255. X    return retval;
  1256. X}
  1257. X
  1258. X#ifdef WEBB_COMPLETE
  1259. X/* vim_fgets();
  1260. X *
  1261. X * Like fgets(), but if the file line is too long, it is truncated and the
  1262. X * rest of the line is thrown away.  Returns TRUE or FALSE for end-of-file or
  1263. X * not.  The integer pointed to by lnum is incremented.  Note: do not pass
  1264. X * IObuff as the buffer since this is used to read and discard the extra part
  1265. X * of any long lines.
  1266. X */
  1267. X    int
  1268. Xvim_fgets(buf, size, fp, lnum)
  1269. X    char_u *buf;
  1270. X    int size;
  1271. X    FILE *fp;
  1272. X    int *lnum;
  1273. X{
  1274. X    char *eof;
  1275. X
  1276. X    buf[size - 2] = NUL;
  1277. X    eof = fgets((char *)buf, size, fp);
  1278. X    if (buf[size - 2] != NUL && buf[size - 2] != '\n')
  1279. X    {
  1280. X        buf[size - 1] = NUL;        /* Truncate the line */
  1281. X
  1282. X        /* Now throw away the rest of the line: */
  1283. X        do
  1284. X        {
  1285. X            IObuff[IOSIZE - 2] = NUL;
  1286. X            eof = fgets((char *)IObuff, IOSIZE, fp);
  1287. X        } while (IObuff[IOSIZE - 2] != NUL && IObuff[IOSIZE - 2] != '\n');
  1288. X        return FALSE;
  1289. X    }
  1290. X    ++*lnum;
  1291. X    return (eof == NULL);
  1292. X}
  1293. X#endif /* WEBB_COMPLETE */
  1294. END_OF_FILE
  1295.   if test 31526 -ne `wc -c <'vim/src/fileio.c'`; then
  1296.     echo shar: \"'vim/src/fileio.c'\" unpacked with wrong size!
  1297.   fi
  1298.   # end of 'vim/src/fileio.c'
  1299. fi
  1300. if test -f 'vim/src/getchar.c' -a "${1}" != "-c" ; then 
  1301.   echo shar: Will not clobber existing file \"'vim/src/getchar.c'\"
  1302. else
  1303.   echo shar: Extracting \"'vim/src/getchar.c'\" \(33517 characters\)
  1304.   sed "s/^X//" >'vim/src/getchar.c' <<'END_OF_FILE'
  1305. X/* vi:ts=4:sw=4
  1306. X *
  1307. X * VIM - Vi IMproved        by Bram Moolenaar
  1308. X *
  1309. X * Read the file "credits.txt" for a list of people who contributed.
  1310. X * Read the file "uganda.txt" for copying and usage conditions.
  1311. X */
  1312. X
  1313. X/*
  1314. X * getchar.c
  1315. X *
  1316. X * functions related with getting a character from the user/mapping/redo/...
  1317. X *
  1318. X * manipulations with redo buffer and stuff buffer
  1319. X * mappings and abbreviations
  1320. X */
  1321. X
  1322. X#include "vim.h"
  1323. X#include "globals.h"
  1324. X#include "proto.h"
  1325. X#include "param.h"
  1326. X
  1327. X/*
  1328. X * structure used to store one block of the stuff/redo/macro buffers
  1329. X */
  1330. Xstruct bufblock
  1331. X{
  1332. X        struct bufblock *b_next;        /* pointer to next bufblock */
  1333. X        char_u            b_str[1];        /* contents (actually longer) */
  1334. X};
  1335. X
  1336. X#define MINIMAL_SIZE 20                 /* minimal size for b_str */
  1337. X
  1338. X/*
  1339. X * header used for the stuff buffer and the redo buffer
  1340. X */
  1341. Xstruct buffheader
  1342. X{
  1343. X        struct bufblock bh_first;        /* first (dummy) block of list */
  1344. X        struct bufblock *bh_curr;        /* bufblock for appending */
  1345. X        int             bh_index;        /* index for reading */
  1346. X        int             bh_space;        /* space in bh_curr for appending */
  1347. X};
  1348. X
  1349. Xstatic struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
  1350. Xstatic struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
  1351. Xstatic struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
  1352. X
  1353. X    /*
  1354. X     * when block_redo is TRUE redo buffer will not be changed
  1355. X     * used by edit() to repeat insertions and 'V' command for redoing
  1356. X     */
  1357. Xstatic int        block_redo = FALSE;
  1358. X
  1359. X/*
  1360. X * structure used for mapping
  1361. X */
  1362. Xstruct mapblock
  1363. X{
  1364. X    struct mapblock *m_next;        /* next mapblock */
  1365. X    char_u            *m_keys;        /* mapped from */
  1366. X    int                 m_keylen;        /* strlen(m_keys) */
  1367. X    char_u            *m_str;         /* mapped to */
  1368. X    int              m_mode;        /* valid mode */
  1369. X    int                 m_noremap;        /* if non-zero no re-mapping for m_str */
  1370. X};
  1371. X
  1372. Xstatic struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
  1373. X                                    /* first dummy entry in maplist */
  1374. X
  1375. X/*
  1376. X * variables used by vgetorpeek() and flush_buffers()
  1377. X *
  1378. X * typestr contains all characters that are not consumed yet.
  1379. X * The part in front may contain the result of mappings, abbreviations and
  1380. X * @a commands. The lenght of this part is typemaplen.
  1381. X * After it are characters that come from the terminal.
  1382. X * no_abbr_cnt is the number of characters in typestr that should not be
  1383. X * considered for abbreviations.
  1384. X * Some parts of typestr may not be mapped. These parts are remembered in
  1385. X * the noremaplist. 
  1386. X */
  1387. X#define MAXMAPLEN 50                /* maximum length of key sequence to be mapped */
  1388. X                                    /* must be able to hold an Amiga resize report */
  1389. Xstatic char_u    *typestr = NULL;    /* NUL-terminated buffer for typeahead characters */
  1390. Xstatic char_u    typebuf[MAXMAPLEN + 3]; /* initial typestr */
  1391. X
  1392. Xstatic int        typemaplen = 0;        /* number of mapped characters in typestr */
  1393. Xstatic int        no_abbr_cnt = 0;    /* number of chars without abbrev. in typestr */
  1394. X
  1395. X/* 
  1396. X * parts int typestr that should not be mapped are remembered with a list
  1397. X * of noremap structs. Noremaplist is the first.
  1398. X */
  1399. Xstruct noremap
  1400. X{
  1401. X    int                nr_off;            /* offset to not remappable chars */
  1402. X    int                nr_len;            /* number of not remappable chars */
  1403. X    struct noremap    *nr_next;        /* next entry in the list */
  1404. X};
  1405. X
  1406. Xstatic struct noremap noremaplist = {0, 0, NULL};
  1407. X
  1408. Xstatic void        free_buff __ARGS((struct buffheader *));
  1409. Xstatic char_u    *get_bufcont __ARGS((struct buffheader *, int));
  1410. Xstatic void        add_buff __ARGS((struct buffheader *, char_u *));
  1411. Xstatic void        add_num_buff __ARGS((struct buffheader *, long));
  1412. Xstatic void        add_char_buff __ARGS((struct buffheader *, int));
  1413. Xstatic int        read_stuff __ARGS((int));
  1414. Xstatic void        start_stuff __ARGS((void));
  1415. Xstatic int        read_redo __ARGS((int));
  1416. Xstatic void        init_typestr __ARGS((void));
  1417. Xstatic void        gotchars __ARGS((char_u *, int));
  1418. Xstatic int        vgetorpeek __ARGS((int));
  1419. Xstatic void        showmap __ARGS((struct mapblock *));
  1420. X
  1421. X/*
  1422. X * free and clear a buffer
  1423. X */
  1424. X    static void
  1425. Xfree_buff(buf)
  1426. X    struct buffheader *buf;
  1427. X{
  1428. X        register struct bufblock *p, *np;
  1429. X
  1430. X        for (p = buf->bh_first.b_next; p != NULL; p = np)
  1431. X        {
  1432. X                np = p->b_next;
  1433. X                free(p);
  1434. X        }
  1435. X        buf->bh_first.b_next = NULL;
  1436. X}
  1437. X
  1438. X/*
  1439. X * return the contents of a buffer as a single string
  1440. X */
  1441. X    static char_u *
  1442. Xget_bufcont(buffer, dozero)
  1443. X    struct buffheader    *buffer;
  1444. X    int                    dozero;        /* count == zero is not an error */
  1445. X{
  1446. X        long_u            count = 0;
  1447. X        char_u            *p = NULL;
  1448. X        struct bufblock    *bp;
  1449. X
  1450. X/* compute the total length of the string */
  1451. X        for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  1452. X                count += STRLEN(bp->b_str);
  1453. X
  1454. X        if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL)
  1455. X        {
  1456. X                *p = NUL;
  1457. X                for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  1458. X                        strcat((char *)p, (char *)bp->b_str);
  1459. X        }
  1460. X        return (p);
  1461. X}
  1462. X
  1463. X/*
  1464. X * return the contents of the record buffer as a single string
  1465. X *    and clear the record buffer
  1466. X */
  1467. X    char_u *
  1468. Xget_recorded()
  1469. X{
  1470. X    char_u *p;
  1471. X
  1472. X    p = get_bufcont(&recordbuff, TRUE);
  1473. X    free_buff(&recordbuff);
  1474. X    return (p);
  1475. X}
  1476. X
  1477. X/*
  1478. X * return the contents of the redo buffer as a single string
  1479. X */
  1480. X    char_u *
  1481. Xget_inserted()
  1482. X{
  1483. X        return(get_bufcont(&redobuff, FALSE));
  1484. X}
  1485. X
  1486. X/*
  1487. X * add string "s" after the current block of buffer "buf"
  1488. X */
  1489. X    static void
  1490. Xadd_buff(buf, s)
  1491. X    register struct buffheader    *buf;
  1492. X    char_u                        *s;
  1493. X{
  1494. X    struct bufblock *p;
  1495. X    long_u             n;
  1496. X    long_u             len;
  1497. X
  1498. X    if ((n = STRLEN(s)) == 0)                /* don't add empty strings */
  1499. X        return;
  1500. X
  1501. X    if (buf->bh_first.b_next == NULL)        /* first add to list */
  1502. X    {
  1503. X        buf->bh_space = 0;
  1504. X        buf->bh_curr = &(buf->bh_first);
  1505. X    }
  1506. X    else if (buf->bh_curr == NULL)            /* buffer has already been read */
  1507. X    {
  1508. X        EMSG("Add to read buffer");
  1509. X        return;
  1510. X    }
  1511. X    else if (buf->bh_index != 0)
  1512. X        STRCPY(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index);
  1513. X    buf->bh_index = 0;
  1514. X
  1515. X    if (buf->bh_space >= n)
  1516. X    {
  1517. X        strcat((char *)buf->bh_curr->b_str, (char *)s);
  1518. X        buf->bh_space -= n;
  1519. X    }
  1520. X    else
  1521. X    {
  1522. X        if (n < MINIMAL_SIZE)
  1523. X            len = MINIMAL_SIZE;
  1524. X        else
  1525. X            len = n;
  1526. X        p = (struct bufblock *)lalloc((long_u)(sizeof(struct bufblock) + len), TRUE);
  1527. X        if (p == NULL)
  1528. X            return; /* no space, just forget it */
  1529. X        buf->bh_space = len - n;
  1530. X        STRCPY(p->b_str, s);
  1531. X
  1532. X        p->b_next = buf->bh_curr->b_next;
  1533. X        buf->bh_curr->b_next = p;
  1534. X        buf->bh_curr = p;
  1535. X    }
  1536. X    return;
  1537. X}
  1538. X
  1539. X    static void
  1540. Xadd_num_buff(buf, n)
  1541. X    struct buffheader *buf;
  1542. X    long               n;
  1543. X{
  1544. X        char_u    number[32];
  1545. X
  1546. X        sprintf((char *)number, "%ld", n);
  1547. X        add_buff(buf, number);
  1548. X}
  1549. X
  1550. X    static void
  1551. Xadd_char_buff(buf, c)
  1552. X    struct buffheader *buf;
  1553. X    int               c;
  1554. X{
  1555. X        char_u    temp[2];
  1556. X
  1557. X        temp[0] = c;
  1558. X        temp[1] = NUL;
  1559. X        add_buff(buf, temp);
  1560. X}
  1561. X
  1562. X/*
  1563. X * get one character from the stuff buffer
  1564. X * If advance == TRUE go to the next char.
  1565. X */
  1566. X    static int
  1567. Xread_stuff(advance)
  1568. X    int            advance;
  1569. X{
  1570. X    register char_u c;
  1571. X    register struct bufblock *curr;
  1572. X
  1573. X
  1574. X    if (stuffbuff.bh_first.b_next == NULL)    /* buffer is empty */
  1575. X        return NUL;
  1576. X
  1577. X    curr = stuffbuff.bh_first.b_next;
  1578. X    c = curr->b_str[stuffbuff.bh_index];
  1579. X
  1580. X    if (advance)
  1581. X    {
  1582. X        if (curr->b_str[++stuffbuff.bh_index] == NUL)
  1583. X        {
  1584. X            stuffbuff.bh_first.b_next = curr->b_next;
  1585. X            free(curr);
  1586. X            stuffbuff.bh_index = 0;
  1587. X        }
  1588. X    }
  1589. X    return c;
  1590. X}
  1591. X
  1592. X/*
  1593. X * prepare stuff buffer for reading (if it contains something)
  1594. X */
  1595. X    static void
  1596. Xstart_stuff()
  1597. X{
  1598. X    if (stuffbuff.bh_first.b_next != NULL)
  1599. X    {
  1600. X        stuffbuff.bh_curr = &(stuffbuff.bh_first);
  1601. X        stuffbuff.bh_space = 0;
  1602. X    }
  1603. X}
  1604. X
  1605. X/*
  1606. X * check if the stuff buffer is empty
  1607. X */
  1608. X    int
  1609. Xstuff_empty()
  1610. X{
  1611. X    return (stuffbuff.bh_first.b_next == NULL);
  1612. X}
  1613. X
  1614. X/*
  1615. X * Remove the contents of the stuff buffer and the mapped characters in the
  1616. X * typeahead buffer (used in case of an error). If 'typeahead' is true,
  1617. X * flush all typeahead characters (used when interrupted by a CTRL-C).
  1618. X */
  1619. X    void
  1620. Xflush_buffers(typeahead)
  1621. X    int typeahead;
  1622. X{
  1623. X    struct noremap *p;
  1624. X
  1625. X    init_typestr();
  1626. X
  1627. X    start_stuff();
  1628. X    while (read_stuff(TRUE) != NUL)
  1629. X        ;
  1630. X
  1631. X    if (typeahead)            /* remove all typeahead */
  1632. X    {
  1633. X            /*
  1634. X             * We have to get all characters, because we may delete the first
  1635. X             * part of an escape sequence.
  1636. X             * In an xterm we get one char at a time and we have to get them all.
  1637. X             */
  1638. X        while (inchar(typestr, MAXMAPLEN, 10))    
  1639. X            ;
  1640. X        *typestr = NUL;
  1641. X    }
  1642. X    else                    /* remove mapped characters only */
  1643. X        STRCPY(typestr, typestr + typemaplen);
  1644. X    typemaplen = 0;
  1645. X    no_abbr_cnt = 0;
  1646. X    noremaplist.nr_len = 0;
  1647. X    noremaplist.nr_off = 0;
  1648. X    while (noremaplist.nr_next)
  1649. X    {
  1650. X        p = noremaplist.nr_next->nr_next;
  1651. X        free(noremaplist.nr_next);
  1652. X        noremaplist.nr_next = p;
  1653. X    }
  1654. X}
  1655. X
  1656. X    void
  1657. XResetRedobuff()
  1658. X{
  1659. X    if (!block_redo)
  1660. X        free_buff(&redobuff);
  1661. X}
  1662. X
  1663. X    void
  1664. XAppendToRedobuff(s)
  1665. X    char_u           *s;
  1666. X{
  1667. X    if (!block_redo)
  1668. X        add_buff(&redobuff, s);
  1669. X}
  1670. X
  1671. X    void
  1672. XAppendCharToRedobuff(c)
  1673. X    int               c;
  1674. X{
  1675. X    if (!block_redo)
  1676. X        add_char_buff(&redobuff, c);
  1677. X}
  1678. X
  1679. X    void
  1680. XAppendNumberToRedobuff(n)
  1681. X    long             n;
  1682. X{
  1683. X    if (!block_redo)
  1684. X        add_num_buff(&redobuff, n);
  1685. X}
  1686. X
  1687. X    void
  1688. XstuffReadbuff(s)
  1689. X    char_u           *s;
  1690. X{
  1691. X    add_buff(&stuffbuff, s);
  1692. X}
  1693. X
  1694. X    void
  1695. XstuffcharReadbuff(c)
  1696. X    int               c;
  1697. X{
  1698. X    add_char_buff(&stuffbuff, c);
  1699. X}
  1700. X
  1701. X    void
  1702. XstuffnumReadbuff(n)
  1703. X    long    n;
  1704. X{
  1705. X    add_num_buff(&stuffbuff, n);
  1706. X}
  1707. X
  1708. X/*
  1709. X * Read a character from the redo buffer.
  1710. X * The redo buffer is left as it is.
  1711. X * if init is TRUE, prepare for redo, return FAIL if nothing to redo, OK otherwise
  1712. X */
  1713. X    static int
  1714. Xread_redo(init)
  1715. X    int            init;
  1716. X{
  1717. X    static struct bufblock    *bp;
  1718. X    static char_u            *p;
  1719. X    int                        c;
  1720. X
  1721. X    if (init)
  1722. X    {
  1723. X        if ((bp = redobuff.bh_first.b_next) == NULL)
  1724. X            return FAIL;
  1725. X        p = bp->b_str;
  1726. X        return OK;
  1727. X    }
  1728. X    if ((c = *p) != NUL)
  1729. X    {
  1730. X        if (*++p == NUL && bp->b_next != NULL)
  1731. X        {
  1732. X            bp = bp->b_next;
  1733. X            p = bp->b_str;
  1734. X        }
  1735. X    }
  1736. X    return c;
  1737. X}
  1738. X
  1739. X/*
  1740. X * copy the rest of the redo buffer into the stuff buffer (could be done faster)
  1741. X */
  1742. X    void
  1743. Xcopy_redo()
  1744. X{
  1745. X    register int c;
  1746. X
  1747. X    while ((c = read_redo(FALSE)) != NUL)
  1748. X        stuffcharReadbuff(c);
  1749. X}
  1750. X
  1751. Xextern int redo_Visual_busy;        /* this is in normal.c */
  1752. X
  1753. X/*
  1754. X * Stuff the redo buffer into the stuffbuff.
  1755. X * Insert the redo count into the command.
  1756. X * return FAIL for failure, OK otherwise
  1757. X */
  1758. X    int
  1759. Xstart_redo(count)
  1760. X    long count;
  1761. X{
  1762. X    register int c;
  1763. X
  1764. X    if (read_redo(TRUE) == FAIL)    /* init the pointers; return if nothing to redo */
  1765. X        return FAIL;
  1766. X
  1767. X    c = read_redo(FALSE);
  1768. X
  1769. X/* copy the buffer name, if present */
  1770. X    if (c == '"')
  1771. X    {
  1772. X        add_buff(&stuffbuff, (char_u *)"\"");
  1773. X        c = read_redo(FALSE);
  1774. X
  1775. X/* if a numbered buffer is used, increment the number */
  1776. X        if (c >= '1' && c < '9')
  1777. X            ++c;
  1778. X        add_char_buff(&stuffbuff, c);
  1779. X        c = read_redo(FALSE);
  1780. X    }
  1781. X
  1782. X    if (c == 'v')    /* redo Visual */
  1783. X    {
  1784. X        VIsual = curwin->w_cursor;
  1785. X        redo_Visual_busy = TRUE;
  1786. X        c = read_redo(FALSE);
  1787. X    }
  1788. X
  1789. X/* try to enter the count (in place of a previous count) */
  1790. X    if (count)
  1791. X    {
  1792. X        while (isdigit(c))        /* skip "old" count */
  1793. X            c = read_redo(FALSE);
  1794. X        add_num_buff(&stuffbuff, count);
  1795. X    }
  1796. X
  1797. X/* copy from the redo buffer into the stuff buffer */
  1798. X    add_char_buff(&stuffbuff, c);
  1799. X    copy_redo();
  1800. X    return OK;
  1801. X}
  1802. X
  1803. X/*
  1804. X * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
  1805. X * the redo buffer into the stuffbuff.
  1806. X * return FAIL for failure, OK otherwise
  1807. X */
  1808. X    int
  1809. Xstart_redo_ins()
  1810. X{
  1811. X    register int c;
  1812. X
  1813. X    if (read_redo(TRUE) == FAIL)
  1814. X        return FAIL;
  1815. X    start_stuff();
  1816. X
  1817. X/* skip the count and the command character */
  1818. X    while ((c = read_redo(FALSE)) != NUL)
  1819. X    {
  1820. X        c = TO_UPPER(c);
  1821. X        if (strchr("AIRO", c) != NULL)
  1822. X        {
  1823. X            if (c == 'O')
  1824. X                stuffReadbuff(NL_STR);
  1825. X            break;
  1826. X        }
  1827. X    }
  1828. X
  1829. X/* copy the typed text from the redo buffer into the stuff buffer */
  1830. X    copy_redo();
  1831. X    block_redo = TRUE;
  1832. X    return OK;
  1833. X}
  1834. X
  1835. X    void
  1836. Xset_redo_ins()
  1837. X{
  1838. X    block_redo = TRUE;
  1839. X}
  1840. X
  1841. X    void
  1842. Xstop_redo_ins()
  1843. X{
  1844. X    block_redo = FALSE;
  1845. X}
  1846. X
  1847. X/*
  1848. X * Initialize typestr to point to typebuf.
  1849. X * Alloc() cannot be used here: In out-of-memory situations it would
  1850. X * be impossible to type anything.
  1851. X */
  1852. X    static void
  1853. Xinit_typestr()
  1854. X{
  1855. X    if (typestr == NULL)
  1856. X    {
  1857. X        typestr = typebuf;
  1858. X        typebuf[0] = NUL;
  1859. X    }
  1860. X}
  1861. X
  1862. X/*
  1863. X * insert a string in front of the typeahead buffer (for '@' command and vgetorpeek)
  1864. X * return FAIL for failure, OK otherwise
  1865. X */
  1866. X    int
  1867. Xins_typestr(str, noremap)
  1868. X    char_u    *str;
  1869. X    int        noremap;
  1870. X{
  1871. X    register char_u    *s;
  1872. X    register int    newlen;
  1873. X    register int    addlen;
  1874. X
  1875. X    init_typestr();
  1876. X
  1877. X    /*
  1878. X     * In typestr there must always be room for MAXMAPLEN + 3 characters
  1879. X     */
  1880. X    addlen = STRLEN(str);
  1881. X    newlen = STRLEN(typestr) + addlen + MAXMAPLEN + 3;
  1882. X    if (newlen < 0)                /* string is getting too long */
  1883. X    {
  1884. X        emsg(e_toocompl);        /* also calls flush_buffers */
  1885. X        setcursor();
  1886. X        return FAIL;
  1887. X    }
  1888. X    s = alloc(newlen);
  1889. X    if (s == NULL)                /* out of memory */
  1890. X        return FAIL;
  1891. X
  1892. X    STRCPY(s, str);
  1893. X    STRCAT(s, typestr);
  1894. X    if (typestr != typebuf)
  1895. X        free(typestr);
  1896. X    typestr = s;
  1897. X    typemaplen += addlen;        /* the inserted string is not typed */
  1898. X    if (no_abbr_cnt)            /* and not used for abbreviations */
  1899. X        no_abbr_cnt += addlen;
  1900. X    if (noremap)
  1901. X    {
  1902. X        if (noremaplist.nr_off == 0)
  1903. X            noremaplist.nr_len += addlen;
  1904. X        else
  1905. X        {
  1906. X            struct noremap *p;
  1907. X
  1908. X            p = (struct noremap *)alloc((int)sizeof(struct noremap));
  1909. X            if (p != NULL)
  1910. X            {
  1911. X                p->nr_next = noremaplist.nr_next;
  1912. X                p->nr_off = noremaplist.nr_off;
  1913. X                p->nr_len = noremaplist.nr_len;
  1914. X                noremaplist.nr_next = p;
  1915. X                noremaplist.nr_len = addlen;
  1916. X                noremaplist.nr_off = 0;
  1917. X            }
  1918. X        }
  1919. X    }
  1920. X    else if (noremaplist.nr_len)
  1921. X        noremaplist.nr_off += addlen;
  1922. X    return OK;
  1923. X}
  1924. X
  1925. X/*
  1926. X * remove "len" characters from the front of typestr
  1927. X */
  1928. X    void
  1929. Xdel_typestr(len)
  1930. X    int    len;
  1931. X{
  1932. X    struct noremap *p;
  1933. X
  1934. X    STRCPY(typestr, typestr + len);
  1935. X                                        /* remove chars from the buffer */
  1936. X    if ((typemaplen -= len) < 0)        /* adjust typemaplen */
  1937. X        typemaplen = 0;
  1938. X    if ((no_abbr_cnt -= len) < 0)        /* adjust no_abbr_cnt */
  1939. X        no_abbr_cnt = 0;
  1940. X
  1941. X    while (len)                            /* adjust noremaplist */
  1942. X    {
  1943. X        if (noremaplist.nr_off >= len)
  1944. X        {
  1945. X            noremaplist.nr_off -= len;
  1946. X            break;
  1947. X        }
  1948. X        len -= noremaplist.nr_off;
  1949. X        noremaplist.nr_off = 0;
  1950. X        if (noremaplist.nr_len > len)
  1951. X        {
  1952. X            noremaplist.nr_len -= len;
  1953. X            break;
  1954. X        }
  1955. X        len -= noremaplist.nr_len;
  1956. X        p = noremaplist.nr_next;
  1957. X        if (p == NULL)
  1958. X        {
  1959. X            noremaplist.nr_len = 0;
  1960. X            break;
  1961. X        }
  1962. X        noremaplist.nr_next = p->nr_next;
  1963. X        noremaplist.nr_len = p->nr_len;
  1964. X        noremaplist.nr_off = p->nr_off;
  1965. X        free(p);
  1966. X    }
  1967. X}
  1968. X
  1969. Xextern int arrow_used;            /* this is in edit.c */
  1970. X
  1971. X/*
  1972. X * Write typed characters to script file.
  1973. X * If recording is on put the character in the recordbuffer.
  1974. X */
  1975. X    static void
  1976. Xgotchars(s, len)
  1977. X    char_u    *s;
  1978. X    int        len;
  1979. X{
  1980. X    while (len--)
  1981. X    {
  1982. X        updatescript(*s & 255);
  1983. X
  1984. X        if (Recording)
  1985. X            add_char_buff(&recordbuff, (*s & 255));
  1986. X        ++s;
  1987. X    }
  1988. X
  1989. X            /* do not sync in insert mode, unless cursor key has been used */
  1990. X    if (!(State & (INSERT + CMDLINE)) || arrow_used)        
  1991. X        u_sync();
  1992. X}
  1993. X
  1994. X/*
  1995. X * open new script file for ":so!" command
  1996. X * return OK on success, FAIL on error
  1997. X */
  1998. X    int
  1999. Xopenscript(name)
  2000. X    char_u *name;
  2001. X{
  2002. X    int oldcurscript;
  2003. X
  2004. X    if (curscript + 1 == NSCRIPT)
  2005. X    {
  2006. X        emsg(e_nesting);
  2007. X        return FAIL;
  2008. X    }
  2009. X    else
  2010. X    {
  2011. X        if (scriptin[curscript] != NULL)    /* already reading script */
  2012. X            ++curscript;
  2013. X        if ((scriptin[curscript] = fopen((char *)name, READBIN)) == NULL)
  2014. X        {
  2015. X            emsg2(e_notopen, name);
  2016. X            if (curscript)
  2017. X                --curscript;
  2018. X            return FAIL;
  2019. X        }
  2020. X        /*
  2021. X         * With command ":g/pat/so! file" we have to execute the
  2022. X         * commands from the file now.
  2023. X         */
  2024. X        if (global_busy)
  2025. X        {
  2026. X            State = NORMAL;
  2027. X            oldcurscript = curscript;
  2028. X            do
  2029. X            {
  2030. X                normal();
  2031. X                vpeekc();            /* check for end of file */
  2032. X            }
  2033. X            while (scriptin[oldcurscript]);
  2034. X            State = CMDLINE;
  2035. X        }
  2036. X    }
  2037. X    return OK;
  2038. X}
  2039. X
  2040. X/*
  2041. X * updatescipt() is called when a character can be written into the script file
  2042. X * or when we have waited some time for a character (c == 0)
  2043. X *
  2044. X * All the changed memfiles are synced if c == 0 or when the number of typed
  2045. X * characters reaches 'updatecount'.
  2046. X */
  2047. X    void
  2048. Xupdatescript(c)
  2049. X    int c;
  2050. X{
  2051. X    static int        count = 0;
  2052. X
  2053. X    if (c && scriptout)
  2054. X        putc(c, scriptout);
  2055. X    if (c == 0 || ++count >= p_uc)
  2056. X    {
  2057. X        ml_sync_all(c == 0);
  2058. X        count = 0;
  2059. X    }
  2060. X}
  2061. X
  2062. X#define NEEDMORET 9999        /* value for incomplete mapping or key-code */
  2063. X
  2064. X/*
  2065. X * get a character: 1. from the stuffbuffer
  2066. X *                    2. from the typeahead buffer
  2067. X *                    3. from the user
  2068. X *
  2069. X * KeyTyped is set to TRUE in the case the user typed the key.
  2070. X * vgetc() (advance is TRUE): really get the character.
  2071. X * vpeekc() (advance is FALSE): just look whether there is a character available.
  2072. X */
  2073. X    int
  2074. Xvgetc()
  2075. X{
  2076. X    return (vgetorpeek(TRUE));
  2077. X}
  2078. X
  2079. X    int
  2080. Xvpeekc()
  2081. X{
  2082. X    return (vgetorpeek(FALSE));
  2083. X}
  2084. X
  2085. X    static int
  2086. Xvgetorpeek(advance)
  2087. X    int        advance;
  2088. X{
  2089. X    register int    c;
  2090. X    int                n = 0;        /* init for GCC */
  2091. X    int                len;
  2092. X#ifdef AMIGA
  2093. X    char_u            *s;
  2094. X#endif
  2095. X    register struct mapblock *mp;
  2096. X    int                timedout = FALSE;        /* waited for more than 1 second
  2097. X                                                for mapping to complete */
  2098. X    int                mapdepth = 0;            /* check for recursive mapping */
  2099. X    int                mode_deleted = FALSE;    /* set when mode has been deleted */
  2100. X
  2101. X    init_typestr();
  2102. X    start_stuff();
  2103. X    if (typemaplen == 0)
  2104. X        Exec_reg = FALSE;
  2105. X    do
  2106. X    {
  2107. X        c = read_stuff(advance);
  2108. X        if (c != NUL && !got_int)
  2109. X            KeyTyped = FALSE;
  2110. X        else
  2111. X        {
  2112. X            /*
  2113. X             * Loop until we either find a matching mapped key, or we
  2114. X             * are sure that it is not a mapped key.
  2115. X             * If a mapped key sequence is found we go back to the start to
  2116. X             * try re-mapping.
  2117. X             */
  2118. X
  2119. X            for (;;)
  2120. X            {
  2121. X                len = STRLEN(typestr);
  2122. X                breakcheck();                /* check for CTRL-C */
  2123. X                if (got_int)
  2124. X                {
  2125. X                    c = inchar(typestr, MAXMAPLEN, 0);    /* flush all input */
  2126. X                    /*
  2127. X                     * If inchar returns TRUE (script file was active) or we are
  2128. X                     * inside a mapping, get out of insert mode.
  2129. X                     * Otherwise we behave like having gotten a CTRL-C.
  2130. X                     * As a result typing CTRL-C in insert mode will
  2131. X                     * really insert a CTRL-C.
  2132. X                     */
  2133. X                    if ((c || typemaplen) && (State & (INSERT + CMDLINE)))
  2134. X                        c = ESC;
  2135. X                    else
  2136. X                        c = Ctrl('C');
  2137. X                    flush_buffers(TRUE);        /* flush all typeahead */
  2138. X                    break;
  2139. X                }
  2140. X                else if (len > 0)    /* see if we have a mapped key sequence */
  2141. X                {
  2142. X                    /*
  2143. X                     * walk through the maplist until we find an
  2144. X                     * entry that matches.
  2145. X                     *
  2146. X                     * Don't look for mappings if:
  2147. X                     * - timed out
  2148. X                     * - typestr[0] should not be remapped
  2149. X                     * - in insert or cmdline mode and 'paste' option set
  2150. X                     * - waiting for "hit return to continue" and CR or SPACE typed
  2151. X                     */
  2152. X                    mp = NULL;
  2153. X                    if (!timedout && (typemaplen == 0 || (p_remap &&
  2154. X                            (noremaplist.nr_len == 0 || noremaplist.nr_off != 0)))
  2155. X                            && !((State & (INSERT + CMDLINE)) && p_paste)
  2156. X                            && !(State == HITRETURN && (typestr[0] == CR || typestr[0] == ' ')))
  2157. X                    {
  2158. X                        for (mp = maplist.m_next; mp; mp = mp->m_next)
  2159. X                        {
  2160. X                            if ((mp->m_mode & ABBREV) || !(mp->m_mode & State))
  2161. X                                continue;
  2162. X                            n = mp->m_keylen;
  2163. X                            if (noremaplist.nr_off != 0 && n > noremaplist.nr_off)
  2164. X                                continue;
  2165. X                            if (!STRNCMP(mp->m_keys, typestr, (size_t)(n > len ? len : n)))
  2166. X                                break;
  2167. X                        }
  2168. X                    }
  2169. X                    if (mp == NULL)                    /* no match found */
  2170. X                    {
  2171. X                            /*
  2172. X                             * check if we have a terminal code, when
  2173. X                             *    mapping is allowed,
  2174. X                             *  keys have not been mapped,
  2175. X                             *    and not an ESC sequence, not in insert mode or
  2176. X                             *        p_ek is on,
  2177. X                             *    and when not timed out,
  2178. X                             */
  2179. X                        if (State != NOMAPPING &&
  2180. X                                /* typemaplen == 0 && */ /* allow mapped keys anyway */
  2181. X                                (typestr[0] != ESC || p_ek || !(State & INSERT)) &&
  2182. X                                !timedout)
  2183. X                            n = check_termcode(typestr);
  2184. X                        else
  2185. X                            n = 0;
  2186. X                        if (n == 0)        /* no matching terminal code */
  2187. X                        {
  2188. X#ifdef AMIGA                    /* check for window bounds report */
  2189. X                            if (typemaplen == 0 && (typestr[0] & 0xff) == CSI)
  2190. X                            {
  2191. X                                for (s = typestr + 1; isdigit(*s) || *s == ';' || *s == ' '; ++s)
  2192. X                                    ;
  2193. X                                if (*s == 'r' || *s == '|')    /* found one */
  2194. X                                {
  2195. X                                    STRCPY(typestr, s + 1);
  2196. X                                    set_winsize(0, 0, FALSE);        /* get size and redraw screen */
  2197. X                                    continue;
  2198. X                                }
  2199. X                                if (*s == NUL)        /* need more characters */
  2200. X                                    n = -1;
  2201. X                            }
  2202. X                            if (n != -1)            /* got a single character */
  2203. X#endif
  2204. X                            {
  2205. X                                c = typestr[0] & 255;
  2206. X                                if (typemaplen)
  2207. X                                    KeyTyped = FALSE;
  2208. X                                else
  2209. X                                {
  2210. X                                    KeyTyped = TRUE;
  2211. X                                    if (advance)    /* write char to script file(s) */
  2212. X                                        gotchars(typestr, 1);
  2213. X                                }
  2214. X                                if (advance)        /* remove chars from typestr */
  2215. X                                    del_typestr(1);
  2216. X                                break;        /* got character, break for loop */
  2217. X                            }
  2218. X                        }
  2219. X                        if (n > 0)        /* full matching terminal code */
  2220. X                            continue;    /* try mapping again */
  2221. X
  2222. X                        /* partial match: get some more characters */
  2223. X                        n = NEEDMORET;
  2224. X                    }
  2225. X                    if (n <= len)        /* complete match */
  2226. X                    {
  2227. X                        if (n > typemaplen)        /* write chars to script file(s) */
  2228. X                            gotchars(typestr + typemaplen, n - typemaplen);
  2229. X
  2230. X                        del_typestr(n);    /* remove the mapped keys */
  2231. X
  2232. X                        /*
  2233. X                         * Put the replacement string in front of mapstr.
  2234. X                         * The depth check catches ":map x y" and ":map y x".
  2235. X                         */
  2236. X                        if (++mapdepth == 1000)
  2237. X                        {
  2238. X                            EMSG("recursive mapping");
  2239. X                            if (State == CMDLINE)
  2240. X                                redrawcmdline();
  2241. X                            else
  2242. X                                setcursor();
  2243. X                            flush_buffers(FALSE);
  2244. X                            mapdepth = 0;        /* for next one */
  2245. X                            c = -1;
  2246. X                            break;
  2247. X                        }
  2248. X                        if (ins_typestr(mp->m_str, mp->m_noremap) == FAIL)
  2249. X                        {
  2250. X                            c = -1;
  2251. X                            break;
  2252. X                        }
  2253. X                        continue;
  2254. X                    }
  2255. X                }
  2256. X                /*
  2257. X                 * special case: if we get an <ESC> in insert mode and there are
  2258. X                 * no more characters at once, we pretend to go out of insert mode.
  2259. X                 * This prevents the one second delay after typing an <ESC>.
  2260. X                 * If we get something after all, we may have to redisplay the
  2261. X                 * mode. That the cursor is in the wrong place does not matter.
  2262. X                 */
  2263. X                c = 0;
  2264. X                if (advance && len == 1 && typestr[0] == ESC && typemaplen == 0 && (State & INSERT) && (p_timeout || (n == NEEDMORET && p_ttimeout)) && (c = inchar(typestr + len, 2, 0)) == 0)
  2265. X                {
  2266. X                    if (p_smd)
  2267. X                    {
  2268. X                        delmode();
  2269. X                        mode_deleted = TRUE;
  2270. X                    }
  2271. X                    if (curwin->w_cursor.col != 0)    /* move cursor one left if possible */
  2272. X                    {
  2273. X                        if (curwin->w_col)
  2274. X                        {
  2275. X                            if (did_ai)
  2276. X                            {
  2277. X                                if (curwin->w_p_nu)
  2278. X                                    curwin->w_col = 8;
  2279. X                                else
  2280. X                                    curwin->w_col = 0;
  2281. X                            }
  2282. X                            else
  2283. X                                --curwin->w_col;
  2284. X                        }
  2285. X                        else if (curwin->w_p_wrap && curwin->w_row)
  2286. X                        {
  2287. X                                --curwin->w_row;
  2288. X                                curwin->w_col = Columns - 1;
  2289. X                        }
  2290. X                    }
  2291. X                    setcursor();
  2292. X                    flushbuf();
  2293. X                }
  2294. X                len += c;
  2295. X
  2296. X                if (len >= typemaplen + MAXMAPLEN)    /* buffer full, don't map */
  2297. X                {
  2298. X                    timedout = TRUE;
  2299. X                    continue;
  2300. X                }
  2301. X                c = inchar(typestr + len, typemaplen + MAXMAPLEN - len, !advance ? 0 : ((len == 0 || !(p_timeout || (p_ttimeout && n == NEEDMORET))) ? -1 : (int)p_tm));
  2302. X                if (c <= NUL)        /* no character available */
  2303. X                {
  2304. X                    if (!advance)
  2305. X                        break;
  2306. X                    if (len)                /* timed out */
  2307. X                    {
  2308. X                        timedout = TRUE;
  2309. X                        continue;
  2310. X                    }
  2311. X                }
  2312. X            }        /* for (;;) */
  2313. X        }        /* if (!character from stuffbuf) */
  2314. X
  2315. X                        /* if advance is FALSE don't loop on NULs */
  2316. X    } while (c < 0 || (advance && c == NUL));
  2317. X
  2318. X    /*
  2319. X     * The "INSERT" message is taken care of here:
  2320. X     *   if we return an ESC the message is deleted
  2321. X     *   if we don't return an ESC but deleted the message before, redisplay it
  2322. X     */
  2323. X    if (p_smd && (State & INSERT))
  2324. X    {
  2325. X        if (c == ESC && !mode_deleted)
  2326. X            delmode();
  2327. X        else if (c != ESC && mode_deleted)
  2328. X            showmode();
  2329. X    }
  2330. X
  2331. X    return c;
  2332. X}
  2333. X
  2334. X/*
  2335. X * map[!]                    : show all key mappings
  2336. X * map[!] {lhs}                : show key mapping for {lhs}
  2337. X * map[!] {lhs} {rhs}        : set key mapping for {lhs} to {rhs}
  2338. X * noremap[!] {lhs} {rhs}    : same, but no remapping for {rhs}
  2339. X * unmap[!] {lhs}            : remove key mapping for {lhs}
  2340. X * abbr                        : show all abbreviations
  2341. X * abbr {lhs}                : show abbreviations for {lhs}
  2342. X * abbr {lhs} {rhs}            : set abbreviation for {lhs} to {rhs}
  2343. X * noreabbr {lhs} {rhs}        : same, but no remapping for {rhs}
  2344. X * unabbr {lhs}                : remove abbreviation for {lhs}
  2345. X *
  2346. X * maptype == 1 for unmap command, 2 for noremap command.
  2347. X *
  2348. X * keys is pointer to any arguments.
  2349. X *
  2350. X * for :map      mode is NORMAL 
  2351. X * for :map!  mode is INSERT + CMDLINE
  2352. X * for :cmap  mode is CMDLINE
  2353. X * for :imap  mode is INSERT 
  2354. X * for :abbr  mode is INSERT + CMDLINE + ABBREV
  2355. X * for :iabbr mode is INSERT + ABBREV
  2356. X * for :cabbr mode is CMDLINE + ABBREV
  2357. X * 
  2358. X * Return 0 for success
  2359. X *          1 for invalid arguments
  2360. X *          2 for no match
  2361. X *          3 for ambiguety
  2362. X *          4 for out of mem
  2363. X */
  2364. X    int
  2365. Xdomap(maptype, keys, mode)
  2366. X    int        maptype;
  2367. X    char_u    *keys;
  2368. X    int        mode;
  2369. X{
  2370. X    struct mapblock        *mp, *mprev;
  2371. X    char_u                *arg;
  2372. X    char_u                *p;
  2373. X    int                    n = 0;            /* init for GCC */
  2374. X    int                    len = 0;        /* init for GCC */
  2375. X    char_u                *newstr;
  2376. X    int                    hasarg;
  2377. X    int                    haskey;
  2378. X    int                    did_it = FALSE;
  2379. X    int                    abbrev = 0;
  2380. X    int                    round;
  2381. X
  2382. X    if (mode & ABBREV)        /* not a mapping but an abbreviation */
  2383. X    {
  2384. X        abbrev = ABBREV;
  2385. X        mode &= ~ABBREV;
  2386. X    }
  2387. X/*
  2388. X * find end of keys and remove CTRL-Vs in it
  2389. X * with :unmap white space is included in the keys, no argument possible
  2390. X */
  2391. X    p = keys;
  2392. X    while (*p && (maptype == 1 || !iswhite(*p)))
  2393. X    {
  2394. X        if (*p == Ctrl('V') && p[1] != NUL)
  2395. X            STRCPY(p, p + 1);            /* remove CTRL-V */
  2396. X        ++p;
  2397. X    }
  2398. X    if (*p != NUL)
  2399. X        *p++ = NUL;
  2400. X    skipspace(&p);
  2401. X    arg = p;
  2402. X    hasarg = (*arg != NUL);
  2403. X    haskey = (*keys != NUL);
  2404. X
  2405. X        /* check for :unmap without argument */
  2406. X    if (maptype == 1 && !haskey)    
  2407. X        return 1;
  2408. X
  2409. X/*
  2410. X * remove CTRL-Vs from argument
  2411. X */
  2412. X    while (*p)
  2413. X    {
  2414. X        if (*p == Ctrl('V') && p[1] != NUL)
  2415. X            STRCPY(p, p + 1);            /* remove CTRL-V */
  2416. X        ++p;
  2417. X    }
  2418. X
  2419. X/*
  2420. X * check arguments and translate function keys
  2421. X */
  2422. X    if (haskey)
  2423. X    {
  2424. X        if (*keys == '#' && isdigit(*(keys + 1)))    /* function key */
  2425. X        {
  2426. X            if (*++keys == '0')
  2427. X                *keys = K_F10;
  2428. X            else
  2429. X                *keys += K_F1 - '1';
  2430. X        }
  2431. X        len = STRLEN(keys);
  2432. X        if (len > MAXMAPLEN)            /* maximum lenght of MAXMAPLEN chars */
  2433. X            return 1;
  2434. X
  2435. X        /*
  2436. X         * abbreviation must end in id-char
  2437. X         * rest must be all id-char or all non-id-char
  2438. X         */
  2439. X        if (abbrev)
  2440. X        {
  2441. X            if (!isidchar(*(keys + len - 1)))        /* does not end in id char */
  2442. X                return 1;
  2443. X            for (n = 0; n < len - 2; ++n)
  2444. X                if (isidchar(*(keys + n)) != isidchar(*(keys + len - 2)))
  2445. X                    return 1;
  2446. X        }
  2447. X    }
  2448. X
  2449. X    if (haskey && hasarg && abbrev)        /* if we will add an abbreviation */
  2450. X        no_abbr = FALSE;                /* reset flag that indicates there are
  2451. X                                                            no abbreviations */
  2452. X
  2453. X    if (!haskey || (maptype != 1 && !hasarg))
  2454. X        msg_start();
  2455. X/*
  2456. X * Find an entry in the maplist that matches.
  2457. X * For :unmap we may loop two times: once to try to unmap an entry with a
  2458. X * matching 'from' part, a second time, if the first fails, to unmap an
  2459. X * entry with a matching 'to' part. This was done to allow ":ab foo bar" to be
  2460. X * unmapped by typing ":unab foo", where "foo" will be replaced by "bar" because
  2461. X * of the abbreviation.
  2462. X */
  2463. X    for (round = 0; (round == 0 || maptype == 1) && round <= 1 && !did_it && !got_int; ++round)
  2464. X    {
  2465. X        for (mp = maplist.m_next, mprev = &maplist; mp && !got_int; mprev = mp, mp = mp->m_next)
  2466. X        {
  2467. X                                        /* skip entries with wrong mode */
  2468. X            if (!(mp->m_mode & mode) || (mp->m_mode & ABBREV) != abbrev)
  2469. X                continue;
  2470. X            if (!haskey)                        /* show all entries */
  2471. X            {
  2472. X                showmap(mp);
  2473. X                did_it = TRUE;
  2474. X            }
  2475. X            else                                /* do we have a match? */
  2476. X            {
  2477. X                if (round)        /* second round: try 'to' string for unmap */
  2478. X                {
  2479. X                    n = STRLEN(mp->m_str);
  2480. X                    p = mp->m_str;
  2481. X                }
  2482. X                else
  2483. X                {
  2484. X                    n = mp->m_keylen;
  2485. X                    p = mp->m_keys;
  2486. X                }
  2487. X                if (!STRNCMP(p, keys, (size_t)(n < len ? n : len)))
  2488. X                {
  2489. X                    if (maptype == 1)            /* delete entry */
  2490. X                    {
  2491. X                        if (n != len)            /* not a full match */
  2492. X                            continue;
  2493. X                        /*
  2494. X                         * We reset the indicated mode bits. If nothing is left the
  2495. X                         * entry is deleted below.
  2496. X                         */
  2497. X                        mp->m_mode &= (~mode | ABBREV);
  2498. X                        did_it = TRUE;            /* remember that we did something */
  2499. X                    }
  2500. X                    else if (!hasarg)            /* show matching entry */
  2501. X                    {
  2502. X                        showmap(mp);
  2503. X                        did_it = TRUE;
  2504. X                    }
  2505. X                    else if (n != len)            /* new entry is ambigious */
  2506. X                    {
  2507. X                        if (abbrev)                /* for abbreviations that's ok */
  2508. X                            continue;
  2509. X                        return 3;
  2510. X                    }
  2511. X                    else
  2512. X                    {
  2513. X                        mp->m_mode &= (~mode | ABBREV);        /* remove mode bits */
  2514. X                        if (!(mp->m_mode & ~ABBREV) && !did_it)    /* reuse existing entry */
  2515. X                        {
  2516. X                            newstr = strsave(arg);
  2517. X                            if (newstr == NULL)
  2518. X                                return 4;            /* no mem */
  2519. X                            free(mp->m_str);
  2520. X                            mp->m_str = newstr;
  2521. X                            mp->m_noremap = maptype;
  2522. X                            mp->m_mode = mode + abbrev;
  2523. X                            did_it = TRUE;
  2524. X                        }
  2525. X                    }
  2526. X                    if (!(mp->m_mode & ~ABBREV))        /* entry can be deleted */
  2527. X                    {
  2528. X                        free(mp->m_keys);
  2529. X                        free(mp->m_str);
  2530. X                        mprev->m_next = mp->m_next;
  2531. X                        free(mp);
  2532. X                        mp = mprev;                    /* continue with next entry */
  2533. X                    }
  2534. X                }
  2535. X            }
  2536. X        }
  2537. X    }
  2538. X
  2539. X    if (maptype == 1)                        /* delete entry */
  2540. X    {
  2541. X        if (did_it)
  2542. X            return 0;                        /* removed OK */
  2543. X        else
  2544. X            return 2;                        /* no match */
  2545. X    }
  2546. X
  2547. X    if (!haskey || !hasarg)                    /* print entries */
  2548. X    {
  2549. X        if (did_it)
  2550. X            msg_end();
  2551. X        else if (abbrev)
  2552. X            MSG("No abbreviation found");
  2553. X        else
  2554. X            MSG("No mapping found");
  2555. X        return 0;                            /* listing finished */
  2556. X    }
  2557. X
  2558. X    if (did_it)                    /* have added the new entry already */
  2559. X        return 0;
  2560. X/*
  2561. X * get here when we have to add a new entry
  2562. X */
  2563. X        /* allocate a new entry for the maplist */
  2564. X    mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
  2565. X    if (mp == NULL)
  2566. X        return 4;            /* no mem */
  2567. X    mp->m_keys = strsave(keys);
  2568. X    mp->m_str = strsave(arg);
  2569. X    if (mp->m_keys == NULL || mp->m_str == NULL)
  2570. X    {
  2571. X        free(mp->m_keys);
  2572. X        free(mp->m_str);
  2573. X        free(mp);
  2574. X        return 4;        /* no mem */
  2575. X    }
  2576. X    mp->m_keylen = STRLEN(mp->m_keys);
  2577. X    mp->m_noremap = maptype;
  2578. X    mp->m_mode = mode + abbrev;
  2579. X
  2580. X    /* add the new entry in front of the maplist */
  2581. X    mp->m_next = maplist.m_next;
  2582. X    maplist.m_next = mp;
  2583. X
  2584. X    return 0;                /* added OK */
  2585. X}
  2586. X
  2587. X    static void
  2588. Xshowmap(mp)
  2589. X    struct mapblock *mp;
  2590. X{
  2591. X    int len;
  2592. X
  2593. X    msg_pos(-1, 0);                        /* always start in column 0 */
  2594. X    if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
  2595. X        msg_outstr((char_u *)"! ");
  2596. X    else if (mp->m_mode & INSERT)
  2597. X        msg_outstr((char_u *)"i ");
  2598. X    else if (mp->m_mode & CMDLINE)
  2599. X        msg_outstr((char_u *)"c ");
  2600. X    len = msg_outtrans(mp->m_keys, -1);    /* get length of what we have written */
  2601. X    do
  2602. X    {
  2603. X        msg_outchar(' ');                /* padd with blanks */
  2604. X        ++len;
  2605. X    } while (len < 12);
  2606. X    if (mp->m_noremap)
  2607. X        msg_outchar('*');
  2608. X    else
  2609. X        msg_outchar(' ');
  2610. X    msg_outtrans(mp->m_str, -1);
  2611. X    msg_outchar('\n');
  2612. X    flushbuf();                            /* show one line at a time */
  2613. X}
  2614. X
  2615. X/*
  2616. X * Check for an abbreviation.
  2617. X * Cursor is at ptr[col]. When inserting, mincol is where insert started.
  2618. X * "c" is the character typed before check_abbr was called.
  2619. X *
  2620. X * Historic vi practice: The last character of an abbreviation must be an id
  2621. X * character ([a-zA-Z0-9_]). The characters in front of it must be all id
  2622. X * characters or all non-id characters. This allows for abbr. "#i" to "#include".
  2623. X *
  2624. X * return TRUE if there is an abbreviation, FALSE if not
  2625. X */
  2626. X    int
  2627. Xcheck_abbr(c, ptr, col, mincol)
  2628. X    int        c;
  2629. X    char_u    *ptr;
  2630. X    int        col;
  2631. X    int        mincol;
  2632. X{
  2633. X    int                len;
  2634. X    int                j;
  2635. X    char_u            tb[3];
  2636. X    struct mapblock *mp;
  2637. X    int                is_id = TRUE;
  2638. X
  2639. X    if (no_abbr_cnt)        /* abbrev. are not recursive */
  2640. X        return FALSE;
  2641. X
  2642. X    if (col == 0 || !isidchar(ptr[col - 1]))    /* cannot be an abbr. */
  2643. X        return FALSE;
  2644. X
  2645. X    if (col > 1)
  2646. X        is_id = isidchar(ptr[col - 2]);
  2647. X    for (len = col - 1; len > 0 && !isspace(ptr[len - 1]) &&
  2648. X                                is_id == isidchar(ptr[len - 1]); --len)
  2649. X        ;
  2650. X
  2651. X    if (len < mincol)
  2652. X        len = mincol;
  2653. X    if (len < col)                /* there is a word in front of the cursor */
  2654. X    {
  2655. X        ptr += len;
  2656. X        len = col - len;
  2657. X        for (mp = maplist.m_next; mp; mp = mp->m_next)
  2658. X        {
  2659. X                    /* find entries with right mode and keys */
  2660. X            if ((mp->m_mode & ABBREV) == ABBREV &&
  2661. X                        (mp->m_mode & State) &&
  2662. X                        mp->m_keylen == len &&
  2663. X                        !STRNCMP(mp->m_keys, ptr, (size_t)len))
  2664. X                break;
  2665. X        }
  2666. X        if (mp)                                /* found a match */
  2667. X        {
  2668. X            j = 0;
  2669. X            if (c < 0x100 && (c < ' ' || c > '~'))
  2670. X                tb[j++] = Ctrl('V');        /* special char needs CTRL-V */
  2671. X            tb[j++] = c;
  2672. X            tb[j] = NUL;
  2673. X            (void)ins_typestr(tb, TRUE);                    /* insert the last typed char */
  2674. X            (void)ins_typestr(mp->m_str, mp->m_noremap);    /* insert the to string */
  2675. X            no_abbr_cnt += STRLEN(mp->m_str) + j;    /* no abbrev. for these chars */
  2676. X            while (len--)
  2677. X                (void)ins_typestr((char_u *)"\b", TRUE);    /* delete the from string */
  2678. X            return TRUE;
  2679. X        }
  2680. X    }
  2681. X    return FALSE;
  2682. X}
  2683. X
  2684. X/*
  2685. X * Write map commands for the current mappings to an .exrc file.
  2686. X * Return FAIL on error, OK otherwise.
  2687. X */
  2688. X    int
  2689. Xmakemap(fd)
  2690. X    FILE *fd;
  2691. X{
  2692. X    struct mapblock *mp;
  2693. X    char_u            c1;
  2694. X    char_u             *p;
  2695. X
  2696. X    for (mp = maplist.m_next; mp; mp = mp->m_next)
  2697. X    {
  2698. X        c1 = NUL;
  2699. X        p = (char_u *)"map";
  2700. X        switch (mp->m_mode)
  2701. X        {
  2702. X        case NORMAL:
  2703. X            break;
  2704. X        case CMDLINE + INSERT:
  2705. X            p = (char_u *)"map!";
  2706. X            break;
  2707. X        case CMDLINE:
  2708. X            c1 = 'c';
  2709. X            break;
  2710. X        case INSERT:
  2711. X            c1 = 'i';
  2712. X            break;
  2713. X        case INSERT + CMDLINE + ABBREV:
  2714. X            p = (char_u *)"abbr";
  2715. X            break;
  2716. X        case CMDLINE + ABBREV:
  2717. X            c1 = 'c';
  2718. X            p = (char_u *)"abbr";
  2719. X            break;
  2720. X        case INSERT + ABBREV:
  2721. X            c1 = 'i';
  2722. X            p = (char_u *)"abbr";
  2723. X            break;
  2724. X        default:
  2725. X            EMSG("makemap: Illegal mode");
  2726. X            return FAIL;
  2727. X        }
  2728. X        if (c1 && putc(c1, fd) < 0)
  2729. X            return FAIL;
  2730. X        if (mp->m_noremap && fprintf(fd, "nore") < 0)
  2731. X            return FAIL;
  2732. X        if (fprintf(fd, (char *)p) < 0)
  2733. X            return FAIL;
  2734. X
  2735. X        if (    putc(' ', fd) < 0 || putescstr(fd, mp->m_keys, FALSE) == FAIL ||
  2736. X                putc(' ', fd) < 0 || putescstr(fd, mp->m_str, FALSE) == FAIL ||
  2737. X#ifdef MSDOS
  2738. X                putc('\r', fd) < 0 ||
  2739. X#endif
  2740. X                putc('\n', fd) < 0)
  2741. X            return FAIL;
  2742. X    }
  2743. X    return OK;
  2744. X}
  2745. X
  2746. X/*
  2747. X * write escape string to file
  2748. X *
  2749. X * return FAIL for failure, OK otherwise
  2750. X */
  2751. X    int
  2752. Xputescstr(fd, str, set)
  2753. X    FILE        *fd;
  2754. X    char_u        *str;
  2755. X    int            set;        /* TRUE for makeset, FALSE for makemap */
  2756. X{
  2757. X    for ( ; *str; ++str)
  2758. X    {
  2759. X        /*
  2760. X         * some characters have to be escaped with CTRL-V to
  2761. X         * prevent them from misinterpreted in DoOneCmd().
  2762. X         * A space has to be escaped with a backslash to
  2763. X         * prevent it to be misinterpreted in doset().
  2764. X         */
  2765. X        if (*str < ' ' || *str > '~' || (*str == ' ' && !set))
  2766. X        {
  2767. X            if (putc(Ctrl('V'), fd) < 0)
  2768. X                return FAIL;
  2769. X        }
  2770. X        else if ((set && *str == ' ') || *str == '|')
  2771. X        {
  2772. X            if (putc('\\', fd) < 0)
  2773. X                return FAIL;
  2774. X        }
  2775. X        if (putc(*str, fd) < 0)
  2776. X            return FAIL;
  2777. X    }
  2778. X    return OK;
  2779. X}
  2780. END_OF_FILE
  2781.   if test 33517 -ne `wc -c <'vim/src/getchar.c'`; then
  2782.     echo shar: \"'vim/src/getchar.c'\" unpacked with wrong size!
  2783.   fi
  2784.   # end of 'vim/src/getchar.c'
  2785. fi
  2786. echo shar: End of archive 15 \(of 26\).
  2787. cp /dev/null ark15isdone
  2788. MISSING=""
  2789. 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
  2790.     if test ! -f ark${I}isdone ; then
  2791.     MISSING="${MISSING} ${I}"
  2792.     fi
  2793. done
  2794. if test "${MISSING}" = "" ; then
  2795.     echo You have unpacked all 26 archives.
  2796.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2797. else
  2798.     echo You still must unpack the following archives:
  2799.     echo "        " ${MISSING}
  2800. fi
  2801. exit 0
  2802. exit 0 # Just in case...
  2803.