home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume41 / vim / part11 < prev    next >
Encoding:
Text File  |  1993-12-20  |  49.3 KB  |  1,986 lines

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i061:  vim - Vi IMitation editor, v2.0, Part11/25
  4. Message-ID: <1993Dec21.035009.28305@sparky.sterling.com>
  5. X-Md4-Signature: 432d0dab88c0af3a746dd3ab36d0ff13
  6. Keywords: utility, editor, vi, vim
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: Sterling Software
  9. Date: Tue, 21 Dec 1993 03:50:09 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 61
  14. Archive-name: vim/part11
  15. Environment: UNIX, AMIGA, MS-DOS
  16. Supersedes: vim: Volume 37, Issue 1-24
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 11 (of 25)."
  25. # Contents:  vim/src/fileio.c vim/src/storage.c
  26. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:05 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'vim/src/fileio.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'vim/src/fileio.c'\"
  30. else
  31. echo shar: Extracting \"'vim/src/fileio.c'\" \(22193 characters\)
  32. sed "s/^X//" >'vim/src/fileio.c' <<'END_OF_FILE'
  33. X/* vi:ts=4:sw=4
  34. X *
  35. X * VIM - Vi IMproved
  36. X *
  37. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  38. X *                            Tim Thompson            twitch!tjt
  39. X *                            Tony Andrews            onecom!wldrdg!tony 
  40. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  41. X */
  42. X
  43. X/*
  44. X * fileio.c: read from and write to a file
  45. X */
  46. X
  47. X/*
  48. X * special feature of this version: NUL characters in the file are
  49. X * replaced by newline characters in memory. This allows us to edit
  50. X * binary files!
  51. X */
  52. X
  53. X#ifdef MSDOS
  54. X# include <io.h>
  55. X#endif
  56. X
  57. X#include "vim.h"
  58. X#include "globals.h"
  59. X#include "proto.h"
  60. X#include "param.h"
  61. X#include "fcntl.h"
  62. X
  63. X#ifdef LATTICE
  64. X# include <proto/dos.h>        /* for Lock() and UnLock() */
  65. X#endif
  66. X
  67. Xstatic int    noendofline = FALSE;    /* Set to TRUE when last line has no
  68. X                                                            EOL in binary mode */
  69. X
  70. X#define BUFSIZE 4096                /* size of normal write buffer */
  71. X#define SBUFSIZE 256                /* size of emergency write buffer */
  72. X
  73. Xstatic int  write_buf __ARGS((int, char *, int));
  74. Xstatic void do_mlines __ARGS((void));
  75. X
  76. X    void
  77. Xfilemess(name, s)
  78. X    char        *name;
  79. X    char        *s;
  80. X{
  81. X    smsg("\"%s\" %s", ((name == NULL) ? "" : name), s);
  82. X}
  83. X
  84. X/*
  85. X * Read lines from file 'fname' into the buffer after line 'from'.
  86. X *
  87. X * 1. We allocate blocks with m_blockalloc, as big as possible.
  88. X * 2. Each block is filled with characters from the file with a single read().
  89. X * 3. The lines are inserted in the buffer with appendline().
  90. X *
  91. X * (caller must check that fname != NULL)
  92. X */
  93. X    int
  94. Xreadfile(fname, sfname, from, newfile)
  95. X    char           *fname;
  96. X    char           *sfname;
  97. X    linenr_t        from;
  98. X    int                newfile;
  99. X{
  100. X#ifdef UNIX
  101. X    int                 fd = -1;
  102. X#else
  103. X    int                 fd;
  104. X#endif
  105. X    register u_char     c;
  106. X    register linenr_t    lnum = from;
  107. X    register u_char     *ptr = NULL;            /* pointer into read buffer */
  108. X    register u_char        *buffer = NULL;            /* read buffer */
  109. X    register long        size;
  110. X    register u_char        *p;
  111. X    long                filesize;
  112. X#define UNKNOWN        0x0fffffff                    /* file size is unknown */
  113. X    linenr_t            linecnt = line_count;
  114. X    int                    incomplete = FALSE;     /* was the last line incomplete? */
  115. X    int                 error = 0;                /* read errors encountered */
  116. X    long                linerest = 0;            /* remaining characters in line */
  117. X    long                filerest;                /* remaining characters in file */
  118. X    int                    firstpart = TRUE;        /* reading first part */
  119. X#ifdef UNIX
  120. X    int                    perm;
  121. X#endif
  122. X    int                    textmode = p_tx;        /* accept CR-LF for line break */
  123. X
  124. X    if (sfname == NULL)
  125. X        sfname = fname;
  126. X    /*
  127. X     * Use the short filename whenever possible.
  128. X     * Avoids problems with networks and when directory names are changed.
  129. X     */
  130. X    if (!did_cd)
  131. X        fname = sfname;
  132. X
  133. X    if (bufempty())        /* special case: buffer has no lines */
  134. X        linecnt = 0;
  135. X
  136. X#ifdef UNIX
  137. X        /*
  138. X         * On Unix it is possible to read a directory, so we have to
  139. X         * check for it before the open().
  140. X         */
  141. X    perm = getperm(fname);
  142. X#ifdef _POSIX_SOURCE
  143. X    if (perm >= 0 && !S_ISREG(perm))                /* not a regular file */
  144. X#else
  145. X    if (perm >= 0 && (perm & S_IFMT) != S_IFREG)    /* not a regular file */
  146. X#endif
  147. X    {
  148. X#ifdef _POSIX_SOURCE
  149. X        if (S_ISDIR(perm))
  150. X#else
  151. X        if ((perm & S_IFMT) == S_IFDIR)
  152. X#endif
  153. X            filemess(fname, "is a directory");
  154. X        else
  155. X            filemess(fname, "is not a file");
  156. X        return TRUE;
  157. X    }
  158. X#endif
  159. X
  160. X    if (
  161. X#ifdef UNIX
  162. X        !(perm & 0200) ||                        /* root's way to check RO */
  163. X#endif
  164. X        (fd = open(fname, O_RDWR)) == -1)        /* cannot open r/w */
  165. X    {
  166. X        if ((fd = open(fname, O_RDONLY)) == -1) /* cannot open at all */
  167. X        {
  168. X#ifdef MSDOS
  169. X        /*
  170. X         * The screen may be messed up by the "insert disk
  171. X         * in drive b: and hit return" message
  172. X         */
  173. X            updateScreen(CLEAR);
  174. X#endif
  175. X
  176. X#ifndef UNIX
  177. X        /*
  178. X         * On MSDOS and Amiga we can't open a directory, check here.
  179. X         */
  180. X            if (isdir(fname) > 0)
  181. X                filemess(fname, "is a directory");
  182. X            else
  183. X#endif
  184. X                if (newfile)
  185. X                    filemess(fname, "[New File]");
  186. X
  187. X            return TRUE;
  188. X        }
  189. X        if (newfile)                        /* set file readonly */
  190. X            p_ro = TRUE;
  191. X    }
  192. X    else if (newfile && !readonlymode)        /* set file not readonly */
  193. X        p_ro = FALSE;
  194. X
  195. X    if (newfile)
  196. X        noendofline = FALSE;
  197. X
  198. X    if ((filesize = lseek(fd, 0L, 2)) < 0)    /* get length of file */
  199. X        filesize = UNKNOWN;
  200. X    lseek(fd, 0L, 0);
  201. X
  202. X    filemess(fname, "");                    /* show that we are busy */
  203. X
  204. X    for (filerest = filesize; !error && !got_int && filerest != 0; breakcheck())
  205. X    {
  206. X        /*
  207. X         * We allocate as much space for the file as we can get, plus
  208. X         * space for the old line, one NUL in front and one NUL at the tail.
  209. X         * The amount is limited by the fact that read() only can read
  210. X         * upto max_unsigned characters (and other things).
  211. X         * If we don't know the file size, just get one Kbyte.
  212. X         */
  213. X        if (filesize >= UNKNOWN)
  214. X            size = 1024;
  215. X        else if (filerest > 0xff00L)
  216. X            size = 0xff00L;
  217. X        else if (filerest < 10)
  218. X            size = 10;
  219. X        else
  220. X            size = filerest;
  221. X
  222. X        for ( ; size >= 10; size /= 2)
  223. X        {
  224. X            if ((buffer = (u_char *)m_blockalloc((u_long)(size + linerest + 4), FALSE))
  225. X                        != NULL)
  226. X                break;
  227. X        }
  228. X        if (buffer == NULL)
  229. X        {
  230. X            emsg(e_outofmem);
  231. X            error = 1;
  232. X            break;
  233. X        }
  234. X        buffer[0] = NUL;    /* make sure there is a NUL in front of the first line */
  235. X        ++buffer;
  236. X        if (linerest)        /* copy characters from the previous buffer */
  237. X        {
  238. X            ptr -= linerest;
  239. X            memmove((char *)buffer, (char *)ptr, linerest);
  240. X            memset((char *)ptr, 1, linerest);    /* fill with non-NULs */
  241. X            ptr[linerest - 1] = NUL;            /* add a NUL on the end */
  242. X            free_line((char *)ptr);                /* free the space we don't use */
  243. X        }
  244. X        ptr = buffer + linerest;
  245. X        
  246. X        if ((size = (unsigned)read(fd, (char *)ptr, (size_t)size)) <= 0)
  247. X        {
  248. X            error = 2;
  249. X            break;
  250. X        }
  251. X        if (filesize >= UNKNOWN)            /* if we don't know the file size */
  252. X            filesize += size;                /* .. count the number of characters */
  253. X        else                                /* .. otherwise */
  254. X            filerest -= size;                /* .. compute the remaining length */
  255. X
  256. X        /*
  257. X         * when reading the first part of a file: guess EOL type
  258. X         */
  259. X        if (firstpart && p_ta)
  260. X        {
  261. X            for (p = ptr; p < ptr + size; ++p)
  262. X                if (*p == NL)
  263. X                {
  264. X                    if (p > ptr && p[-1] == CR)    /* found CR-NL */
  265. X                        textmode = TRUE;
  266. X                    else                        /* found a single NL */
  267. X                        textmode = FALSE;
  268. X                        /* if editing a new file: may set p_tx */
  269. X                    if (newfile && p_tx != textmode)
  270. X                    {
  271. X                        p_tx = textmode;
  272. X                        paramchanged("tx");
  273. X                    }
  274. X                    break;
  275. X                }
  276. X        }
  277. X
  278. X        /*
  279. X         * This loop is executed once for every character read.
  280. X         * Keep it fast!
  281. X         */
  282. X        --ptr;
  283. X        while (++ptr, --size >= 0)
  284. X        {
  285. X            if ((c = *ptr) != NUL && c != NL)    /* catch most common case */
  286. X                continue;
  287. X            if (c == NUL)
  288. X                *ptr = NL;        /* NULs are replaced by newlines! */
  289. X            else
  290. X            {
  291. X                *ptr = NUL;        /* end of line */
  292. X                if (textmode && ptr[-1] == CR)    /* remove CR */
  293. X                    ptr[-1] = NUL;
  294. X                if (!appendline(lnum, (char *)buffer))
  295. X                {
  296. X                    error = 1;
  297. X                    break;
  298. X                }
  299. X                ++lnum;
  300. X                buffer = ptr + 1;
  301. X            }
  302. X        }
  303. X        linerest = ptr - buffer;
  304. X        firstpart = FALSE;
  305. X    }
  306. X    if (lnum != from && !newfile)    /* added at least one line */
  307. X        CHANGED;
  308. X    if (error != 1 && linerest != 0)
  309. X    {
  310. X        /*
  311. X         * If we get EOF in the middle of a line, note the fact and
  312. X         * complete the line ourselves.
  313. X         */
  314. X        incomplete = TRUE;
  315. X        if (newfile && p_bin)        /* remember for when writing */
  316. X            noendofline = TRUE;
  317. X        *ptr = NUL;
  318. X        if (!appendline(lnum, (char *)buffer))
  319. X            error = 1;
  320. X        else if (!newfile)
  321. X            CHANGED;
  322. X    }
  323. X    if (error == 2 && filesize >= UNKNOWN)    /* no error, just EOF encountered */
  324. X    {
  325. X        filesize -= UNKNOWN;
  326. X        error = 0;
  327. X    }
  328. X
  329. X    close(fd);
  330. X
  331. X#ifdef MSDOS        /* the screen may be messed up by the "insert disk
  332. X                            in drive b: and hit return" message */
  333. X    updateScreen(CLEAR);
  334. X#endif
  335. X
  336. X    if (got_int)
  337. X    {
  338. X        filemess(fname, e_interr);
  339. X        return FALSE;            /* an interrupt isn't really an error */
  340. X    }
  341. X
  342. X    linecnt = line_count - linecnt;
  343. X    smsg("\"%s\" %s%s%s%s%ld line%s, %ld character%s",
  344. X            fname,
  345. X            p_ro ? "[readonly] " : "",
  346. X            incomplete ? "[Incomplete last line] " : "",
  347. X            error ? "[READ ERRORS] " : "",
  348. X#ifdef MSDOS
  349. X            textmode ? "" : "[notextmode] ",
  350. X#else
  351. X            textmode ? "[textmode] " : "",
  352. X#endif
  353. X            (long)linecnt, plural((long)linecnt),
  354. X            filesize, plural(filesize));
  355. X
  356. X    if (error && newfile)    /* with errors we should not write the file */
  357. X    {
  358. X        p_ro = TRUE;
  359. X        paramchanged("ro");
  360. X    }
  361. X
  362. X    u_clearline();        /* cannot use "U" command after adding lines */
  363. X
  364. X    if (newfile)        /* edit a new file: read mode from lines */
  365. X        do_mlines();
  366. X    if (from < line_count)
  367. X    {
  368. X        Curpos.lnum = from + 1;    /* put cursor at first new line */
  369. X        Curpos.col = 0;
  370. X    }
  371. X
  372. X    return FALSE;
  373. X}
  374. X
  375. X/*
  376. X * writeit - write to file 'fname' lines 'start' through 'end'
  377. X *
  378. X * We do our own buffering here because fwrite() is so slow.
  379. X *
  380. X * If forceit is true, we don't care for errors when attempting backups (jw).
  381. X * In case of an error everything possible is done to restore the original file.
  382. X * But when forceit is TRUE, we risk loosing it.
  383. X * When whole is TRUE and start == 1 and end == line_count, reset Changed.
  384. X */
  385. X    int
  386. Xwriteit(fname, sfname, start, end, append, forceit, whole)
  387. X    char            *fname;
  388. X    char            *sfname;
  389. X    linenr_t        start, end;
  390. X    int                append;
  391. X    int                forceit;
  392. X    int                whole;
  393. X{
  394. X    int                 fd;
  395. X    char               *backup = NULL;
  396. X    register char       *s;
  397. X    register u_char       *ptr;
  398. X    register u_char        c;
  399. X    register int        len;
  400. X    register linenr_t    lnum;
  401. X    long                nchars;
  402. X    char                *errmsg = NULL;
  403. X    char                *buffer;
  404. X    char                smallbuf[SBUFSIZE];
  405. X    int                    bufsize;
  406. X    long                 perm = -1;            /* file permissions */
  407. X    int                    retval = TRUE;
  408. X    int                    newfile = FALSE;    /* TRUE if file does not exist yet */
  409. X#ifdef UNIX
  410. X    struct stat            old;
  411. X    int                    made_writable = FALSE;    /* 'w' bit has been set */
  412. X#endif
  413. X#ifdef AMIGA
  414. X    BPTR                flock;
  415. X#endif
  416. X
  417. X    if (fname == NULL || *fname == NUL)        /* safety check */
  418. X        return FALSE;
  419. X    if (sfname == NULL)
  420. X        sfname = fname;
  421. X    /*
  422. X     * Use the short filename whenever possible.
  423. X     * Avoids problems with networks and when directory names are changed.
  424. X     */
  425. X    if (!did_cd)
  426. X        fname = sfname;
  427. X
  428. X    /*
  429. X     * Disallow writing from .exrc and .vimrc in current directory for
  430. X     * security reasons.
  431. X     */
  432. X    if (secure)
  433. X    {
  434. X        secure = 2;
  435. X        emsg(e_curdir);
  436. X        return FALSE;
  437. X    }
  438. X
  439. X    if (exiting)
  440. X        settmode(0);            /* when exiting allow typahead now */
  441. X
  442. X    filemess(fname, "");        /* show that we are busy */
  443. X
  444. X    buffer = alloc(BUFSIZE);
  445. X    if (buffer == NULL)            /* can't allocate big buffer, use small one */
  446. X    {
  447. X        buffer = smallbuf;
  448. X        bufsize = SBUFSIZE;
  449. X    }
  450. X    else
  451. X        bufsize = BUFSIZE;
  452. X
  453. X#ifdef UNIX
  454. X        /* get information about original file (if there is one) */
  455. X    old.st_dev = old.st_ino = 0;
  456. X    if (stat(fname, &old))
  457. X        newfile = TRUE;
  458. X    else
  459. X    {
  460. X#ifdef _POSIX_SOURCE
  461. X        if (!S_ISREG(old.st_mode))              /* not a file */
  462. X#else
  463. X        if ((old.st_mode & S_IFMT) != S_IFREG)    /* not a file */
  464. X#endif
  465. X        {
  466. X#ifdef _POSIX_SOURCE
  467. X            if (S_ISDIR(old.st_mode))
  468. X#else
  469. X            if ((old.st_mode & S_IFMT) == S_IFDIR)
  470. X#endif
  471. X                errmsg = "is a directory";
  472. X            else
  473. X                errmsg = "is not a file";
  474. X            goto fail;
  475. X        }
  476. X        perm = old.st_mode;
  477. X    }
  478. X/*
  479. X * If we are not appending, the file exists, and the 'writebackup' or
  480. X * 'backup' option is set, try to make a backup copy of the file.
  481. X */
  482. X    if (!append && perm >= 0 && (p_wb || p_bk) &&
  483. X                    (fd = open(fname, O_RDONLY)) >= 0)
  484. X    {
  485. X        int                bfd, buflen;
  486. X        char            buf[BUFSIZE + 1], *wp;
  487. X        int                some_error = FALSE;
  488. X        struct stat        new;
  489. X
  490. X        new.st_dev = new.st_ino = 0;
  491. X
  492. X        /*
  493. X         * Unix semantics has it, that we may have a writable file, 
  494. X         * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
  495. X         *  - the directory is not writable, 
  496. X         *  - the file may be a symbolic link, 
  497. X         *  - the file may belong to another user/group, etc.
  498. X         *
  499. X         * For these reasons, the existing writable file must be truncated and
  500. X         * reused. Creation of a backup COPY will be attempted.
  501. X         */
  502. X        if ((backup = modname(fname, ".bak")) == NULL)
  503. X        {
  504. X            some_error = TRUE;
  505. X            goto nobackup;
  506. X        }            
  507. X        if (!stat(backup, &new) &&
  508. X                    new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  509. X        {
  510. X            /*
  511. X             * may happen when modname gave the same file back.
  512. X             * E.g. silly link, or filename-length reached.
  513. X             * If we don't check here, we either ruin the file when
  514. X             * copying or erase it after writing. jw.
  515. X             */
  516. X            errmsg = "Invalid backup file (use ! to override)";
  517. X            free(backup);
  518. X            backup = NULL;    /* there is no backup file to delete */
  519. X            goto nobackup;
  520. X        }
  521. X        remove(backup);        /* remove old backup, if present */
  522. X        if ((bfd = open(backup, O_WRONLY | O_CREAT, 0666)) < 0)
  523. X        {
  524. X            /* 
  525. X             * oops, no write/create permission here?
  526. X             * try again in p_bdir directory. 
  527. X             */
  528. X            for (wp = fname + strlen(fname); wp >= fname; wp--)
  529. X                if (*wp == '/')
  530. X                    break;
  531. X            ++wp;
  532. X            sprintf(buf, "%s/%s", p_bdir, wp);
  533. X            free(backup);
  534. X            if ((backup = modname(buf, ".bak")) == NULL)
  535. X            {
  536. X                some_error = TRUE;
  537. X                goto nobackup;
  538. X            }
  539. X            if (!stat(backup, &new) &&
  540. X                        new.st_dev == old.st_dev && new.st_ino == old.st_ino)
  541. X            {
  542. X                errmsg = "Invalid backup file (use ! to override)";
  543. X                free(backup);
  544. X                backup = NULL;    /* there is no backup file to delete */
  545. X                goto nobackup;
  546. X            }
  547. X            remove(backup);
  548. X            if ((bfd = open(backup, O_WRONLY | O_CREAT, 0666)) < 0)
  549. X            {
  550. X                free(backup);
  551. X                backup = NULL;    /* there is no backup file to delete */
  552. X                errmsg = "Can't make backup file (use ! to override)";
  553. X                goto nobackup;
  554. X            }
  555. X        }
  556. X        /* set file protection same as original file, but strip s-bit */
  557. X        setperm(backup, perm & 0777);
  558. X
  559. X        /* copy the file. */
  560. X        while ((buflen = read(fd, buf, BUFSIZE)) > 0)
  561. X        {
  562. X            if (write_buf(bfd, buf, buflen) == -1)
  563. X            {
  564. X                errmsg = "Can't write to backup file (use ! to override)";
  565. X                goto writeerr;
  566. X            }
  567. X        }
  568. Xwriteerr:
  569. X        close(bfd);
  570. X        if (buflen < 0)
  571. X            errmsg = "Can't read file for backup (use ! to override)";
  572. Xnobackup:
  573. X        close(fd);
  574. X    /* ignore errors when forceit is TRUE */
  575. X        if ((some_error || errmsg) && !forceit)
  576. X        {
  577. X            retval = FALSE;
  578. X            goto fail;
  579. X        }
  580. X        errmsg = NULL;
  581. X    }
  582. X        /* if forceit and the file was read-only: make it writable */
  583. X    if (forceit && (old.st_uid == getuid()) && perm >= 0 && !(perm & 0200))
  584. X     {
  585. X        perm |= 0200;    
  586. X        setperm(fname, perm);
  587. X        made_writable = TRUE;
  588. X            /* if we are writing to the current file, readonly makes no sense */
  589. X        if (fname == Filename || fname == sFilename)
  590. X            p_ro = FALSE;
  591. X     }
  592. X#else /* UNIX */
  593. X
  594. X/*
  595. X * If we are not appending, the file exists, and the 'writebackup' or
  596. X * 'backup' option is set, make a backup.
  597. X * Do not make any backup, if "writebackup" and "backup" are 
  598. X * both switched off. This helps when editing large files on
  599. X * almost-full disks. (jw)
  600. X */
  601. X    perm = getperm(fname);
  602. X    if (perm < 0)
  603. X        newfile = TRUE;
  604. X    else if (isdir(fname) > 0)
  605. X    {
  606. X        errmsg = "is a directory";
  607. X        goto fail;
  608. X    }
  609. X    if (!append && perm >= 0 && (p_wb || p_bk))
  610. X    {
  611. X        /*
  612. X         * Form the backup file name - change path/fo.o.h to path/fo.o.h.bak
  613. X         */
  614. X        backup = modname(fname, ".bak");
  615. X        if (backup == NULL)
  616. X        {
  617. X            if (!forceit)
  618. X                goto fail;
  619. X        }
  620. X        else
  621. X        {
  622. X            /*
  623. X             * Delete any existing backup and move the current version to the backup.
  624. X             * For safety, we don't remove the backup until the write has finished
  625. X             * successfully. And if the 'backup' option is set, leave it around.
  626. X             */
  627. X#ifdef AMIGA
  628. X            /*
  629. X             * With MSDOS-compatible filesystems (crossdos, messydos) it is
  630. X             * possible that the name of the backup file is the same as the
  631. X             * original file. To avoid the chance of accidently deleting the
  632. X             * original file (horror!) we lock it during the remove.
  633. X             * This should not happen with ":w", because startscript() should
  634. X             * detect this problem and set thisfile_sn, causing modname to
  635. X             * return a correct ".bak" filename. This problem does exist with
  636. X             * ":w filename", but then the original file will be somewhere else
  637. X             * so the backup isn't really important. If autoscripting is off
  638. X             * the rename may fail.
  639. X             */
  640. X            flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  641. X#endif
  642. X            remove(backup);
  643. X#ifdef AMIGA
  644. X            if (flock)
  645. X                UnLock(flock);
  646. X#endif
  647. X            len = rename(fname, backup);
  648. X            if (len != 0)
  649. X            {
  650. X                if (forceit)
  651. X                {
  652. X                    free(backup);    /* don't do the rename below */
  653. X                    backup = NULL;
  654. X                }
  655. X                else
  656. X                {
  657. X                    errmsg = "Can't make backup file (use ! to override)";
  658. X                    goto fail;
  659. X                }
  660. X            }
  661. X        }
  662. X    }
  663. X#endif /* UNIX */
  664. X
  665. X        /* 
  666. X         * We may try to open the file twice: If we can't write to the
  667. X         * file and forceit is TRUE we delete the existing file and try to create
  668. X         * a new one. If this still fails we may have lost the original file!
  669. X         * (this may happen when the user reached his quotum for number of files).
  670. X         * Appending will fail if the file does not exist and forceit is FALSE.
  671. X         */
  672. X    while ((fd = open(fname, O_WRONLY | (append ?
  673. X                    (forceit ? (O_APPEND | O_CREAT) : O_APPEND) :
  674. X                    (O_CREAT | O_TRUNC)), 0666)) < 0)
  675. X     {
  676. X        /*
  677. X         * A forced write will try to create a new file if the old one is
  678. X         * still readonly. This may also happen when the directory is
  679. X         * read-only. In that case the remove() will fail.
  680. X         */
  681. X        if (!errmsg)
  682. X        {
  683. X            errmsg = "Can't open file for writing";
  684. X            if (forceit)
  685. X            {
  686. X#ifdef UNIX
  687. X                /* we write to the file, thus it should be marked
  688. X                                                    writable after all */
  689. X                perm |= 0200;        
  690. X                made_writable = TRUE;
  691. X                if (old.st_uid != getuid() || old.st_gid != getgid())
  692. X                    perm &= 0777;
  693. X#endif /* UNIX */
  694. X                if (!append)        /* don't remove when appending */
  695. X                    remove(fname);
  696. X                continue;
  697. X            }
  698. X        }
  699. X/*
  700. X * If we failed to open the file, we don't need a backup. Throw it away.
  701. X * If we moved or removed the original file try to put the backup in its place.
  702. X */
  703. X         if (backup)
  704. X        {
  705. X#ifdef UNIX
  706. X            struct stat st;
  707. X
  708. X            /*
  709. X             * There is a small chance that we removed the original, try
  710. X             * to move the copy in its place.
  711. X             * This won't work if the backup is in another file system!
  712. X             * In that case we leave the copy around.
  713. X             */
  714. X            if (stat(fname, &st) < 0)    /* file does not exist */
  715. X                rename(backup, fname);    /* put the copy in its place */
  716. X            if (stat(fname, &st) >= 0)    /* original file does exist */
  717. X                remove(backup);            /* throw away the copy */
  718. X#else
  719. X             rename(backup, fname);    /* try to put the original file back */
  720. X#endif
  721. X        }
  722. X         goto fail;
  723. X     }
  724. X    errmsg = NULL;
  725. X
  726. X    if (end > line_count)
  727. X        end = line_count;
  728. X    len = 0;
  729. X    s = buffer;
  730. X    nchars = 0;
  731. X    for (lnum = start; lnum <= end; ++lnum)
  732. X    {
  733. X        /*
  734. X         * The next while loop is done once for each character written.
  735. X         * Keep it fast!
  736. X         */
  737. X        ptr = (u_char *)nr2ptr(lnum) - 1;
  738. X        while ((c = *++ptr) != NUL)
  739. X        {
  740. X            if (c == NL)
  741. X                *s = NUL;        /* replace newlines with NULs */
  742. X            else
  743. X                *s = c;
  744. X            ++s;
  745. X            if (++len != bufsize)
  746. X                continue;
  747. X            if (write_buf(fd, buffer, bufsize) == -1)
  748. X            {
  749. X                end = 0;                /* write error: break loop */
  750. X                break;
  751. X            }
  752. X            nchars += bufsize;
  753. X            s = buffer;
  754. X            len = 0;
  755. X        }
  756. X            /* write failed or last line has no EOL: stop here */
  757. X        if (end == 0 || (p_bin && lnum == line_count && noendofline))
  758. X            break;
  759. X        if (p_tx)        /* write CR-NL */
  760. X        {
  761. X            *s = CR;
  762. X            ++s;
  763. X            if (++len == bufsize)
  764. X            {
  765. X                if (write_buf(fd, buffer, bufsize) == -1)
  766. X                {
  767. X                    end = 0;                /* write error: break loop */
  768. X                    break;
  769. X                }
  770. X                nchars += bufsize;
  771. X                s = buffer;
  772. X                len = 0;
  773. X            }
  774. X        }
  775. X        *s = NL;
  776. X        ++s;
  777. X        if (++len == bufsize && end)
  778. X        {
  779. X            if (write_buf(fd, buffer, bufsize) == -1)
  780. X            {
  781. X                end = 0;                /* write error: break loop */
  782. X                break;
  783. X            }
  784. X            nchars += bufsize;
  785. X            s = buffer;
  786. X            len = 0;
  787. X        }
  788. X    }
  789. X    if (len && end)
  790. X    {
  791. X        if (write_buf(fd, buffer, len) == -1)
  792. X            end = 0;                /* write error */
  793. X        nchars += len;
  794. X    }
  795. X
  796. X    if (close(fd) != 0)
  797. X    {
  798. X        errmsg = "Close failed";
  799. X        goto fail;
  800. X    }
  801. X#ifdef UNIX
  802. X    if (made_writable)
  803. X        perm &= ~0200;            /* reset 'w' bit for security reasons */
  804. X#endif
  805. X    if (perm >= 0)
  806. X        setperm(fname, perm);    /* set permissions of new file same as old file */
  807. X
  808. X    if (end == 0)
  809. X    {
  810. X        errmsg = "write error (file system full?)";
  811. X        goto fail;
  812. X    }
  813. X
  814. X#ifdef MSDOS        /* the screen may be messed up by the "insert disk
  815. X                            in drive b: and hit return" message */
  816. X    if (!exiting)
  817. X        updateScreen(CLEAR);
  818. X#endif
  819. X
  820. X    lnum -= start;        /* compute number of written lines */
  821. X    smsg("\"%s\"%s%s %ld line%s, %ld character%s",
  822. X            fname,
  823. X            newfile ? " [New File]" : " ",
  824. X#ifdef MSDOS
  825. X            p_tx ? "" : "[notextmode]",
  826. X#else
  827. X            p_tx ? "[textmode]" : "",
  828. X#endif
  829. X            (long)lnum, plural((long)lnum),
  830. X            nchars, plural(nchars));
  831. X    if (whole && start == 1 && end == line_count)    /* when written everything */
  832. X    {
  833. X        UNCHANGED;
  834. X        NotEdited = FALSE;
  835. X        startscript();        /* re-start auto script file */
  836. X    }
  837. X
  838. X    /*
  839. X     * Remove the backup unless 'backup' option is set
  840. X     */
  841. X    if (!p_bk && backup != NULL && remove(backup) != 0)
  842. X        emsg("Can't delete backup file");
  843. X    
  844. X    goto nofail;
  845. X
  846. Xfail:
  847. X#ifdef MSDOS        /* the screen may be messed up by the "insert disk
  848. X                            in drive b: and hit return" message */
  849. X    updateScreen(CLEAR);
  850. X#endif
  851. Xnofail:
  852. X
  853. X    free((char *) backup);
  854. X    free(buffer);
  855. X
  856. X    if (errmsg != NULL)
  857. X    {
  858. X        filemess(fname, errmsg);
  859. X        retval = FALSE;
  860. X    }
  861. X    return retval;
  862. X}
  863. X
  864. X/*
  865. X * write_buf: call write() to write a buffer
  866. X */
  867. X    static int
  868. Xwrite_buf(fd, buf, len)
  869. X    int        fd;
  870. X    char    *buf;
  871. X    int        len;
  872. X{
  873. X    int        wlen;
  874. X
  875. X    while (len)
  876. X    {
  877. X        wlen = write(fd, buf, (size_t)len);
  878. X        if (wlen <= 0)                /* error! */
  879. X            return -1;
  880. X        len -= wlen;
  881. X        buf += wlen;
  882. X    }
  883. X    return 0;
  884. X}
  885. X
  886. X/*
  887. X * do_mlines() - process mode lines for the current file
  888. X *
  889. X * Returns immediately if the "ml" parameter isn't set.
  890. X */
  891. Xstatic void     chk_mline __ARGS((linenr_t));
  892. X
  893. X    static void
  894. Xdo_mlines()
  895. X{
  896. X    linenr_t        lnum;
  897. X    int             nmlines;
  898. X
  899. X    if (!p_ml || (nmlines = (int)p_mls) == 0)
  900. X        return;
  901. X
  902. X    for (lnum = 1; lnum <= line_count && lnum <= nmlines; ++lnum)
  903. X        chk_mline(lnum);
  904. X
  905. X    for (lnum = line_count; lnum > 0 && lnum > nmlines &&
  906. X                            lnum > line_count - nmlines; --lnum)
  907. X        chk_mline(lnum);
  908. X}
  909. X
  910. X/*
  911. X * chk_mline() - check a single line for a mode string
  912. X */
  913. X    static void
  914. Xchk_mline(lnum)
  915. X    linenr_t lnum;
  916. X{
  917. X    register char    *s;
  918. X    register char    *e;
  919. X    char            *cs;            /* local copy of any modeline found */
  920. X    char            prev;
  921. X    int                end;
  922. X
  923. X    prev = ' ';
  924. X    for (s = nr2ptr(lnum); *s != NUL; ++s)
  925. X    {
  926. 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))
  927. X        {
  928. X            do
  929. X                ++s;
  930. X            while (s[-1] != ':');
  931. X            s = cs = strsave(s);
  932. X            if (cs == NULL)
  933. X                break;
  934. X            end = FALSE;
  935. X            while (end == FALSE)
  936. X            {
  937. X                while (*s == ' ' || *s == TAB)
  938. X                    ++s;
  939. X                if (*s == NUL)
  940. X                    break;
  941. X                for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
  942. X                    ;
  943. X                if (*e == NUL)
  944. X                    end = TRUE;
  945. X                *e = NUL;
  946. X                if (strncmp(s, "set ", (size_t)4) == 0) /* "vi:set opt opt opt: foo" */
  947. X                {
  948. X                    doset(s + 4);
  949. X                    break;
  950. X                }
  951. X                if (doset(s))        /* stop if error found */
  952. X                    break;
  953. X                s = e + 1;
  954. X            }
  955. X            free(cs);
  956. X            break;
  957. X        }
  958. X        prev = *s;
  959. X    }
  960. X}
  961. END_OF_FILE
  962. if test 22193 -ne `wc -c <'vim/src/fileio.c'`; then
  963.     echo shar: \"'vim/src/fileio.c'\" unpacked with wrong size!
  964. fi
  965. chmod +x 'vim/src/fileio.c'
  966. # end of 'vim/src/fileio.c'
  967. fi
  968. if test -f 'vim/src/storage.c' -a "${1}" != "-c" ; then 
  969.   echo shar: Will not clobber existing file \"'vim/src/storage.c'\"
  970. else
  971. echo shar: Extracting \"'vim/src/storage.c'\" \(23385 characters\)
  972. sed "s/^X//" >'vim/src/storage.c' <<'END_OF_FILE'
  973. X/* vi:ts=4:sw=4
  974. X *
  975. X * VIM - Vi IMproved
  976. X *
  977. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  978. X *                            Tim Thompson            twitch!tjt
  979. X *                            Tony Andrews            onecom!wldrdg!tony 
  980. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  981. X */
  982. X
  983. X/*
  984. X * storage.c: allocation of lines and management of them
  985. X *
  986. X * part 1: storage allocation for the lines and blocks of the current file
  987. X * part 2: managing of the pointer blocks
  988. X */
  989. X
  990. X#include "vim.h"
  991. X#include "globals.h"
  992. X#include "proto.h"
  993. X
  994. X/***************************************************************************
  995. X * part 1: storage allocation for the lines and blocks of the current file *
  996. X ***************************************************************************/
  997. X
  998. X/*
  999. X * Memory is allocated in relatively large blocks. These blocks are linked
  1000. X * in the allocated block list, headed by block_head. They are all freed
  1001. X * when abandoning a file, so we don't have to free every single line. The
  1002. X * list is kept sorted on memory address.
  1003. X * block_alloc() allocates a block.
  1004. X * m_blockfree() frees all blocks.
  1005. X *
  1006. X * The available chunks of memory are kept in free chunk lists. There is
  1007. X * one free list for each block of allocated memory. The list is kept sorted
  1008. X * on memory address.
  1009. X * alloc_line() gets a chunk from the free lists.
  1010. X * free_line() returns a chunk to the free lists.
  1011. X * m_search points to the chunk before the chunk that was freed/allocated the
  1012. X * last time.
  1013. X * mb_current points to the b_head where m_search points into the free list.
  1014. X *
  1015. X *
  1016. X *    block_head     /---> block #1     /---> block #2
  1017. X *       mb_next ---/       mb_next ---/       mb_next ---> NULL
  1018. X *       mb_info            mb_info            mb_info
  1019. X *          |                  |                  |
  1020. X *          V                  V                  V
  1021. X *        NULL          free chunk #1.1      free chunk #2.1
  1022. X *                             |                  |
  1023. X *                             V                  V
  1024. X *                      free chunk #1.2          NULL
  1025. X *                             |
  1026. X *                             V
  1027. X *                            NULL
  1028. X *
  1029. X * When a single free chunk list would have been used, it could take a lot
  1030. X * of time in free_line() to find the correct place to insert a chunk in the
  1031. X * free list. The single free list would become very long when many lines are
  1032. X * changed (e.g. with :%s/^M$//).
  1033. X */
  1034. X
  1035. X    /*
  1036. X     * this blocksize is used when allocating new lines
  1037. X     * When reading files larger blocks are used (see fileio.c)
  1038. X     * on the Amiga the blocksize must not be a multiple of 256
  1039. X     * with MS-Dos the blocksize must be larger than 255
  1040. X     * For Unix it does not really matter
  1041. X     */
  1042. X#define MEMBLOCKSIZE 2044
  1043. X
  1044. Xtypedef struct m_info info_t;
  1045. X
  1046. X/*
  1047. X * There are two types of in-use memory chunks:
  1048. X *    1. those that are allocated by readfile(). These are always preceded
  1049. X *        by a NUL character and end in a NUL character. The chunk must not
  1050. X *        contain other NUL characters. The preceding NUL is used to
  1051. X *        determine the chunk type. The ending NUL is used to determine the
  1052. X *        end of the chunk. The preceding NUL is not part of the chunk, the
  1053. X *        ending NUL is. 
  1054. X *  2. the other chunks have been allocated with alloc_line(). They are
  1055. X *        preceded by a non-NUL character. This is used to determine the chunk
  1056. X *        type. The non-NUL may be part of a size field or may be an extra 0xff
  1057. X *        byte. The chunk always ends in a NUL character and may also contain
  1058. X *        a NUL character. The size field contains the size of the chunk,
  1059. X *        including the size field. The trailing NUL may be used by a possibly
  1060. X *        follwing type 1 chunk. The preceding size, the optional 0xff and the
  1061. X *        trailing NUL are all part of the chunk.
  1062. X *
  1063. X * When the chunk is not in-use it is preceded with the m_info structure.
  1064. X * The m_next field links it in one of the free chunk lists. It must still
  1065. X * end in a NUL byte, because it may be followed by a type 1 chunk!
  1066. X *
  1067. X * When in-use we must make sure there is a non-NUL byte in front of type
  1068. X * 2 chunks.
  1069. X *
  1070. X * On the Amiga this means that the size must not be a multiple of 256.
  1071. X * This is done by multiplying the size by 2 and adding one.
  1072. X *
  1073. X * On MS-DOS the size must be larger than 255. This is done by adding 256
  1074. X * to the size.
  1075. X *
  1076. X * On Unix systems an extra 0xff byte is added. This costs 4 bytes because
  1077. X * pointers must be kept long-aligned.
  1078. X *
  1079. X * On most unix systems structures have to be longword (32 or 64 bit) aligned.
  1080. X * On most other systems they are short (16 bit) aligned.
  1081. X */
  1082. X
  1083. X#ifdef UNIX
  1084. X# define ALIGN_LONG        /* longword alignment and use filler byte */
  1085. X# define ALIGN_SIZE (sizeof(long))
  1086. X# define ALIGN_MASK (ALIGN_SIZE - 1)
  1087. X#else
  1088. X# ifdef AMIGA
  1089. X#  define LOWBYTE        /* size must not be multiple of 256 */
  1090. X# else
  1091. X#  ifdef MSDOS
  1092. X#   define HIGHBYTE        /* size must be larger than 255 */
  1093. X#  else
  1094. X    you must define something!
  1095. X#  endif
  1096. X# endif
  1097. X#endif
  1098. X
  1099. X/*
  1100. X * stucture used to link chunks in one of the free chunk lists.
  1101. X */
  1102. Xstruct m_info
  1103. X{
  1104. X#ifdef ALIGN_LONG
  1105. X    u_long     m_size;    /* size of the chunk (including m_info) */
  1106. X#else
  1107. X    u_short  m_size;    /* size of the chunk (including m_info) */
  1108. X#endif
  1109. X    info_t    *m_next;    /* pointer to next free chunk in the list */
  1110. X};
  1111. X
  1112. X#ifdef ALIGN_LONG
  1113. X    /* size of m_size + room for 0xff byte */
  1114. X# define M_OFFSET (sizeof(u_long) * 2)
  1115. X#else
  1116. X    /* size of m_size */
  1117. X# define M_OFFSET (sizeof(u_short))
  1118. X#endif
  1119. X
  1120. X/*
  1121. X * structure used to link blocks in the list of allocated blocks.
  1122. X */
  1123. Xstruct m_block
  1124. X{
  1125. X    struct m_block    *mb_next;    /* pointer to next allocated block */
  1126. X    info_t            mb_info;    /* head of free chuck list for this block */
  1127. X};
  1128. X
  1129. Xstatic struct m_block block_head = {NULL, {0, NULL}};
  1130. X                                /* head of allocated memory block list */
  1131. X
  1132. Xstatic info_t *m_search = NULL;     /* pointer to chunk before previously
  1133. X                                       allocated/freed chunk */
  1134. Xstatic struct m_block *mb_current = NULL;    /* block where m_search points in */
  1135. X
  1136. X/*
  1137. X * Allocate a block of memory and link it in the allocated block list.
  1138. X */
  1139. X    char *
  1140. Xm_blockalloc(size, message)
  1141. X    u_long    size;
  1142. X    int        message;
  1143. X{
  1144. X    struct m_block *p;
  1145. X    struct m_block *mp, *next;
  1146. X
  1147. X    p = (struct m_block *)lalloc(size + sizeof(struct m_block), message);
  1148. X    if (p != NULL)
  1149. X    {
  1150. X         /* Insert the block into the allocated block list, keeping it
  1151. X                     sorted on address. */
  1152. X        for (mp = &block_head; (next = mp->mb_next) != NULL && next < p; mp = next)
  1153. X            ;
  1154. X        p->mb_next = next;                /* link in block list */
  1155. X        mp->mb_next = p;
  1156. X        p->mb_info.m_next = NULL;        /* clear free list */
  1157. X        p->mb_info.m_size = 0;
  1158. X        mb_current = p;                    /* remember current block */
  1159. X        m_search = NULL;
  1160. X        p++;                            /* return usable memory */
  1161. X    }
  1162. X    return (char *)p;
  1163. X}
  1164. X
  1165. X/*
  1166. X * free all allocated memory blocks
  1167. X */
  1168. X    void
  1169. Xm_blockfree()
  1170. X{
  1171. X    struct m_block *p, *np;
  1172. X
  1173. X    for (p = block_head.mb_next; p != NULL; p = np)
  1174. X    {
  1175. X        np = p->mb_next;
  1176. X        free((char *)p);
  1177. X    }
  1178. X    block_head.mb_next = NULL;
  1179. X    m_search = NULL;
  1180. X    mb_current = NULL;
  1181. X}
  1182. X
  1183. X/*
  1184. X * Free a chunk of memory which was
  1185. X *  1. inserted with readfile(); these are preceded with a NUL byte
  1186. X *  2. allocated with alloc_line(); these are preceded with a non-NUL byte
  1187. X * Insert the chunk into the correct free list, keeping it sorted on address.
  1188. X */
  1189. X    void
  1190. Xfree_line(ptr)
  1191. X    char *ptr;
  1192. X{
  1193. X    register info_t        *next;
  1194. X    register info_t        *prev, *curr;
  1195. X    register info_t        *mp;
  1196. X    long                len;
  1197. X    struct m_block        *nextb;
  1198. X
  1199. X    if (ptr == NULL || ptr == IObuff)
  1200. X        return;    /* illegal address can happen in out-of-memory situations */
  1201. X
  1202. X    if (*(ptr - 1) == NUL)        /* type 1 chunk: no size field */
  1203. X    {
  1204. X#ifdef ALIGN_LONG        /* use longword alignment */
  1205. X        long c;
  1206. X
  1207. X        len = strlen(ptr) + 1;
  1208. X        if ((c = ((long)ptr & ALIGN_MASK)) != 0)     /* lose some bytes */
  1209. X        {
  1210. X            c = ALIGN_SIZE - c;
  1211. X            ptr += c;
  1212. X            len -= c;
  1213. X        }
  1214. X#else            /* use short (16 bit) alignment */
  1215. X        len = strlen(ptr) + 1;
  1216. X        if (len > 0xff00)        /* can't handle this large (cannot happen?) */
  1217. X            len = 0xff00;
  1218. X        if ((long)ptr & 1)                    /* lose a byte */
  1219. X        {
  1220. X            ++ptr;
  1221. X            --len;
  1222. X        }
  1223. X#endif    /* ALIGN_LONG */
  1224. X
  1225. X        /* we must be able to store size, pointer and a trailing NUL */
  1226. X        /* otherwise we can't fit it in the free list */
  1227. X        if (len <= (long)sizeof(info_t))
  1228. X            return;            /* these bytes are not used until you quit the file */
  1229. X        mp = (info_t *)ptr;
  1230. X        mp->m_size = len;
  1231. X    }
  1232. X#ifdef ALIGN_LONG
  1233. X    else if ((*(ptr - 1) & 0xff) == 0xff)    /* type 2 chunk: has size field */
  1234. X    {
  1235. X        mp = (info_t *)(ptr - M_OFFSET);
  1236. X    }
  1237. X    else        /* illegal situation: there is no NUL or 0xff in front of the line */
  1238. X    {
  1239. X        emsg("Illegal chunk");
  1240. X        return;
  1241. X    }
  1242. X#endif
  1243. X#ifdef LOWBYTE
  1244. X    else             /* type 2 chunk: has size field */
  1245. X    {
  1246. X        mp = (info_t *)(ptr - M_OFFSET);
  1247. X        mp->m_size >>= 1;
  1248. X    }
  1249. X#endif
  1250. X#ifdef HIGHBYTE
  1251. X    else             /* type 2 chunk: has size field */
  1252. X    {
  1253. X        mp = (info_t *)(ptr - M_OFFSET);
  1254. X        mp->m_size -= 256;
  1255. X    }
  1256. X#endif
  1257. X
  1258. X        /* find block where chunk could be a part off */
  1259. X        /* if we change mb_current, m_search is set to NULL */
  1260. X    if (mb_current == NULL || mp < (info_t *)mb_current)
  1261. X    {
  1262. X        mb_current = block_head.mb_next;
  1263. X        m_search = NULL;
  1264. X    }
  1265. X    if ((nextb = mb_current->mb_next) != NULL && (info_t *)nextb < mp)
  1266. X    {
  1267. X        mb_current = nextb;
  1268. X        m_search = NULL;
  1269. X    }
  1270. X    while ((nextb = mb_current->mb_next) != NULL && (info_t *)nextb < mp)
  1271. X        mb_current = nextb;
  1272. X
  1273. X    curr = NULL;
  1274. X    /* if mp is smaller than m_search->m_next we go to the start of the free list */
  1275. X    if (m_search == NULL || mp < (m_search->m_next))
  1276. X        next = &(mb_current->mb_info);
  1277. X    else
  1278. X        next = m_search;
  1279. X    /*
  1280. X     * The following loop is executed very often.
  1281. X     * Therefore it has been optimized at the cost of readability.
  1282. X     * Keep it fast!
  1283. X     */
  1284. X#ifdef SLOW_BUT_EASY_TO_READ
  1285. X    do
  1286. X    {
  1287. X        prev = curr;
  1288. X        curr = next;
  1289. X        next = next->m_next;
  1290. X    }
  1291. X    while (mp > next && next != NULL);
  1292. X#else
  1293. X    do                                        /* first, middle, last */
  1294. X    {
  1295. X        prev = next->m_next;                /* curr, next, prev */
  1296. X        if (prev == NULL || mp <= prev)
  1297. X        {
  1298. X            prev = curr;
  1299. X            curr = next;
  1300. X            next = next->m_next;
  1301. X            break;
  1302. X        }
  1303. X        curr = prev->m_next;                /* next, prev, curr */
  1304. X        if (curr == NULL || mp <= curr)
  1305. X        {
  1306. X            prev = next;
  1307. X            curr = prev->m_next;
  1308. X            next = curr->m_next;
  1309. X            break;
  1310. X        }
  1311. X        next = curr->m_next;                /* prev, curr, next */
  1312. X    }
  1313. X    while (mp > next && next != NULL);
  1314. X#endif
  1315. X
  1316. X/* if *mp and *next are concatenated, join them into one chunk */
  1317. X    if ((char *)mp + mp->m_size == (char *)next)
  1318. X    {
  1319. X        mp->m_size += next->m_size;
  1320. X        mp->m_next = next->m_next;
  1321. X    }
  1322. X    else
  1323. X        mp->m_next = next;
  1324. X
  1325. X/* if *curr and *mp are concatenated, join them */
  1326. X    if (prev != NULL && (char *)curr + curr->m_size == (char *)mp)
  1327. X    {
  1328. X        curr->m_size += mp->m_size;
  1329. X        curr->m_next = mp->m_next;
  1330. X        m_search = prev;
  1331. X    }
  1332. X    else
  1333. X    {
  1334. X        curr->m_next = mp;
  1335. X        m_search = curr;    /* put m_search before freed chunk */
  1336. X    }
  1337. X}
  1338. X
  1339. X/*
  1340. X * Allocate and initialize a new line structure with room for at least
  1341. X * 'size' characters.
  1342. X */
  1343. X    char *
  1344. Xalloc_line(size)
  1345. X    register unsigned size;
  1346. X{
  1347. X    register info_t *mp, *mprev, *mp2;
  1348. X    struct m_block    *mbp;
  1349. X    int                 size_align;
  1350. X
  1351. X/*
  1352. X * Add room for size field, optional 0xff byte and trailing NUL byte.
  1353. X * Adjust for minimal size (must be able to store info_t
  1354. X * plus a trailing NUL, so the chunk can be released again)
  1355. X */
  1356. X    size += M_OFFSET + 1;
  1357. X    if (size < sizeof(info_t) + 1)
  1358. X      size = sizeof(info_t) + 1;
  1359. X
  1360. X/*
  1361. X * round size up for alignment
  1362. X */
  1363. X#ifdef ALIGN_LONG            /* use longword alignment */
  1364. X    size_align = (size + ALIGN_MASK) & ~ALIGN_MASK;
  1365. X#else /* ALIGN_LONG */    /* use short (16 bit) alignment */
  1366. X    size_align = (size + 1) & ~1;
  1367. X#endif    /* ALIGN_LONG */
  1368. X
  1369. X/* if m_search is NULL (uninitialized free list) we start at block_head */
  1370. X    if (mb_current == NULL || m_search == NULL)
  1371. X    {
  1372. X        mb_current = &block_head;
  1373. X        m_search = &(block_head.mb_info);
  1374. X    }
  1375. X
  1376. X/* search for space in free list */
  1377. X    mprev = m_search;
  1378. X    mbp = mb_current;
  1379. X    mp = m_search->m_next;
  1380. X    if (mp == NULL)
  1381. X    {
  1382. X        if (mbp->mb_next)
  1383. X            mbp = mbp->mb_next;
  1384. X        else
  1385. X            mbp = &block_head;
  1386. X        mp = m_search = &(mbp->mb_info);
  1387. X    }
  1388. X    while (mp->m_size < size)
  1389. X    {
  1390. X        if (mp == m_search)        /* back where we started in free chunk list */
  1391. X        {
  1392. X            if (mbp->mb_next)
  1393. X                mbp = mbp->mb_next;
  1394. X            else
  1395. X                mbp = &block_head;
  1396. X            mp = m_search = &(mbp->mb_info);
  1397. X            if (mbp == mb_current)    /* back where we started in block list */
  1398. X            {
  1399. X                int        n = (size_align > (MEMBLOCKSIZE / 4) ? size_align : MEMBLOCKSIZE);
  1400. X
  1401. X                mp = (info_t *)m_blockalloc((u_long)n, TRUE);
  1402. X                if (mp == NULL)
  1403. X                    return (NULL);
  1404. X#ifdef HIGHBYTE
  1405. X                mp->m_size = n + 256;
  1406. X#endif
  1407. X#ifdef LOWBYTE
  1408. X                mp->m_size = (n << 1) + 1;
  1409. X#endif
  1410. X#ifdef ALIGN_LONG
  1411. X                mp->m_size = n;
  1412. X                *((u_char *)mp + M_OFFSET - 1) = 0xff;
  1413. X#endif
  1414. X                free_line((char *)mp + M_OFFSET);
  1415. X                mp = m_search;
  1416. X                mbp = mb_current;
  1417. X            }
  1418. X        }
  1419. X        mprev = mp;
  1420. X        if ((mp = mp->m_next) == NULL)        /* at end of the list */
  1421. X            mp = &(mbp->mb_info);            /* wrap around to begin */
  1422. X    }
  1423. X
  1424. X/* if the chunk we found is large enough, split it up in two */
  1425. X    if ((long)mp->m_size - size_align >= (long)(sizeof(info_t) + 1))
  1426. X    {
  1427. X        mp2 = (info_t *)((char *)mp + size_align);
  1428. X        mp2->m_size = mp->m_size - size_align;
  1429. X        mp2->m_next = mp->m_next;
  1430. X        mprev->m_next = mp2;
  1431. X        mp->m_size = size_align;
  1432. X    }
  1433. X    else                    /* remove *mp from the free list */
  1434. X    {
  1435. X        mprev->m_next = mp->m_next;
  1436. X    }
  1437. X    m_search = mprev;
  1438. X    mb_current = mbp;
  1439. X
  1440. X#ifdef HIGHBYTE
  1441. X    mp->m_size += 256;
  1442. X#endif
  1443. X#ifdef LOWBYTE
  1444. X    mp->m_size = (mp->m_size << 1) + 1;
  1445. X#endif
  1446. X    mp = (info_t *)((char *)mp + M_OFFSET);
  1447. X#ifdef ALIGN_LONG
  1448. X    *((u_char *)mp - 1) = 0xff;            /* mark type 2 chunk */
  1449. X#endif
  1450. X    *(char *)mp = NUL;                    /* set the first byte to NUL */
  1451. X
  1452. X    return ((char *)mp);
  1453. X}
  1454. X
  1455. X/*
  1456. X * save_line(): allocate memory with alloc_line() and copy the
  1457. X * string 'src' into it.
  1458. X */
  1459. X    char *
  1460. Xsave_line(src)
  1461. X    register char *src;
  1462. X{
  1463. X    register char *dst;
  1464. X    register unsigned len;
  1465. X
  1466. X    len = strlen(src);
  1467. X    if ((dst = alloc_line(len)) != NULL)
  1468. X        memmove(dst, src, (size_t)(len + 1));
  1469. X    return (dst);
  1470. X}
  1471. X
  1472. X/******************************************
  1473. X * part 2: managing of the pointer blocks *
  1474. X ******************************************/
  1475. X
  1476. Xtypedef struct block block_t;
  1477. X
  1478. X#ifdef BLOCK_SIZE
  1479. X# undef BLOCK_SIZE    /* for Linux: is in limits.h */
  1480. X#endif
  1481. X
  1482. X#define BLOCK_SIZE 40
  1483. X
  1484. Xstruct block
  1485. X{
  1486. X    char    *b_ptr[BLOCK_SIZE];        /* pointers to the lines */
  1487. X    char     b_flags[BLOCK_SIZE];    /* see below */
  1488. X    u_short  b_count;                /* current number of pointers in b_ptr */
  1489. X    block_t *b_next;                /* pointer to next block */
  1490. X    block_t *b_prev;                /* pointer to previous block */
  1491. X};
  1492. X
  1493. X#define B_MARKED    0x01        /* mark for :global command */
  1494. X
  1495. Xstatic block_t *first_block;    /* pointer to first block in block list */
  1496. Xstatic block_t *last_block;        /* pointer to last block in block list */
  1497. X
  1498. Xstatic block_t *curr_block;        /* block used by nr2ptr */
  1499. Xstatic linenr_t curr_count;        /* first line number of block curr_block */
  1500. Xstatic linenr_t curr_count_max;    /* curr_count + curr_block->b_count */
  1501. X
  1502. Xstatic block_t *alloc_block __ARGS((void));
  1503. X
  1504. X    static block_t *
  1505. Xalloc_block()
  1506. X{
  1507. X    block_t *p;
  1508. X
  1509. X    p = (block_t *)(alloc_line((unsigned)sizeof(block_t)));
  1510. X    if (p != NULL)
  1511. X    {
  1512. X        memset((char *)p, 0, sizeof(block_t));
  1513. X    }
  1514. X    return (p);
  1515. X}
  1516. X
  1517. X/*
  1518. X * filealloc() - construct an initial empty file buffer
  1519. X */
  1520. X    void
  1521. Xfilealloc()
  1522. X{
  1523. X    first_block = last_block = alloc_block();
  1524. X    if (first_block == NULL || (first_block->b_ptr[0] = alloc_line(0)) == NULL)
  1525. X        getout(1);
  1526. X    first_block->b_count = 1;
  1527. X    Curpos.lnum = 1;
  1528. X    Curswant = Curpos.col = 0;
  1529. X    Topline = 1;
  1530. X    Botline = 2;
  1531. X    line_count = 1;
  1532. X    curr_count = 0;
  1533. X    clrallmarks();
  1534. X    clrtags();
  1535. X    UNCHANGED;
  1536. X}
  1537. X
  1538. X/*
  1539. X * freeall() - free the current buffer
  1540. X *
  1541. X * Free all lines in the current buffer.
  1542. X */
  1543. X    void
  1544. Xfreeall()
  1545. X{
  1546. X    m_blockfree();
  1547. X    line_count = 0;
  1548. X    s_ins(0, 0, TRUE);    /* invalidate Line arrays */
  1549. X    u_clearall();
  1550. X}
  1551. X
  1552. X/*
  1553. X * Get the pointer to the line 'nr'.
  1554. X * This function is used a lot for sequential access (writeit, search),
  1555. X * so that is what it is optimized for.
  1556. X */
  1557. X    char *
  1558. Xnr2ptr(nr)
  1559. X    register linenr_t nr;
  1560. X{
  1561. X    register linenr_t count = curr_count;
  1562. X
  1563. X    /*
  1564. X     * if we don't have a current block or the line is not in the current block,
  1565. X     * make the block containing the line the current block.
  1566. X     */
  1567. X    if (count == 0 || nr >= curr_count_max || nr < count)
  1568. X    {
  1569. X        register block_t *bp = curr_block;
  1570. X
  1571. X        if (nr < 1 || nr > line_count)
  1572. X        {
  1573. X            emsg("nr2ptr: illegal nr");
  1574. X            return (IObuff);    /* always return a valid ptr */
  1575. X        }
  1576. X
  1577. X        /*
  1578. X         * three ways to find the pointer:
  1579. X         * 1. first pointer in the next block (fast for sequential access)
  1580. X         * 2. search forward
  1581. X         * 3. search backward
  1582. X         */
  1583. X        if (count && nr == count + bp->b_count)        /* in next block */
  1584. X        {
  1585. X            count = nr;
  1586. X            bp = bp->b_next;
  1587. X        }
  1588. X        else if (nr <= (count + line_count) / 2 ||
  1589. X                (nr <= count && nr <= count / 2))
  1590. X        {
  1591. X                                                    /* search forward */
  1592. X            if (nr < count || count == 0)
  1593. X            {
  1594. X                count = 1;
  1595. X                bp = first_block;
  1596. X            }
  1597. X            while (bp != NULL)
  1598. X            {
  1599. X                count += bp->b_count;
  1600. X                if (nr < count)
  1601. X                {
  1602. X                    count -= bp->b_count;
  1603. X                    break;
  1604. X                }
  1605. X                bp = bp->b_next;
  1606. X            }
  1607. X        }
  1608. X        else
  1609. X        {                                            /* search backward */
  1610. X            if (nr < count)
  1611. X                bp = bp->b_prev;
  1612. X            else
  1613. X            {
  1614. X                bp = last_block;
  1615. X                count = line_count + 1;
  1616. X            }
  1617. X            while (bp != NULL)
  1618. X            {
  1619. X                count -= bp->b_count;
  1620. X                if (nr >= count)
  1621. X                    break;
  1622. X                bp = bp->b_prev;
  1623. X            }
  1624. X        }
  1625. X        
  1626. X        if (bp == NULL)
  1627. X        {
  1628. X            emsg("nr2ptr: strorage corrupt");
  1629. X            curr_count = 0;
  1630. X            return (IObuff);
  1631. X        }
  1632. X        curr_count = count;
  1633. X        curr_count_max = count + bp->b_count;
  1634. X        curr_block = bp;
  1635. X    }
  1636. X    return (curr_block->b_ptr[nr - count]);
  1637. X}
  1638. X
  1639. X/*
  1640. X * pos2ptr: get pointer to position 'pos'
  1641. X */
  1642. X    char *
  1643. Xpos2ptr(pos)
  1644. X    FPOS    *pos;
  1645. X{
  1646. X    return (nr2ptr(pos->lnum) + pos->col);
  1647. X}
  1648. X
  1649. X    char *
  1650. XCurpos2ptr()
  1651. X{
  1652. X    return (nr2ptr(Curpos.lnum) + Curpos.col);
  1653. X}
  1654. X
  1655. X/*
  1656. X * set the B_MARKED flag for line 'lnum'
  1657. X */
  1658. X    void
  1659. Xsetmarked(lnum)
  1660. X    linenr_t lnum;
  1661. X{
  1662. X    nr2ptr(lnum);
  1663. X    curr_block->b_flags[lnum - curr_count] |= B_MARKED;
  1664. X}
  1665. X
  1666. X/*
  1667. X * find the first line with its B_MARKED flag set
  1668. X */
  1669. X    linenr_t
  1670. Xfirstmarked()
  1671. X{
  1672. X    register block_t    *bp;
  1673. X    register linenr_t    lnum;
  1674. X    register u_short    i;
  1675. X
  1676. X    for (bp = first_block, lnum = 1; bp != NULL; bp = bp->b_next)
  1677. X        for (i = 0; i < bp->b_count; ++i, ++lnum)
  1678. X            if (bp->b_flags[i] & B_MARKED)
  1679. X            {
  1680. X                bp->b_flags[i] &= ~B_MARKED;
  1681. X                return lnum;
  1682. X            }
  1683. X    return (linenr_t) 0;
  1684. X}
  1685. X
  1686. X/*
  1687. X * clear all B_MARKED flags
  1688. X */
  1689. X    void
  1690. Xclearmarked()
  1691. X{
  1692. X    register block_t    *bp;
  1693. X    register int        i;
  1694. X
  1695. X    for (bp = first_block; bp != NULL; bp = bp->b_next)
  1696. X        for (i = bp->b_count; --i >= 0; )
  1697. X                bp->b_flags[i] &= ~B_MARKED;
  1698. X}
  1699. X
  1700. X/*
  1701. X * a pointer to a line is converted into a line number
  1702. X * we start at line number 'start'
  1703. X * this is a bit slow, but it is used for marks and undo only
  1704. X */
  1705. X    linenr_t
  1706. Xptr2nr(ptr, start)
  1707. X    char *ptr;
  1708. X    linenr_t start;
  1709. X{
  1710. X    block_t *bp;
  1711. X    register linenr_t nr;
  1712. X    register char **pp;
  1713. X    register int    i;
  1714. X
  1715. X    if (ptr == NULL)
  1716. X        return (linenr_t)0;
  1717. X
  1718. X    if (start == 0)
  1719. X        start = 1;
  1720. X    nr2ptr(start);        /* set curr_block and curr_count */
  1721. X
  1722. X    for (nr = curr_count, bp = curr_block; bp != NULL; bp = bp->b_next)
  1723. X        for (pp = bp->b_ptr, i = bp->b_count; --i >= 0; ++nr)
  1724. X            if (*pp++ == ptr)
  1725. X                return (nr);
  1726. X    return (linenr_t)0;
  1727. X}
  1728. X
  1729. X/*
  1730. X * appendline: add a line
  1731. X *    return TRUE when succesful
  1732. X */
  1733. X    int
  1734. Xappendline(after, s)
  1735. X    linenr_t    after;
  1736. X    char        *s;
  1737. X{
  1738. X    register block_t    *bp;
  1739. X    block_t             *nbp;
  1740. X    linenr_t            count;
  1741. X    register int        i;
  1742. X
  1743. X    if (s == NULL)        /* don't insert NULL pointers! */
  1744. X        return FALSE;
  1745. X    if (after == 0)     /* insert in front of first line */
  1746. X    {
  1747. X        bp = first_block;
  1748. X        count = 1;
  1749. X        if (bufempty())     /* simply replace dummy line */
  1750. X        {
  1751. X            free_line(bp->b_ptr[0]);
  1752. X            bp->b_ptr[0] = s;
  1753. X            return TRUE;
  1754. X        }
  1755. X        curr_count = 0; /* curr_block will become invalid */
  1756. X    }
  1757. X    else
  1758. X    {
  1759. X        (void)nr2ptr(after);    /* find block */
  1760. X        bp = curr_block;
  1761. X        count = curr_count;
  1762. X    }
  1763. X
  1764. X    ++line_count;
  1765. X    i = bp->b_count;
  1766. X    if (i < BLOCK_SIZE)            /* there is place in the current block */
  1767. X/* move ptrs one place forward to make space for new one */
  1768. X    {
  1769. X        register char **pp;
  1770. X        register char *fp;
  1771. X
  1772. X        pp = &(bp->b_ptr[i]);
  1773. X        fp = &(bp->b_flags[i]);
  1774. X        for (i += count - after - 1; --i >= 0; --pp, --fp)
  1775. X        {
  1776. X            *pp = *(pp - 1);
  1777. X            *fp = *(fp - 1);
  1778. X        }
  1779. X        *pp = s;
  1780. X        *fp = 0;
  1781. X        ++bp->b_count;
  1782. X        ++curr_count_max;
  1783. X        return TRUE;
  1784. X    }
  1785. X
  1786. X/* need to allocate a new block */
  1787. X    nbp = alloc_block();
  1788. X    if (nbp == NULL)
  1789. X    {
  1790. X        --line_count;
  1791. X        free_line(s);
  1792. X        return FALSE;
  1793. X    }
  1794. X
  1795. X/* put new block in linked list */
  1796. X    if (after == 0) /* put new block in front of linked list */
  1797. X    {
  1798. X        bp->b_prev = nbp;
  1799. X        nbp->b_next = bp;
  1800. X        first_block = nbp;
  1801. X        nbp->b_ptr[0] = s;
  1802. X        nbp->b_count = 1;
  1803. X        return TRUE;
  1804. X    }
  1805. X
  1806. X    /* insert new block in linked list after bp */
  1807. X    nbp->b_next = bp->b_next;
  1808. X    bp->b_next = nbp;
  1809. X    nbp->b_prev = bp;
  1810. X    if (nbp->b_next == NULL)
  1811. X        last_block = nbp;
  1812. X    else
  1813. X        nbp->b_next->b_prev = nbp;
  1814. X
  1815. X    if (after - count + 1 == BLOCK_SIZE) /* put s in new block */
  1816. X    {
  1817. X        nbp->b_ptr[0] = s;
  1818. X        nbp->b_count = 1;
  1819. X        return TRUE;
  1820. X    }
  1821. X
  1822. X    /* move some ptrs from full block to new block */
  1823. X    {
  1824. X        register int j = 0;
  1825. X
  1826. X        bp->b_count = after - count + 1;    /* number of ptrs remaining */
  1827. X        i = BLOCK_SIZE - bp->b_count;        /* number of ptrs to be moved */
  1828. X        nbp->b_count = i;
  1829. X        while (--i >= 0)
  1830. X        {
  1831. X            j = bp->b_count + i;
  1832. X            nbp->b_ptr[i] = bp->b_ptr[j];
  1833. X            nbp->b_flags[i] = bp->b_flags[j];
  1834. X        }
  1835. X        bp->b_ptr[j] = s;
  1836. X        bp->b_flags[j] = 0;
  1837. X        ++bp->b_count;
  1838. X        curr_count_max = curr_count + bp->b_count;
  1839. X    }
  1840. X    return TRUE;
  1841. X}
  1842. X
  1843. X/*
  1844. X * delsline: delete line from storage
  1845. X *
  1846. X * the line is turned over to the caller
  1847. X */
  1848. X    char *
  1849. Xdelsline(nr, delmarks)
  1850. X    linenr_t    nr;
  1851. X    int            delmarks;
  1852. X{
  1853. X    char    *ptr;
  1854. X    register block_t    *bp;
  1855. X    register char **pp;
  1856. X    register char *fp;
  1857. X    register int i;
  1858. X
  1859. X    if (nr < 1 || nr > line_count)
  1860. X    {
  1861. X        emsg("delsline: nr wrong");
  1862. X        return (alloc_line(0));
  1863. X    }
  1864. X    ptr = nr2ptr(nr);
  1865. X    if (delmarks)
  1866. X        adjustmark(ptr, NULL);            /* remove marks for this line (slow!) */
  1867. X    bp = curr_block;
  1868. X    if (line_count == 1)    /* don't delete the last line in the file */
  1869. X    {
  1870. X        bp->b_ptr[0] = alloc_line(0);
  1871. X        return (ptr);
  1872. X    }
  1873. X    --line_count;
  1874. X
  1875. X    /* move the rest of the ptrs in this block one down */
  1876. X    pp = &(bp->b_ptr[nr - curr_count]);
  1877. X    fp = &(bp->b_flags[nr - curr_count]);
  1878. X    for (i = bp->b_count + curr_count - nr - 1; --i >= 0; ++pp, ++fp)
  1879. X    {
  1880. X        *pp = *(pp + 1);
  1881. X        *fp = *(fp + 1);
  1882. X    }
  1883. X    if (--bp->b_count == 0) /* the block became empty, remove it from the list */
  1884. X    {
  1885. X        if (bp->b_prev == NULL)
  1886. X            first_block = bp->b_next;
  1887. X        else
  1888. X            bp->b_prev->b_next = bp->b_next;
  1889. X        if (bp->b_next == NULL)
  1890. X            last_block = bp->b_prev;
  1891. X        else
  1892. X            bp->b_next->b_prev = bp->b_prev;
  1893. X        free_line((char *)bp);
  1894. X        curr_count = 0; /* curr_block invalid */
  1895. X    }
  1896. X    else
  1897. X        --curr_count_max;
  1898. X    return (ptr);
  1899. X}
  1900. X
  1901. X/*
  1902. X * replace the line "lnum" with the line "new".
  1903. X * return the old line (which should be freed by the caller)
  1904. X */
  1905. X    char *
  1906. Xreplaceline(lnum, new)
  1907. X    linenr_t lnum;
  1908. X    char *new;
  1909. X{
  1910. X    char *old;
  1911. X
  1912. X    old = nr2ptr(lnum);
  1913. X    if (new == NULL || curr_count == 0)    /* we don't want NULL pointers in the list */
  1914. X        return (alloc_line(0)); /* be friendly to the caller */
  1915. X
  1916. X    curr_block->b_ptr[lnum - curr_count] = new;
  1917. X    curr_block->b_flags[lnum - curr_count] = 0;
  1918. X    adjustmark(old, new);
  1919. X    return (old);
  1920. X}
  1921. X
  1922. X/*
  1923. X * canincrease(n) - returns TRUE if the current line can be increased 'n'
  1924. X * bytes
  1925. X *
  1926. X * This routine returns immediately if the requested space is available. If not,
  1927. X * it attempts to allocate the space and adjust the data structures
  1928. X * accordingly. If everything fails it returns FALSE.
  1929. X */
  1930. X    int
  1931. Xcanincrease(n)
  1932. X    int    n;
  1933. X{
  1934. X    register char    *old;
  1935. X    register char    *new;        /* pointer to new space */
  1936. X    register unsigned newsize;
  1937. X
  1938. X    old = nr2ptr(Curpos.lnum);
  1939. X    newsize = strlen(old) + n;
  1940. X
  1941. X    new = alloc_line(newsize);
  1942. X    if (new == NULL)
  1943. X        return FALSE;
  1944. X
  1945. X    strcpy(new, old);
  1946. X    adjustmark(old, new);
  1947. X    free_line(old);
  1948. X    curr_block->b_ptr[Curpos.lnum - curr_count] = new;
  1949. X    curr_block->b_flags[Curpos.lnum - curr_count] = 0;
  1950. X
  1951. X    return TRUE;
  1952. X}
  1953. END_OF_FILE
  1954. if test 23385 -ne `wc -c <'vim/src/storage.c'`; then
  1955.     echo shar: \"'vim/src/storage.c'\" unpacked with wrong size!
  1956. fi
  1957. chmod +x 'vim/src/storage.c'
  1958. # end of 'vim/src/storage.c'
  1959. fi
  1960. echo shar: End of archive 11 \(of 25\).
  1961. cp /dev/null ark11isdone
  1962. MISSING=""
  1963. 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 ; do
  1964.     if test ! -f ark${I}isdone ; then
  1965.     MISSING="${MISSING} ${I}"
  1966.     fi
  1967. done
  1968. if test "${MISSING}" = "" ; then
  1969.     echo You have unpacked all 25 archives.
  1970.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1971. else
  1972.     echo You still need to unpack the following archives:
  1973.     echo "        " ${MISSING}
  1974. fi
  1975. ##  End of shell archive.
  1976. exit 0
  1977.  
  1978. ===============================================================================
  1979. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  1980. Oce Nederland B.V., Research & Development | necessarily represent the position
  1981. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  1982. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  1983. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  1984.  
  1985. exit 0 # Just in case...
  1986.