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

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i056:  vim - Vi IMitation editor, v2.0, Part06/25
  4. Message-ID: <1993Dec21.034449.27319@sparky.sterling.com>
  5. X-Md4-Signature: 8b9340c3976466881e3dcb467cb15291
  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:44:49 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 56
  14. Archive-name: vim/part06
  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 6 (of 25)."
  25. # Contents:  vim/src/script.c vim/src/term.h vim/src/termlib.c
  26. #   vim/src/undo.c
  27. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:05 1993
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'vim/src/script.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'vim/src/script.c'\"
  31. else
  32. echo shar: Extracting \"'vim/src/script.c'\" \(12921 characters\)
  33. sed "s/^X//" >'vim/src/script.c' <<'END_OF_FILE'
  34. X/* vi:ts=4:sw=4
  35. X *
  36. X * VIM - Vi IMproved
  37. X *
  38. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  39. X *                            Tim Thompson            twitch!tjt
  40. X *                            Tony Andrews            onecom!wldrdg!tony 
  41. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  42. X */
  43. X
  44. X/*
  45. X * script.c: functions for handling script files
  46. X */
  47. X
  48. X#include "vim.h"
  49. X#include "globals.h"
  50. X#include "proto.h"
  51. X#include "param.h"
  52. X
  53. Xstatic char *scriptname;            /* name of the script in use */
  54. Xstatic FILE *autoscriptfd = NULL;
  55. Xstatic char *makescriptname __ARGS((void));
  56. Xstatic void Supdatescript __ARGS((char *));
  57. X
  58. Xextern int global_busy;            /* this is in csearch.c */
  59. X
  60. X/*
  61. X * for Amiga Dos 2.0x we use Open/Close/Flush instead of fopen/fclose
  62. X */
  63. X#ifdef AMIGA
  64. X# ifndef NO_ARP
  65. Xextern int dos2;                    /* this is in amiga.c */
  66. X# endif
  67. X# ifdef SASC
  68. X#  include <proto/dos.h>
  69. X# endif
  70. X#endif
  71. X
  72. X/*
  73. X * We use this flag to avoid writing :win to commands to the script file
  74. X * during startup.
  75. X */
  76. Xstatic int script_started = FALSE;
  77. X
  78. X/*
  79. X * startscript(): open automatic script file
  80. X */
  81. X    void
  82. Xstartscript()
  83. X{
  84. X    int        n;
  85. X    char    buf[25];
  86. X#ifdef AMIGA
  87. X    int        r;
  88. X    FILE    *dummyfd = NULL;
  89. X#endif
  90. X#ifdef UNIX
  91. X# ifdef SCO
  92. X    mode_t    oldmask;
  93. X# else
  94. X    int        oldmask;
  95. X# endif
  96. X#endif
  97. X
  98. X    script_started = TRUE;
  99. X
  100. X#ifdef AMIGA
  101. X/*
  102. X * With Amiga DOS 2.0 the system may lockup with the sequence: write to .vim
  103. X * file, close it, delete it, create a new .vim file and write to it.
  104. X * This is a problem in the filesystem hash chains (solved in version 39.xx).
  105. X * The Delay seems to solve this problem, maybe because DOS gets a chance to
  106. X * finish closing and deleting the old .vim file. Also do this for DOS 1.3,
  107. X * just in case.
  108. X */
  109. X    if (stopscript())
  110. X        Delay(10L);        /* This should fix the lockup bug */
  111. X#else
  112. X    stopscript();        /* stop any old script */
  113. X#endif
  114. X
  115. X    if (p_uc == 0 || exiting)    /* no auto script wanted/needed */
  116. X        return;
  117. X    if (Changed)
  118. X        emsg("Warning: buffer already changed, auto script file will be incomplete");
  119. X
  120. X#ifdef AMIGA
  121. X/*
  122. X * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
  123. X * compatible filesystem, it is possible that the file "test.doc.vim" which we
  124. X * create will be exactly the same file. To avoid this problem we temporarily
  125. X * create "test.doc".
  126. X */
  127. X    if (!(p_sn || thisfile_sn) && xFilename && getperm(xFilename) < 0)
  128. X        dummyfd = fopen(xFilename, "w");
  129. X#endif
  130. X
  131. X/*
  132. X * we try different names until we find one that does not exist yet
  133. X */
  134. X    scriptname = makescriptname();
  135. X    for (;;)
  136. X    {
  137. X        if (scriptname == NULL)        /* must be out of memory */
  138. X            break;
  139. X        if ((n = strlen(scriptname)) == 0)    /* safety check */
  140. X        {
  141. X            free(scriptname);
  142. X            break;
  143. X        }
  144. X        
  145. X        /*
  146. X         * check if the scriptfile already exists
  147. X         */
  148. X        if (getperm(scriptname) < 0)        /* it does not exist */
  149. X        {
  150. X                /*
  151. X                 * Create the autoscript file.
  152. X                 */
  153. X#ifdef UNIX
  154. X            /*
  155. X             * Disallow others to read our .vim file. This is useful if the
  156. X             * .vim file is put in some public place like /tmp.
  157. X             */
  158. X# ifdef SCO
  159. X            oldmask = umask((mode_t)066);    /* rw------- */
  160. X# else
  161. X            oldmask = umask(066);            /* rw------- */
  162. X# endif
  163. X#endif
  164. X#ifdef AMIGA
  165. X# ifndef NO_ARP
  166. X            if (dos2)
  167. X# endif
  168. X                autoscriptfd = (FILE *)Open((UBYTE *)scriptname, (long)MODE_NEWFILE);
  169. X# ifndef NO_ARP
  170. X            else
  171. X                autoscriptfd = fopen(scriptname, "w");
  172. X# endif
  173. X#else    /* !AMIGA */
  174. X            autoscriptfd = fopen(scriptname, WRITEBIN);
  175. X#endif    /* AMIGA */
  176. X#ifdef UNIX
  177. X            umask(oldmask);                /* back to default umask */
  178. X#endif
  179. X
  180. X#ifdef AMIGA
  181. X            /*
  182. X             * on the Amiga getperm() will return -1 when the file exists but
  183. X             * is being used by another program. This happens if you edit
  184. X             * a file twice.
  185. X             */
  186. X            if (autoscriptfd != NULL || (IoErr() != ERROR_OBJECT_IN_USE && IoErr() != ERROR_OBJECT_EXISTS))
  187. X#endif
  188. X                break;
  189. X        }
  190. X    /*
  191. X     * get here when file already exists
  192. X     */
  193. X        if (scriptname[n - 1] == 'm')        /* first try */
  194. X        {
  195. X#ifdef AMIGA
  196. X        /*
  197. X         * on MS-DOS compatible filesystems (e.g. messydos) file.doc.vim
  198. X         * and file.doc are the same file. To guess if this problem is
  199. X         * present try if file.doc.vix exists. If it does, we set thisfile_sn
  200. X         * and try file_doc.vim (dots replaced by underscores for this file),
  201. X         * and try again. If it doesn't we assume that "file.doc.vim" already
  202. X         * exists.
  203. X         */
  204. X            if (!(p_sn || thisfile_sn))        /* not tried yet */
  205. X            {
  206. X                scriptname[n - 1] = 'x';
  207. X                r = getperm(scriptname);    /* try "file.vix" */
  208. X                scriptname[n - 1] = 'm';
  209. X                if (r >= 0)                    /* it seems to exist */
  210. X                {
  211. X                    thisfile_sn = TRUE;
  212. X                    free(scriptname);
  213. X                    scriptname = makescriptname();    /* '.' replaced by '_' */
  214. X                    continue;                        /* try again */
  215. X                }
  216. X            }
  217. X#endif
  218. X            /* if we get here ".vim" file really exists */
  219. X            if (!recoverymode)
  220. X                emsg(".vim file exists: an edit of this file has not been finished");
  221. X        }
  222. X
  223. X        if (scriptname[n - 1] == 'a')    /* tried enough names, give up */
  224. X        {
  225. X            free(scriptname);
  226. X            break;
  227. X        }
  228. X        --scriptname[n - 1];                /* change last char of the name */
  229. X    }
  230. X    if (autoscriptfd != NULL)        /* ".vim" file has been created */
  231. X    {
  232. X        script_winsize();            /* always start with a :win command */
  233. X                                    /* output cursor position if neccessary */
  234. X        if (Curpos.lnum > 1 || Curpos.col > 0)
  235. X        {
  236. X            sprintf(buf, "%ldG0%dl", (long)Curpos.lnum, (int)Curpos.col);
  237. X            Supdatescript(buf);
  238. X        }
  239. X    }
  240. X
  241. X#ifdef AMIGA
  242. X    if (dummyfd)        /* file has been created temporarily */
  243. X    {
  244. X        fclose(dummyfd);
  245. X        remove(xFilename);
  246. X    }
  247. X#endif
  248. X}
  249. X
  250. X    int
  251. Xstopscript()
  252. X{
  253. X    if (!autoscriptfd)
  254. X        return FALSE;        /* nothing to stop */
  255. X
  256. X#ifdef AMIGA
  257. X# ifndef NO_ARP
  258. X    if (dos2)
  259. X# endif
  260. X        Close((BPTR)autoscriptfd);
  261. X# ifndef NO_ARP
  262. X    else
  263. X        fclose(autoscriptfd);
  264. X# endif
  265. X#else
  266. X    fclose(autoscriptfd);
  267. X#endif
  268. X    remove(scriptname);        /* delete the file */
  269. X    autoscriptfd = NULL;
  270. X    free(scriptname);
  271. X    return TRUE;
  272. X}
  273. X
  274. X/*
  275. X * open new script file
  276. X * return 0 on success, 1 on error
  277. X */
  278. X    int
  279. Xopenscript(name)
  280. X    char *name;
  281. X{
  282. X    int oldcurscript;
  283. X
  284. X    if (curscript + 1 == NSCRIPT)
  285. X    {
  286. X        emsg(e_nesting);
  287. X        return 1;
  288. X    }
  289. X    else
  290. X    {
  291. X        if (scriptin[curscript] != NULL)    /* already reading script */
  292. X            ++curscript;
  293. X        if ((scriptin[curscript] = fopen((char *)name, READBIN)) == NULL)
  294. X        {
  295. X            emsg(e_notopen);
  296. X            if (curscript)
  297. X                --curscript;
  298. X            return 1;
  299. X        }
  300. X        /*
  301. X         * With command ":g/pat/so! file" we have to execute the
  302. X         * commands from the file now.
  303. X         */
  304. X        if (global_busy)
  305. X        {
  306. X            State = NORMAL;
  307. X            oldcurscript = curscript;
  308. X            do
  309. X            {
  310. X                normal();
  311. X                vpeekc();            /* check for end of file */
  312. X            }
  313. X            while (scriptin[oldcurscript]);
  314. X            State = CMDLINE;
  315. X        }
  316. X    }
  317. X    return 0;
  318. X}
  319. X
  320. X/*
  321. X * updatescipt() is called when a character has to be written into the script file
  322. X * or when we have waited some time for a character (c == 0)
  323. X */
  324. X    void
  325. Xupdatescript(c)
  326. X    int c;
  327. X{
  328. X    static int count = 0;
  329. X
  330. X    if (c && scriptout)
  331. X        putc(c, scriptout);
  332. X    if (autoscriptfd == NULL || (c == 0 && count == 0))        /* nothing to do */
  333. X        return;
  334. X    if (c)
  335. X    {
  336. X#ifdef AMIGA
  337. X# ifndef NO_ARP
  338. X        if (dos2)
  339. X# endif
  340. X            FPutC((BPTR)autoscriptfd, (unsigned long)c);
  341. X# ifndef NO_ARP
  342. X        else
  343. X            putc(c, autoscriptfd);
  344. X# endif
  345. X#else
  346. X        putc(c, autoscriptfd);
  347. X#endif
  348. X        ++count;
  349. X    }
  350. X    if ((c == 0 || count >= p_uc) && Updated)
  351. X    {
  352. X        /*
  353. X         * Before DOS 2.0x we have to close and open the file in order to really
  354. X         * get the characters in the file to disk!
  355. X         * With DOS 2.0x Flush() can be used for that
  356. X         */
  357. X#ifdef AMIGA
  358. X# ifndef NO_ARP
  359. X        if (dos2)
  360. X# endif
  361. X            Flush((BPTR)autoscriptfd);
  362. X# ifndef NO_ARP
  363. X        else
  364. X        {
  365. X            fclose(autoscriptfd);
  366. X            autoscriptfd = fopen(scriptname, "a");
  367. X        }
  368. X# endif
  369. X#else     /* !AMIGA */
  370. X        fclose(autoscriptfd);
  371. X# ifdef MSDOS
  372. X        autoscriptfd = fopen(scriptname, "ab");
  373. X# else
  374. X        autoscriptfd = fopen(scriptname, "a");
  375. X# endif
  376. X#endif
  377. X        count = 0;
  378. X        Updated = 0;
  379. X    }
  380. X}
  381. X
  382. X    static void
  383. XSupdatescript(str)
  384. X    char *str;
  385. X{
  386. X    while (*str)
  387. X        updatescript(*str++);
  388. X}
  389. X
  390. X/*
  391. X * try to open the ".vim" file for recovery
  392. X * if recoverymode is 1: start recovery, set recoverymode to 2
  393. X * if recoverymode is 2: stop recovery mode
  394. X */
  395. X    void
  396. Xopenrecover()
  397. X{
  398. X    char *fname;
  399. X    struct stat efile, rfile;
  400. X
  401. X    if (recoverymode == 2)        /* end of recovery */
  402. X    {
  403. X        recoverymode = 0;
  404. X        if (got_int)
  405. X            emsg("Recovery Interrupted");
  406. X        else
  407. X            msg("Recovery completed; If everything is OK: Save this file and delete the .vim file");
  408. X            /* The cursor will be in the wrong place after the msg() */
  409. X            /* We need to fix it here because we are called from inchar() */
  410. X        setcursor();
  411. X        flushbuf();
  412. X    }
  413. X    else
  414. X    {
  415. X        fname = makescriptname();
  416. X        if (fname)
  417. X        {
  418. X            recoverymode = 2;
  419. X            if (xFilename != NULL &&
  420. X                    stat(xFilename, &efile) != -1 &&
  421. X                    stat(fname, &rfile) != -1 &&
  422. X                    efile.st_mtime > rfile.st_mtime)
  423. X                emsg(".vim file is older; file not recovered");
  424. X            else
  425. X            {
  426. X                if (openscript(fname))
  427. X                    emsg("Cannot open .vim file; file not recovered");
  428. X            }
  429. X            free(fname);
  430. X        }
  431. X    }
  432. X}
  433. X
  434. X/*
  435. X * make script name out of the filename
  436. X */
  437. X    static char *
  438. Xmakescriptname()
  439. X{
  440. X    char    *r, *s, *fname;
  441. X
  442. X    r = modname(xFilename, ".vim");
  443. X    if (*p_dir == 0 || r == NULL)
  444. X        return r;
  445. X
  446. X    fname = gettail(r);
  447. X    s = alloc((unsigned)(strlen(p_dir) + strlen(fname) + 1));
  448. X    if (s != NULL)
  449. X    {
  450. X        strcpy(s, p_dir);
  451. X        if (*s && !ispathsep(*(s + strlen(s) - 1)))    /* don't add '/' after ':' */
  452. X            strcat(s, PATHSEPSTR);
  453. X        strcat(s, fname);
  454. X    }
  455. X    free(r);
  456. X    return s;
  457. X}
  458. X
  459. X/*
  460. X * add full path to auto script name, used before first :cd command.
  461. X */
  462. X    void
  463. Xscriptfullpath()
  464. X{
  465. X    char *s;
  466. X
  467. X    if (!autoscriptfd)
  468. X        return;        /* nothing to do */
  469. X    /*
  470. X     * on the Amiga we cannot get the full path name while the file is open
  471. X     * so we close it for a moment
  472. X     */
  473. X#ifdef AMIGA
  474. X# ifndef NO_ARP
  475. X    if (dos2)
  476. X# endif
  477. X        Close((BPTR)autoscriptfd);
  478. X# ifndef NO_ARP
  479. X    else
  480. X        fclose(autoscriptfd);
  481. X# endif
  482. X#endif
  483. X
  484. X    if (FullName(scriptname, IObuff, IOSIZE))
  485. X    {
  486. X        s = strsave(IObuff);
  487. X        if (s)
  488. X        {
  489. X            free(scriptname);
  490. X            scriptname = s;
  491. X        }
  492. X    }
  493. X
  494. X#ifdef AMIGA
  495. X# ifndef NO_ARP
  496. X    if (dos2)
  497. X# endif
  498. X    {
  499. X        autoscriptfd = (FILE *)Open((UBYTE *)scriptname, (long)MODE_OLDFILE);
  500. X        if (autoscriptfd)
  501. X            Seek((BPTR)autoscriptfd, 0L, (long)OFFSET_END);
  502. X    }
  503. X# ifndef NO_ARP
  504. X    else
  505. X        autoscriptfd = fopen(scriptname, "a");
  506. X# endif
  507. X#endif
  508. X}
  509. X
  510. X/*
  511. X * add extention to filename - change path/fo.o.h to path/fo.o.h.ext or
  512. X * fo_o_h.ext for MSDOS or when dotfname option reset.
  513. X *
  514. X * Assumed that fname is a valid name found in the filesystem we assure that
  515. X * the return value is a different name and ends in ".ext".
  516. X * "ext" MUST start with a "." and MUST be at most 4 characters long.
  517. X * Space for the returned name is allocated, must be freed later.
  518. X */
  519. X
  520. X    char *
  521. Xmodname(fname, ext)
  522. X    char *fname, *ext;
  523. X{
  524. X    char            *retval;
  525. X    register char   *s;
  526. X    register char   *ptr;
  527. X    register int    fnamelen, extlen;
  528. X    char            currentdir[512];
  529. X
  530. X    extlen = strlen(ext);
  531. X
  532. X    /*
  533. X     * if there is no filename we must get the name of the current directory
  534. X     * (we need the full path in case :cd is used)
  535. X     */
  536. X    if (fname == NULL || *fname == NUL)
  537. X    {
  538. X        (void)dirname(currentdir, 511);
  539. X        strcat(currentdir, PATHSEPSTR);
  540. X        fnamelen = strlen(currentdir);
  541. X    }
  542. X    else
  543. X        fnamelen = strlen(fname);
  544. X    retval = alloc((unsigned) (fnamelen + extlen + 1));
  545. X    if (retval != NULL)
  546. X    {
  547. X        if (fname == NULL || *fname == NUL)
  548. X            strcpy(retval, currentdir);
  549. X        else
  550. X            strcpy(retval, fname);
  551. X        /*
  552. X         * search backwards until we hit a '/', '\' or ':' replacing all '.' by '_'
  553. X         * for MSDOS or when dotfname option reset.
  554. X         * Then truncate what is after the '/', '\' or ':' to 8 characters for MSDOS
  555. X         * and 26 characters for AMIGA and UNIX.
  556. X         */
  557. X        for (ptr = retval + fnamelen; ptr >= retval; ptr--)
  558. X        {
  559. X#ifndef MSDOS
  560. X            if (p_sn || thisfile_sn)
  561. X#endif
  562. X                if (*ptr == '.')    /* replace '.' by '_' */
  563. X                    *ptr = '_';
  564. X            if (ispathsep(*ptr))
  565. X                break;
  566. X        }
  567. X        ptr++;
  568. X
  569. X        /* the filename has at most BASENAMELEN characters. */
  570. X        if (strlen(ptr) > (unsigned)BASENAMELEN)
  571. X            ptr[BASENAMELEN] = '\0';
  572. X#ifndef MSDOS
  573. X        if ((p_sn || thisfile_sn) && strlen(ptr) > (unsigned)8)
  574. X            ptr[8] = '\0';
  575. X#endif
  576. X        s = ptr + strlen(ptr);
  577. X
  578. X        /*
  579. X         * Append the extention.
  580. X         * ext must start with '.' and cannot exceed 3 more characters.
  581. X         */
  582. X        strcpy(s, ext);
  583. X        if (fname != NULL && strcmp(fname, retval) == 0)
  584. X        {
  585. X            /* after modification still the same name? */
  586. X            /* we search for a character that can be replaced by '_' */
  587. X            while (--s >= ptr)
  588. X            {
  589. X                if (*s != '_')
  590. X                {
  591. X                    *s = '_';
  592. X                    break;
  593. X                }
  594. X            }
  595. X            if (s < ptr)
  596. X            {
  597. X                /* fname was "________.<ext>" how tricky! */
  598. X                *ptr = 'v';
  599. X            }
  600. X        }
  601. X    }
  602. X    return retval;
  603. X}
  604. X
  605. X/*
  606. X * the new window size must be used in scripts;
  607. X * write a ":winsize width height" command to the (auto)script
  608. X * Postpone this action if not in NORMAL State, otherwise we may insert the
  609. X * command halfway another command.
  610. X */
  611. Xint script_winsize_postponed = FALSE;
  612. X
  613. X    void
  614. Xscript_winsize()
  615. X{
  616. X    char            buf[25];
  617. X
  618. X    if (!script_started || State != NORMAL)        /* postpone action */
  619. X    {
  620. X        script_winsize_postponed = TRUE;
  621. X        return;
  622. X    }
  623. X
  624. X    sprintf(buf, ":win %d %d\r", (int)Columns, (int)Rows);
  625. X    Supdatescript(buf);
  626. X    script_winsize_postponed = FALSE;
  627. X}
  628. X
  629. X/*
  630. X * This function is called after each "State = NORMAL"
  631. X */
  632. X    void
  633. Xscript_winsize_pp()
  634. X{
  635. X    if (script_winsize_postponed)
  636. X        script_winsize();
  637. X}
  638. END_OF_FILE
  639. if test 12921 -ne `wc -c <'vim/src/script.c'`; then
  640.     echo shar: \"'vim/src/script.c'\" unpacked with wrong size!
  641. fi
  642. chmod +x 'vim/src/script.c'
  643. # end of 'vim/src/script.c'
  644. fi
  645. if test -f 'vim/src/term.h' -a "${1}" != "-c" ; then 
  646.   echo shar: Will not clobber existing file \"'vim/src/term.h'\"
  647. else
  648. echo shar: Extracting \"'vim/src/term.h'\" \(13223 characters\)
  649. sed "s/^X//" >'vim/src/term.h' <<'END_OF_FILE'
  650. X/* vi:ts=4:sw=4
  651. X *
  652. X * term.h -- VIM - Vi IMproved
  653. X *
  654. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  655. X *                            Tim Thompson            twitch!tjt
  656. X *                            Tony Andrews            onecom!wldrdg!tony 
  657. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  658. X */
  659. X
  660. X/*
  661. X * This file contains the machine dependent escape sequences that the editor
  662. X * needs to perform various operations. Some of the sequences here are
  663. X * optional. Anything not available should be indicated by a null string. In
  664. X * the case of insert/delete line sequences, the editor checks the capability
  665. X * and works around the deficiency, if necessary.
  666. X */
  667. X
  668. X/*
  669. X * the terminal capabilities are stored in this structure
  670. X * keep in sync with array in term.c
  671. X */
  672. Xtypedef struct _tcarr
  673. X{
  674. X/* output codes */
  675. X  char *t_name;        /* name of this terminal entry */
  676. X  char *t_el;        /* el       ce    clear to end of line */
  677. X  char *t_il;        /* il1      al    add new blank line */
  678. X  char *t_cil;        /* il       AL    add number of blank lines */
  679. X  char *t_dl;        /* dl1      dl    delete line */
  680. X  char *t_cdl;        /* dl       DL    delete number of lines */
  681. X  char *t_ed;        /* clear    cl    clear screen */
  682. X  char *t_ci;        /* civis    vi    cursur invisible */
  683. X  char *t_cv;        /* cnorm    ve    cursur visible */
  684. X  char *t_tp;        /* sgr0     me    normal mode */
  685. X  char *t_ti;        /* rev      mr    reverse mode */
  686. X  char *t_cm;        /* cup      cm    cursor motion */
  687. X  char *t_sr;        /* ri       sr    scroll reverse (backward) */
  688. X  char *t_cri;        /* cuf      RI    cursor number of chars right */
  689. X  char *t_vb;        /* flash    vb    visual bell */
  690. X  char *t_ks;        /* smkx     ks    put terminal in "keypad transmit" mode */
  691. X  char *t_ke;        /* rmkx     ke    out of "keypad transmit" mode */
  692. X  char *t_ts;        /*          ti    put terminal in termcap mode */
  693. X  char *t_te;        /*          te    out of termcap mode */
  694. X
  695. X/* key codes */
  696. X  char *t_ku;        /* kcuu1    ku    arrow up */
  697. X  char *t_kd;        /* kcud1    kd    arrow down */
  698. X  char *t_kl;        /* kcub1    kl    arrow left */
  699. X  char *t_kr;        /* kcuf1    kr    arrow right */
  700. X  char *t_sku;        /* shift arrow up */
  701. X  char *t_skd;        /* shift arrow down */
  702. X  char *t_skl;        /* kLFT     #4    shift arrow left */
  703. X  char *t_skr;        /* kRIT     %    shift arrow right */
  704. X  char *t_f1;        /* kf1      k1    function key 1 */
  705. X  char *t_f2;        /* kf2      k2    function key 2 */
  706. X  char *t_f3;        /* kf3      k3    function key 3 */
  707. X  char *t_f4;        /* kf4      k4    function key 4 */
  708. X  char *t_f5;        /* kf5      k5    function key 5 */
  709. X  char *t_f6;        /* kf6      k6    function key 6 */
  710. X  char *t_f7;        /* kf7      k7    function key 7 */
  711. X  char *t_f8;        /* kf8      k8    function key 8 */
  712. X  char *t_f9;        /* kf9      k9    function key 9 */
  713. X  char *t_f10;        /* kf10     k;    function key 10 */
  714. X  char *t_sf1;        /* kf11     F1    shifted function key 1 */
  715. X  char *t_sf2;        /* kf12     F2    shifted function key 2 */
  716. X  char *t_sf3;        /* kf13     F3    shifted function key 3 */
  717. X  char *t_sf4;        /* kf14     F4    shifted function key 4 */
  718. X  char *t_sf5;        /* kf15     F5    shifted function key 5 */
  719. X  char *t_sf6;        /* kf16     F6    shifted function key 6 */
  720. X  char *t_sf7;        /* kf17     F7    shifted function key 7 */
  721. X  char *t_sf8;        /* kf18     F8    shifted function key 8 */
  722. X  char *t_sf9;        /* kf19     F9    shifted function key 9 */
  723. X  char *t_sf10;        /* kf20     FA    shifted function key 10 */
  724. X  char *t_help;        /* khlp     %1    help key */
  725. X  char *t_undo;        /* kund     &8    undo key */
  726. X  /* adjust inchar() for last entry! */
  727. X} Tcarr;
  728. X
  729. Xextern Tcarr term_strings;    /* currently used terminal strings */
  730. X
  731. X/*
  732. X * strings used for terminal
  733. X */
  734. X#define T_EL    (term_strings.t_el)
  735. X#define T_IL    (term_strings.t_il)
  736. X#define T_CIL    (term_strings.t_cil)
  737. X#define T_DL    (term_strings.t_dl)
  738. X#define T_CDL    (term_strings.t_cdl)
  739. X#define T_ED    (term_strings.t_ed)
  740. X#define T_CI    (term_strings.t_ci)
  741. X#define T_CV    (term_strings.t_cv)
  742. X#define T_TP    (term_strings.t_tp)
  743. X#define T_TI    (term_strings.t_ti)
  744. X#define T_CM    (term_strings.t_cm)
  745. X#define T_SR    (term_strings.t_sr)
  746. X#define T_CRI    (term_strings.t_cri)
  747. X#define T_VB    (term_strings.t_vb)
  748. X#define T_KS    (term_strings.t_ks)
  749. X#define T_KE    (term_strings.t_ke)
  750. X#define T_TS    (term_strings.t_ts)
  751. X#define T_TE    (term_strings.t_te)
  752. X
  753. X
  754. X#ifndef TERMINFO
  755. X# ifndef NO_BUILTIN_TCAPS
  756. X/*
  757. X * here are the builtin termcap entries.
  758. X * They not stored as complete Tcarr structures, as such a structure 
  759. X * is to big. 
  760. X * Each termcap is a concatenated string of entries, where '\0' characters
  761. X * followed by a skip character sepereate the capabilities. The skip 
  762. X * character is the relative structure offset for the following entry.
  763. X * See parse_builtin_tcap() in term.c for all details.
  764. X */
  765. X#  define AMIGA_TCAP "amiga\0\
  766. X\0\033[K\0\
  767. X\0\033[L\0\
  768. X\0\033[%dL\0\
  769. X\0\033[M\0\
  770. X\0\033[%dM\0\
  771. X\0\014\0\
  772. X\0\033[0 p\0\
  773. X\0\033[1 p\0\
  774. X\0\033[0m\0\
  775. X\0\033[7m\0\
  776. X\0\033[%i%d;%dH\0\
  777. X\1\033[%dC\0\
  778. X\5\233A\0\
  779. X\0\233B\0\
  780. X\0\233D\0\
  781. X\0\233C\0\
  782. X\0\233T\0\
  783. X\0\233S\0\
  784. X\0\233 A\0\
  785. X\0\233 @\0\
  786. X\0\233\060~\0\
  787. X\0\233\061~\0\
  788. X\0\233\062~\0\
  789. X\0\233\063~\0\
  790. X\0\233\064~\0\
  791. X\0\233\065~\0\
  792. X\0\233\066~\0\
  793. X\0\233\067~\0\
  794. X\0\233\070~\0\
  795. X\0\233\071~\0\
  796. X\0\233\061\060~\0\
  797. X\0\233\061\061~\0\
  798. X\0\233\061\062~\0\
  799. X\0\233\061\063~\0\
  800. X\0\233\061\064~\0\
  801. X\0\233\061\065~\0\
  802. X\0\233\061\066~\0\
  803. X\0\233\061\067~\0\
  804. X\0\233\061\070~\0\
  805. X\0\233\061\071~\0\
  806. X\0\233?~\0\
  807. X\0\0"
  808. X
  809. X#  define ATARI_TCAP "atari\0\
  810. X\0\033l\0\
  811. X\0\033L\0\
  812. X\1\033M\0\
  813. X\1\033E\0\
  814. X\0\033f\0\
  815. X\0\033e\0\
  816. X\0\0"
  817. X
  818. X#  define ANSI_TCAP "ansi\0\
  819. X\0\033[2K\0\
  820. X\0\033[L\0\
  821. X\0\033[%dL\0\
  822. X\0\033[M\0\
  823. X\0\033[%dM\0\
  824. X\0\033[2J\0\
  825. X\2\033[0m\0\
  826. X\0\033[7m\0\
  827. X\0\033[%i%d;%dH\0\
  828. X\1\033[%dC\0\
  829. X\0\0"
  830. X
  831. X/*
  832. X * These codes are valid when nansi.sys or equivalent has been installed.
  833. X * Function keys on a PC are preceded with a NUL. These are converted into
  834. X * K_NUL '\316' in GetChars(), because we cannot handle NULs in key codes.
  835. X * CTRL-arrow is used instead of SHIFT-arrow.
  836. X */
  837. X#  define PCANSI_TCAP "pcansi\0\
  838. X\0\033[K\0\
  839. X\0\033[L\0\
  840. X\1\033[M\0\
  841. X\1\033[2J\0\
  842. X\2\033[0m\0\
  843. X\0\033[7m\0\
  844. X\0\033[%i%d;%dH\0\
  845. X\1\033[%dC\0\
  846. X\5\316H\0\
  847. X\0\316P\0\
  848. X\0\316K\0\
  849. X\0\316M\0\
  850. X\2\316s\0\
  851. X\0\316t\0\
  852. X\0\316;\0\
  853. X\0\316<\0\
  854. X\0\316=\0\
  855. X\0\316>\0\
  856. X\0\316?\0\
  857. X\0\316@\0\
  858. X\0\316A\0\
  859. X\0\316B\0\
  860. X\0\316C\0\
  861. X\0\316D\0\
  862. X\0\316T\0\
  863. X\0\316U\0\
  864. X\0\316V\0\
  865. X\0\316W\0\
  866. X\0\316X\0\
  867. X\0\316Y\0\
  868. X\0\316Z\0\
  869. X\0\316[\0\
  870. X\0\316\\\0\
  871. X\0\316]\0\
  872. X\0\0"
  873. X
  874. X/*
  875. X * These codes are valid for the pc video.
  876. X * The entries that start with ESC | are translated into conio calls in msdos.c.
  877. X */
  878. X#  define PCTERM_TCAP "pcterm\0\
  879. X\0\033|K\0\
  880. X\0\033|L\0\
  881. X\1\033|M\0\
  882. X\1\033|J\0\
  883. X\2\033|0m\0\
  884. X\0\033|79m\0\
  885. X\0\033|%i%d;%dH\0\
  886. X\7\316H\0\
  887. X\0\316P\0\
  888. X\0\316K\0\
  889. X\0\316M\0\
  890. X\2\316s\0\
  891. X\0\316t\0\
  892. X\0\316;\0\
  893. X\0\316<\0\
  894. X\0\316=\0\
  895. X\0\316>\0\
  896. X\0\316?\0\
  897. X\0\316@\0\
  898. X\0\316A\0\
  899. X\0\316B\0\
  900. X\0\316C\0\
  901. X\0\316D\0\
  902. X\0\316T\0\
  903. X\0\316U\0\
  904. X\0\316V\0\
  905. X\0\316W\0\
  906. X\0\316X\0\
  907. X\0\316Y\0\
  908. X\0\316Z\0\
  909. X\0\316[\0\
  910. X\0\316\\\0\
  911. X\0\316]\0\
  912. X\0\0"
  913. X
  914. X#  define VT52_TCAP "vt52\0\
  915. X\0\033K\0\
  916. X\0\033T\0\
  917. X\1\033U\0\
  918. X\1\014\0\
  919. X\2\033SO\0\
  920. X\0\033S2\0\
  921. X\0\033Y%+ %+ \0\
  922. X\0\0"
  923. X
  924. X/*
  925. X * The xterm termcap is missing F14 and F15, because they send the same
  926. X * codes as the undo and help key, although they don't work on all keyboards.
  927. X */
  928. X#  define XTERM_TCAP "xterm\0\
  929. X\0\033[K\0\
  930. X\0\033[L\0\
  931. X\0\033[%dL\0\
  932. X\0\033[M\0\
  933. X\0\033[%dM\0\
  934. X\0\033[H\033[2J\0\
  935. X\2\033[m\0\
  936. X\0\033[7m\0\
  937. X\0\033[%i%d;%dH\0\
  938. X\0\033M\0\
  939. X\0\033[%dC\0\
  940. X\1\033[?1h\033=\0\
  941. X\0\033[?1l\033>\0\
  942. X\0\0337\033[?47h\0\
  943. X\0\033[2J\033[?47l\0338\0\
  944. X\0\033OA\0\
  945. X\0\033OB\0\
  946. X\0\033OD\0\
  947. X\0\033OC\0\
  948. X\0\033Ox\0\
  949. X\0\033Or\0\
  950. X\0\033Ot\0\
  951. X\0\033Ov\0\
  952. X\0\033[11~\0\
  953. X\0\033[12~\0\
  954. X\0\033[13~\0\
  955. X\0\033[14~\0\
  956. X\0\033[15~\0\
  957. X\0\033[17~\0\
  958. X\0\033[18~\0\
  959. X\0\033[19~\0\
  960. X\0\033[20~\0\
  961. X\0\033[21~\0\
  962. X\0\033[23~\0\
  963. X\0\033[24~\0\
  964. X\0\033[25~\0\
  965. X\2\033[29~\0\
  966. X\0\033[31~\0\
  967. X\0\033[32~\0\
  968. X\0\033[33~\0\
  969. X\0\033[34~\0\
  970. X\0\033[28~\0\
  971. X\0\033[26~\0\
  972. X\0\0"
  973. X
  974. X#  define DEBUG_TCAP "debug\0\
  975. X\0[EL]\0\
  976. X\0[IL]\0\
  977. X\0[CIL%d]\0\
  978. X\0[DL]\0\
  979. X\0[CDL%d]\0\
  980. X\0[ED]\0\
  981. X\0[CI]\0\
  982. X\0[CV]\0\
  983. X\0[TP]\0\
  984. X\0[TI]\0\
  985. X\0[%dCM%d]\0\
  986. X\0[SR]\0\
  987. X\0[CRI%d]\0\
  988. X\0[VB]\0\
  989. X\0[KS]\0\
  990. X\0[KE]\0\
  991. X\0[TI]\0\
  992. X\0[TE]\0\
  993. X\0[KU]\0\
  994. X\0[KD]\0\
  995. X\0[KL]\0\
  996. X\0[KR]\0\
  997. X\0[SKU]\0\
  998. X\0[SKD]\0\
  999. X\0[SKL]\0\
  1000. X\0[SKR]\0\
  1001. X\0[F1]\0\
  1002. X\0[F2]\0\
  1003. X\0[F3]\0\
  1004. X\0[F4]\0\
  1005. X\0[F5]\0\
  1006. X\0[F6]\0\
  1007. X\0[F7]\0\
  1008. X\0[F8]\0\
  1009. X\0[F9]\0\
  1010. X\0[F10]\0\
  1011. X\0[SF1]\0\
  1012. X\0[SF2]\0\
  1013. X\0[SF3]\0\
  1014. X\0[SF4]\0\
  1015. X\0[SF5]\0\
  1016. X\0[SF6]\0\
  1017. X\0[SF7]\0\
  1018. X\0[SF8]\0\
  1019. X\0[SF9]\0\
  1020. X\0[SF10]\0\
  1021. X\0[HELP]\0\
  1022. X\0[UNDO]\0\
  1023. X\0\0"
  1024. X
  1025. X#  ifdef ATARI
  1026. X#   define DFLT_TCAP ATARI_TCAP
  1027. X#  endif /* ATARI */
  1028. X
  1029. X#  ifdef AMIGA
  1030. X#   define DFLT_TCAP AMIGA_TCAP
  1031. X#  endif /* AMIGA */
  1032. X
  1033. X#  ifdef MSDOS
  1034. X#   define DFLT_TCAP PCTERM_TCAP
  1035. X#  endif /* MSDOS */
  1036. X
  1037. X#  ifdef UNIX
  1038. X#   define DFLT_TCAP ANSI_TCAP
  1039. X#  endif /* UNIX */
  1040. X
  1041. X# else /* NO_BUILTIN_TCAPS */
  1042. X#  define DUMB_TCAP "dumb\0\
  1043. X\5\014\0\
  1044. X\4\033[%i%d;%dH\0\
  1045. X\0\0"
  1046. X# endif /* NO_BUILTIN_TCAPS */
  1047. X
  1048. X#else /* TERMINFO */
  1049. X# ifndef NO_BUILTIN_TCAPS
  1050. X/*
  1051. X * here are the builtin termcap entries.
  1052. X * They not stored as complete Tcarr structures, as such a structure 
  1053. X * is to big. 
  1054. X * Each termcap is a concatenated string of entries, where '\0' characters
  1055. X * followed by a skip character sepereate the capabilities. The skip 
  1056. X * character is the relative structure offset for the following entry.
  1057. X * See parse_builtin_tcap() in term.c for all details.
  1058. X */
  1059. X#  define AMIGA_TCAP "amiga\0\
  1060. X\0\033[K\0\
  1061. X\0\033[L\0\
  1062. X\0\033[%p1%dL\0\
  1063. X\0\033[M\0\
  1064. X\0\033[%p1%dM\0\
  1065. X\0\014\0\
  1066. X\0\033[0 p\0\
  1067. X\0\033[1 p\0\
  1068. X\0\033[0m\0\
  1069. X\0\033[7m\0\
  1070. X\0\033[%i%p1%d;%p2%dH\0\
  1071. X\1\033[%p1%dC\0\
  1072. X\5\233A\0\
  1073. X\0\233B\0\
  1074. X\0\233D\0\
  1075. X\0\233C\0\
  1076. X\0\233T\0\
  1077. X\0\233S\0\
  1078. X\0\233 A\0\
  1079. X\0\233 @\0\
  1080. X\0\233\060~\0\
  1081. X\0\233\061~\0\
  1082. X\0\233\062~\0\
  1083. X\0\233\063~\0\
  1084. X\0\233\064~\0\
  1085. X\0\233\065~\0\
  1086. X\0\233\066~\0\
  1087. X\0\233\067~\0\
  1088. X\0\233\070~\0\
  1089. X\0\233\071~\0\
  1090. X\0\233\061\060~\0\
  1091. X\0\233\061\061~\0\
  1092. X\0\233\061\062~\0\
  1093. X\0\233\061\063~\0\
  1094. X\0\233\061\064~\0\
  1095. X\0\233\061\065~\0\
  1096. X\0\233\061\066~\0\
  1097. X\0\233\061\067~\0\
  1098. X\0\233\061\070~\0\
  1099. X\0\233\061\071~\0\
  1100. X\0\233?~\0\
  1101. X\0\0"
  1102. X
  1103. X#  define ATARI_TCAP "atari\0\
  1104. X\0\033l\0\
  1105. X\0\033L\0\
  1106. X\1\033M\0\
  1107. X\1\033E\0\
  1108. X\0\033f\0\
  1109. X\0\033e\0\
  1110. X\0\0"
  1111. X
  1112. X#  define ANSI_TCAP "ansi\0\
  1113. X\0\033[2K\0\
  1114. X\0\033[L\0\
  1115. X\0\033[%p1%dL\0\
  1116. X\0\033[M\0\
  1117. X\0\033[%p1%dM\0\
  1118. X\0\033[2J\0\
  1119. X\2\033[0m\0\
  1120. X\0\033[7m\0\
  1121. X\0\033[%i%p1%d;%p2%dH\0\
  1122. X\1\033[%p1%dC\0\
  1123. X\0\0"
  1124. X
  1125. X/*
  1126. X * These codes are valid when nansi.sys or equivalent has been installed.
  1127. X * Function keys on a PC are preceded with a NUL. These are converted into
  1128. X * K_NUL '\316' in GetChars(), because we cannot handle NULs in key codes.
  1129. X * CTRL-arrow is used instead of SHIFT-arrow.
  1130. X */
  1131. X#  define PCANSI_TCAP "pcansi\0\
  1132. X\0\033[K\0\
  1133. X\0\033[L\0\
  1134. X\1\033[M\0\
  1135. X\1\033[2J\0\
  1136. X\2\033[0m\0\
  1137. X\0\033[7m\0\
  1138. X\0\033[%i%p1%d;%p2%dH\0\
  1139. X\1\033[%p1%dC\0\
  1140. X\5\316H\0\
  1141. X\0\316P\0\
  1142. X\0\316K\0\
  1143. X\0\316M\0\
  1144. X\2\316s\0\
  1145. X\0\316t\0\
  1146. X\0\316;\0\
  1147. X\0\316<\0\
  1148. X\0\316=\0\
  1149. X\0\316>\0\
  1150. X\0\316?\0\
  1151. X\0\316@\0\
  1152. X\0\316A\0\
  1153. X\0\316B\0\
  1154. X\0\316C\0\
  1155. X\0\316D\0\
  1156. X\0\316T\0\
  1157. X\0\316U\0\
  1158. X\0\316V\0\
  1159. X\0\316W\0\
  1160. X\0\316X\0\
  1161. X\0\316Y\0\
  1162. X\0\316Z\0\
  1163. X\0\316[\0\
  1164. X\0\316\\\0\
  1165. X\0\316]\0\
  1166. X\0\0"
  1167. X
  1168. X/*
  1169. X * These codes are valid for the pc video.
  1170. X * The entries that start with ESC | are translated into conio calls in msdos.c.
  1171. X */
  1172. X#  define PCTERM_TCAP "pcterm\0\
  1173. X\0\033|K\0\
  1174. X\0\033|L\0\
  1175. X\1\033|M\0\
  1176. X\1\033|J\0\
  1177. X\2\033|0m\0\
  1178. X\0\033|79m\0\
  1179. X\0\033|%i%p1%d;%p2%dH\0\
  1180. X\7\316H\0\
  1181. X\0\316P\0\
  1182. X\0\316K\0\
  1183. X\0\316M\0\
  1184. X\2\316s\0\
  1185. X\0\316t\0\
  1186. X\0\316;\0\
  1187. X\0\316<\0\
  1188. X\0\316=\0\
  1189. X\0\316>\0\
  1190. X\0\316?\0\
  1191. X\0\316@\0\
  1192. X\0\316A\0\
  1193. X\0\316B\0\
  1194. X\0\316C\0\
  1195. X\0\316D\0\
  1196. X\0\316T\0\
  1197. X\0\316U\0\
  1198. X\0\316V\0\
  1199. X\0\316W\0\
  1200. X\0\316X\0\
  1201. X\0\316Y\0\
  1202. X\0\316Z\0\
  1203. X\0\316[\0\
  1204. X\0\316\\\0\
  1205. X\0\316]\0\
  1206. X\0\0"
  1207. X
  1208. X#  define VT52_TCAP "vt52\0\
  1209. X\0\033K\0\
  1210. X\0\033T\0\
  1211. X\1\033U\0\
  1212. X\1\014\0\
  1213. X\2\033SO\0\
  1214. X\0\033S2\0\
  1215. X\0\033Y%+ %+ \0\
  1216. X\0\0"
  1217. X
  1218. X/*
  1219. X * The xterm termcap is missing F14 and F15, because they send the same
  1220. X * codes as the undo and help key, although they don't work on all keyboards.
  1221. X */
  1222. X#  define XTERM_TCAP "xterm\0\
  1223. X\0\033[K\0\
  1224. X\0\033[L\0\
  1225. X\0\033[%p1%dL\0\
  1226. X\0\033[M\0\
  1227. X\0\033[%p1%dM\0\
  1228. X\0\033[H\033[2J\0\
  1229. X\2\033[m\0\
  1230. X\0\033[7m\0\
  1231. X\0\033[%i%p1%d;%p2%dH\0\
  1232. X\0\033M\0\
  1233. X\0\033[%p1%dC\0\
  1234. X\1\033[?1h\033=\0\
  1235. X\0\033[?1l\033>\0\
  1236. X\0\0337\033[?47h\0\
  1237. X\0\033[2J\033[?47l\0338\0\
  1238. X\0\033OA\0\
  1239. X\0\033OB\0\
  1240. X\0\033OD\0\
  1241. X\0\033OC\0\
  1242. X\0\033Ox\0\
  1243. X\0\033Or\0\
  1244. X\0\033Ot\0\
  1245. X\0\033Ov\0\
  1246. X\0\033[11~\0\
  1247. X\0\033[12~\0\
  1248. X\0\033[13~\0\
  1249. X\0\033[14~\0\
  1250. X\0\033[15~\0\
  1251. X\0\033[17~\0\
  1252. X\0\033[18~\0\
  1253. X\0\033[19~\0\
  1254. X\0\033[20~\0\
  1255. X\0\033[21~\0\
  1256. X\0\033[23~\0\
  1257. X\0\033[24~\0\
  1258. X\0\033[25~\0\
  1259. X\2\033[29~\0\
  1260. X\0\033[31~\0\
  1261. X\0\033[32~\0\
  1262. X\0\033[33~\0\
  1263. X\0\033[34~\0\
  1264. X\0\033[28~\0\
  1265. X\0\033[26~\0\
  1266. X\0\0"
  1267. X
  1268. X#  define DEBUG_TCAP "debug\0\
  1269. X\0[EL]\0\
  1270. X\0[IL]\0\
  1271. X\0[CIL%p1%d]\0\
  1272. X\0[DL]\0\
  1273. X\0[CDL%p1%d]\0\
  1274. X\0[ED]\0\
  1275. X\0[CI]\0\
  1276. X\0[CV]\0\
  1277. X\0[TP]\0\
  1278. X\0[TI]\0\
  1279. X\0[%p1%dCM%p2%d]\0\
  1280. X\0[SR]\0\
  1281. X\0[CRI%p1%d]\0\
  1282. X\0[VB]\0\
  1283. X\0[KS]\0\
  1284. X\0[KE]\0\
  1285. X\0[TI]\0\
  1286. X\0[TE]\0\
  1287. X\0[KU]\0\
  1288. X\0[KD]\0\
  1289. X\0[KL]\0\
  1290. X\0[KR]\0\
  1291. X\0[SKU]\0\
  1292. X\0[SKD]\0\
  1293. X\0[SKL]\0\
  1294. X\0[SKR]\0\
  1295. X\0[F1]\0\
  1296. X\0[F2]\0\
  1297. X\0[F3]\0\
  1298. X\0[F4]\0\
  1299. X\0[F5]\0\
  1300. X\0[F6]\0\
  1301. X\0[F7]\0\
  1302. X\0[F8]\0\
  1303. X\0[F9]\0\
  1304. X\0[F10]\0\
  1305. X\0[SF1]\0\
  1306. X\0[SF2]\0\
  1307. X\0[SF3]\0\
  1308. X\0[SF4]\0\
  1309. X\0[SF5]\0\
  1310. X\0[SF6]\0\
  1311. X\0[SF7]\0\
  1312. X\0[SF8]\0\
  1313. X\0[SF9]\0\
  1314. X\0[SF10]\0\
  1315. X\0[HELP]\0\
  1316. X\0[UNDO]\0\
  1317. X\0\0"
  1318. X
  1319. X#  ifdef ATARI
  1320. X#   define DFLT_TCAP ATARI_TCAP
  1321. X#  endif /* ATARI */
  1322. X
  1323. X#  ifdef AMIGA
  1324. X#   define DFLT_TCAP AMIGA_TCAP
  1325. X#  endif /* AMIGA */
  1326. X
  1327. X#  ifdef MSDOS
  1328. X#   define DFLT_TCAP PCTERM_TCAP
  1329. X#  endif /* MSDOS */
  1330. X
  1331. X#  ifdef UNIX
  1332. X#   define DFLT_TCAP ANSI_TCAP
  1333. X#  endif /* UNIX */
  1334. X
  1335. X# else /* NO_BUILTIN_TCAPS */
  1336. X/*
  1337. X * The most minimal terminal: only clear screen and cursor positioning
  1338. X */
  1339. X#  define DUMB_TCAP "dumb\0\
  1340. X\5\014\0\
  1341. X\4\033[%i%p1%d;%p2%dH\0\
  1342. X\0\0"
  1343. X# endif /* NO_BUILTIN_TCAPS */
  1344. X
  1345. X#endif
  1346. END_OF_FILE
  1347. if test 13223 -ne `wc -c <'vim/src/term.h'`; then
  1348.     echo shar: \"'vim/src/term.h'\" unpacked with wrong size!
  1349. fi
  1350. chmod +x 'vim/src/term.h'
  1351. # end of 'vim/src/term.h'
  1352. fi
  1353. if test -f 'vim/src/termlib.c' -a "${1}" != "-c" ; then 
  1354.   echo shar: Will not clobber existing file \"'vim/src/termlib.c'\"
  1355. else
  1356. echo shar: Extracting \"'vim/src/termlib.c'\" \(15527 characters\)
  1357. sed "s/^X//" >'vim/src/termlib.c' <<'END_OF_FILE'
  1358. X/* vi:sw=4:ts=4:
  1359. X   The following software is (C) 1984 Peter da Silva,
  1360. X   the Mad Australian, in the public domain. It may
  1361. X   be re-distributed for any purpose with the inclusion
  1362. X   of this notice. */
  1363. X/* modified by Bram Moolenaar */
  1364. X
  1365. X/* TERMLIB: Terminal independant database. */
  1366. X
  1367. X#include "vim.h"
  1368. X#include "proto.h"
  1369. X#include "proto/termlib.pro"
  1370. X
  1371. X#ifndef AMIGA
  1372. X# include <sgtty.h>
  1373. X#endif
  1374. X
  1375. Xstatic int    getent __PARMS((char *, char *, FILE *, int));
  1376. Xstatic int    nextent __PARMS((char *, FILE *, int));
  1377. Xstatic int    _match __PARMS((char *, char *));
  1378. Xstatic char    *_addfmt __PARMS((char *, char *, int));
  1379. Xstatic char    *_find __PARMS((char *, char *));
  1380. X
  1381. X/*
  1382. X * Global variables for termlib
  1383. X */
  1384. X
  1385. Xchar    *tent;                /* Pointer to terminal entry, set by tgetent */
  1386. Xchar    PC = 0;               /* Pad character, default NULL */
  1387. Xchar    *UP = 0, *BC = 0;     /* Pointers to UP and BC strings from database */
  1388. Xshort    ospeed;               /* Baud rate (1-16, 1=300, 16=19200), as in stty */
  1389. X
  1390. X/*
  1391. X * Module: tgetent
  1392. X *
  1393. X * Purpose: Get termcap entry for <term> into buffer at <tbuf>.
  1394. X *
  1395. X * Calling conventions: char tbuf[TBUFSZ+], term=canonical name for
  1396. X *            terminal.
  1397. X *
  1398. X * Returned values: 1 = success, -1 = can't open file,
  1399. X *            0 = can't find terminal.
  1400. X *
  1401. X * Notes
  1402. X *        Should probably supply static buffer.
  1403. X *
  1404. X *        Uses environment variables "TERM" and
  1405. X *    "TERMCAP". If TERM = term (that is, if the argument
  1406. X *    matches the environment) then it looks at TERMCAP.
  1407. X *        If TERMCAP begins with a slash, then it assumes
  1408. X *    this is the file to search rather than /etc/termcap.
  1409. X *        If TERMCAP does not begin with a slash, and it
  1410. X *    matches TERM, then this is used as the entry.
  1411. X *
  1412. X *        This could be simplified considerably for non-UNIX
  1413. X *    systems.
  1414. X */
  1415. X
  1416. X#ifdef AMIGA
  1417. X# define TERMCAPFILE "s:termcap"
  1418. X#else
  1419. X# define TERMCAPFILE "/etc/termcap"
  1420. X#endif
  1421. X
  1422. Xtgetent(tbuf, term)
  1423. X    char    *tbuf;               /* Buffer to hold termcap entry, TBUFSZ bytes max */
  1424. X    char    *term;               /* Name of terminal */
  1425. X{
  1426. X    char    tcbuf[32];           /* Temp buffer to handle */
  1427. X    char    *tcptr = tcbuf;      /* extended entries */
  1428. X    char    *tcap = TERMCAPFILE; /* Default termcap file */
  1429. X    char    *tmp;
  1430. X    FILE    *termcap;
  1431. X    int        retval = 0;
  1432. X    int        len;
  1433. X
  1434. X    if ((tmp = (char *)vimgetenv("TERMCAP")) != NULL)
  1435. X    {
  1436. X        if (*tmp == '/')            /* TERMCAP = name of termcap file */
  1437. X            tcap = tmp ;
  1438. X        else                        /* TERMCAP = termcap entry itself */
  1439. X        {
  1440. X            int tlen = strlen(term);
  1441. X
  1442. X            while (*tmp && *tmp != ':') /* Check if TERM matches */
  1443. X            {
  1444. X                while (*tmp == '|')
  1445. X                    tmp++;
  1446. X                if (_match(tmp, term) == tlen)
  1447. X                {
  1448. X                    strcpy(tbuf, tmp);
  1449. X                    tent = tbuf;
  1450. X                    return 1;
  1451. X                } 
  1452. X                else
  1453. X                    tmp = _find(tmp, ":|");
  1454. X            }
  1455. X        }
  1456. X    }
  1457. X    if (!(termcap = fopen(tcap, "r")))
  1458. X    {
  1459. X        strcpy(tbuf, tcap);
  1460. X        return -1;
  1461. X    }
  1462. X
  1463. X    len = 0;
  1464. X    while (getent(tbuf + len, term, termcap, TBUFSZ - len))
  1465. X    {
  1466. X        if ((term = tgetstr("tc", &tcptr)))         /* extended entry */
  1467. X        {
  1468. X            rewind(termcap);
  1469. X            len = strlen(tbuf);
  1470. X        }
  1471. X        else
  1472. X        {
  1473. X            retval = 1; 
  1474. X            tent = tbuf;
  1475. X            break;
  1476. X        }
  1477. X    }
  1478. X    fclose(termcap);
  1479. X    return retval;
  1480. X}
  1481. X
  1482. X    static int
  1483. Xgetent(tbuf, term, termcap, buflen)
  1484. X    char    *tbuf, *term;
  1485. X    FILE    *termcap;
  1486. X    int        buflen;
  1487. X{
  1488. X    char    *tptr;
  1489. X    int        tlen = strlen(term);
  1490. X
  1491. X    while (nextent(tbuf, termcap, buflen))   /* For each possible entry */
  1492. X    {
  1493. X        tptr = tbuf;
  1494. X        while (*tptr && *tptr != ':')    /* : terminates name field */
  1495. X        {
  1496. X            while (*tptr == '|')             /* | seperates names */
  1497. X                tptr++;
  1498. X            if (_match(tptr, term) == tlen)             /* FOUND! */
  1499. X            {
  1500. X                tent = tbuf;
  1501. X                return 1;
  1502. X            } 
  1503. X            else                           /* Look for next name */
  1504. X                tptr = _find(tptr, ":|");
  1505. X        }
  1506. X    }
  1507. X    return 0;
  1508. X}
  1509. X
  1510. X    static int
  1511. Xnextent(tbuf, termcap, buflen)         /* Read 1 entry from TERMCAP file */
  1512. X    char    *tbuf;
  1513. X    FILE    *termcap;
  1514. X    int        buflen;
  1515. X{
  1516. X    char *lbuf = tbuf;           /* lbuf=line buffer */
  1517. X                                 /* read lines straight into buffer */
  1518. X
  1519. X    while (lbuf < tbuf+buflen &&                        /* There's room and */
  1520. X          fgets(lbuf, (int)(tbuf+buflen-lbuf), termcap))        /* another line */
  1521. X    {
  1522. X        int llen = strlen(lbuf);
  1523. X
  1524. X        if (*lbuf == '#')                               /* eat comments */
  1525. X            continue;
  1526. X        if (lbuf[-1] == ':' &&                        /* and whitespace */
  1527. X            lbuf[0] == '\t' &&
  1528. X            lbuf[1] == ':')
  1529. X        {
  1530. X            strcpy(lbuf, lbuf+2);
  1531. X            llen -= 2;
  1532. X        }
  1533. X        if (lbuf[llen-2] == '\\')                  /* and continuations */
  1534. X            lbuf += llen-2;
  1535. X        else
  1536. X        {
  1537. X            lbuf[llen-1]=0;           /* no continuation, return */
  1538. X            return 1;
  1539. X        }
  1540. X    }
  1541. X
  1542. X    return 0;                                    /* ran into end of file */
  1543. X}
  1544. X
  1545. X/*
  1546. X * Module: tgetflag
  1547. X *
  1548. X * Purpose: returns flag true or false as to the existence of a given
  1549. X *        entry. used with 'bs', 'am', etc...
  1550. X *
  1551. X * Calling conventions: id is the 2 character capability id.
  1552. X *
  1553. X * Returned values: 1 for success, 0 for failure.
  1554. X */
  1555. X
  1556. Xtgetflag(id)
  1557. X    char *id;
  1558. X{
  1559. X    char    buf[256], *ptr = buf;
  1560. X
  1561. X    return tgetstr(id, &ptr) ? 1 : 0;
  1562. X}
  1563. X
  1564. X/*
  1565. X * Module: tgetnum
  1566. X *
  1567. X * Purpose: get numeric value such as 'li' or 'co' from termcap.
  1568. X *
  1569. X * Calling conventions: id = 2 character id.
  1570. X *
  1571. X * Returned values: -1 for failure, else numerical value.
  1572. X */
  1573. X
  1574. Xtgetnum(id)
  1575. Xchar *id;
  1576. X{
  1577. X    char *ptr, buf[256];
  1578. X    ptr = buf;
  1579. X
  1580. X    if (tgetstr(id, &ptr))
  1581. X        return atoi(buf);
  1582. X    else
  1583. X        return 0;
  1584. X}
  1585. X
  1586. X/*
  1587. X * Module: tgetstr
  1588. X *
  1589. X * Purpose: get terminal capability string from database.
  1590. X *
  1591. X * Calling conventions: id is the two character capability id.
  1592. X *            (*buf) points into a hold buffer for the
  1593. X *            id. the capability is copied into the buffer
  1594. X *            and (*buf) is advanced to point to the next
  1595. X *            free byte in the buffer.
  1596. X *
  1597. X * Returned values: 0 = no such entry, otherwise returns original
  1598. X *            (*buf) (now a pointer to the string).
  1599. X *
  1600. X * Notes
  1601. X *        It also decodes certain escape sequences in the buffer.
  1602. X *    they should be obvious from the code:
  1603. X *        \E = escape.
  1604. X *        \n, \r, \t, \f, \b match the 'c' escapes.
  1605. X *        ^x matches control-x (^@...^_).
  1606. X *        \nnn matches nnn octal.
  1607. X *        \x, where x is anything else, matches x. I differ
  1608. X *    from the standard library here, in that I allow ^: to match
  1609. X *    :.
  1610. X *
  1611. X */
  1612. X
  1613. Xchar *
  1614. Xtgetstr(id, buf)
  1615. Xchar    *id, **buf;
  1616. X{
  1617. X    int    len = strlen(id);
  1618. X    char *tmp=tent;
  1619. X    char *hold;
  1620. X    int        i;
  1621. X
  1622. X    do {
  1623. X        tmp = _find(tmp, ":");                     /* For each field */
  1624. X        while (*tmp == ':')                        /* skip empty fields */
  1625. X            tmp++;
  1626. X        if (!*tmp)
  1627. X            break;
  1628. X
  1629. X        if (_match(id, tmp) == len) {
  1630. X            tmp += len;                   /* find '=' '@' or '#' */
  1631. X            if (*tmp == '@')                  /* :xx@: entry for tc */
  1632. X                return 0;                   /* deleted entry */
  1633. X            hold= *buf;
  1634. X            while (*++tmp && *tmp != ':') {/* not at end of field */
  1635. X                switch(*tmp) {
  1636. X                case '\\':            /* Expand escapes here */
  1637. X                    switch(*++tmp) {
  1638. X                    case 0:        /* ignore backslashes */
  1639. X                        tmp--;    /* at end of entry */
  1640. X                        break;   /* shouldn't happen */
  1641. X                    case 'e':
  1642. X                    case 'E':                     /* ESC */
  1643. X                        *(*buf)++ = '\033'; 
  1644. X                        break;
  1645. X                    case 'n':                      /* \n */
  1646. X                        *(*buf)++ = '\n'; 
  1647. X                        break;
  1648. X                    case 'r':                      /* \r */
  1649. X                        *(*buf)++ = '\r'; 
  1650. X                        break;
  1651. X                    case 't':                      /* \t */
  1652. X                        *(*buf)++ = '\t'; 
  1653. X                        break;
  1654. X                    case 'b':                      /* \b */
  1655. X                        *(*buf)++ = '\b'; 
  1656. X                        break;
  1657. X                    case 'f':                      /* \f */
  1658. X                        *(*buf)++ = '\f'; 
  1659. X                        break;
  1660. X                    case '0':                    /* \nnn */
  1661. X                    case '1': 
  1662. X                    case '2': 
  1663. X                    case '3': 
  1664. X                    case '4':
  1665. X                    case '5': 
  1666. X                    case '6': 
  1667. X                    case '7': 
  1668. X                    case '8': 
  1669. X                    case '9':
  1670. X                        **buf = 0;
  1671. X                            /* get up to three digits */
  1672. X                        for (i = 0; i < 3 && isdigit(*tmp); ++i)
  1673. X                            **buf = **buf * 8 + *tmp++ - '0';
  1674. X                        (*buf)++;
  1675. X                        tmp--;
  1676. X                        break;
  1677. X                    default:      /* \x, for all other x */
  1678. X                        *(*buf)++= *tmp;
  1679. X                    }
  1680. X                    break;
  1681. X                case '^':              /* control characters */
  1682. X                    *(*buf)++ = *++tmp - '@'; 
  1683. X                    break;
  1684. X                default: 
  1685. X                    *(*buf)++ = *tmp;
  1686. X                }
  1687. X            }
  1688. X            *(*buf)++ = 0;
  1689. X            return hold;
  1690. X        }
  1691. X    } while (*tmp);
  1692. X
  1693. X    return 0;
  1694. X}
  1695. X
  1696. X/*
  1697. X * Module: tgoto
  1698. X *
  1699. X * Purpose: decode cm cursor motion string.
  1700. X *
  1701. X * Calling conventions: cm is cursor motion string.
  1702. X *            line, col, are the desired destination.
  1703. X *
  1704. X * Returned values: a string pointing to the decoded string, or
  1705. X *            "OOPS" if it cannot be decoded.
  1706. X *
  1707. X * Notes
  1708. X *        The accepted escapes are:
  1709. X *            %d     as in printf, 0 origin.
  1710. X *            %2, %3     like %02d, %03d in printf.
  1711. X *            %.     like %c
  1712. X *            %+x     adds <x> to value, then %.
  1713. X *            %>xy     if value>x, adds y. No output.
  1714. X *            %i     increments line& col, no output.
  1715. X *            %r     reverses order of line&col. No output.
  1716. X *            %%     prints as a single %.
  1717. X *            %n     exclusive or row & col with 0140.
  1718. X *            %B     BCD, no output.
  1719. X *            %D     reverse coding (x-2*(x%16)), no output.
  1720. X */
  1721. X
  1722. Xchar *
  1723. Xtgoto(cm, col, line)
  1724. Xchar    *cm;                                      /* cm string, from termcap */
  1725. Xint    col,                                           /* column, x position */
  1726. X    line;                                            /* line, y position */
  1727. X{
  1728. X    char    gx, gy,                                           /*    x, y */
  1729. X        *ptr,                                     /* pointer in 'cm' */
  1730. X        reverse = 0,                                 /* reverse flag */
  1731. X        *bufp,                         /* pointer in returned string */
  1732. X        addup = 0,                                     /* add upline */
  1733. X        addbak = 0,                                    /* add backup */
  1734. X        c;
  1735. X    static char buffer[32];
  1736. X
  1737. X    if (!cm)
  1738. X        return "OOPS";                       /* Kludge, but standard */
  1739. X
  1740. X    bufp = buffer;
  1741. X    ptr = cm;
  1742. X
  1743. X    while (*ptr) {
  1744. X        if ((c = *ptr++) != '%') {                     /* normal char */
  1745. X            *bufp++ = c;
  1746. X        } else {                                         /* % escape */
  1747. X            switch(c = *ptr++) {
  1748. X            case 'd':                                 /* decimal */
  1749. X                bufp = _addfmt(bufp, "%d", line);
  1750. X                line = col;
  1751. X                break;
  1752. X            case '2':                         /* 2 digit decimal */
  1753. X                bufp = _addfmt(bufp, "%02d", line);
  1754. X                line = col;
  1755. X                break;
  1756. X            case '3':                         /* 3 digit decimal */
  1757. X                bufp = _addfmt(bufp, "%03d", line);
  1758. X                line = col;
  1759. X                break;
  1760. X            case '>':                      /* %>xy: if >x, add y */
  1761. X                gx = *ptr++;
  1762. X                gy = *ptr++;
  1763. X                if (col>gx) col += gy;
  1764. X                if (line>gx) line += gy;
  1765. X                break;
  1766. X            case '+':                              /* %+c: add c */
  1767. X                line += *ptr++;
  1768. X            case '.':                               /* print x/y */
  1769. X                if (line == '\t' ||                /* these are */
  1770. X                   line == '\n' ||             /* chars that */
  1771. X                   line == '\004' ||             /* UNIX hates */
  1772. X                   line == '\0') {
  1773. X                    line++;         /* so go to next pos */
  1774. X                    if (reverse == (line == col))
  1775. X                        addup=1;      /* and mark UP */
  1776. X                    else
  1777. X                        addbak=1;           /* or BC */
  1778. X                }
  1779. X                *bufp++=line;
  1780. X                line = col;
  1781. X                break;
  1782. X            case 'r':                              /* r: reverse */
  1783. X                gx = line; 
  1784. X                line = col; 
  1785. X                col = gx;
  1786. X                reverse = 1;
  1787. X                break;
  1788. X            case 'i':             /* increment (1-origin screen) */
  1789. X                col++;
  1790. X                line++;
  1791. X                break;
  1792. X            case '%':                          /* %%=% literally */
  1793. X                *bufp++='%';
  1794. X                break;
  1795. X            case 'n':                       /* magic DM2500 code */
  1796. X                line ^= 0140;
  1797. X                col ^= 0140;
  1798. X                break;
  1799. X            case 'B':                            /* bcd encoding */
  1800. X                line = line/10<<4+line%10;
  1801. X                col = col/10<<4+col%10;
  1802. X                break;
  1803. X            case 'D':                   /* magic Delta Data code */
  1804. X                line = line-2*(line&15);
  1805. X                col = col-2*(col&15);
  1806. X                break;
  1807. X            default:                           /* Unknown escape */
  1808. X                return "OOPS";
  1809. X            }
  1810. X        }
  1811. X    }
  1812. X
  1813. X    if (addup)                                              /* add upline */
  1814. X        if (UP) {
  1815. X            ptr=UP;
  1816. X            while (isdigit(*ptr) || *ptr == '.')
  1817. X                ptr++;
  1818. X            if (*ptr == '*')
  1819. X                ptr++;
  1820. X            while (*ptr)
  1821. X                *bufp++ = *ptr++;
  1822. X        }
  1823. X
  1824. X    if (addbak)                                          /* add backspace */
  1825. X        if (BC) {
  1826. X            ptr=BC;
  1827. X            while (isdigit(*ptr) || *ptr == '.')
  1828. X                ptr++;
  1829. X            if (*ptr == '*')
  1830. X                ptr++;
  1831. X            while (*ptr)
  1832. X                *bufp++ = *ptr++;
  1833. X        } 
  1834. X        else
  1835. X            *bufp++='\b';
  1836. X
  1837. X    *bufp = 0;
  1838. X
  1839. X    return(buffer);
  1840. X}
  1841. X
  1842. X/*
  1843. X * Module: tinit
  1844. X *
  1845. X * Purpose: simplified terminal initialisation.
  1846. X *
  1847. X * Calling conventions: name is name of terminal.
  1848. X *
  1849. X * Returned values: none.
  1850. X *
  1851. X * Notes
  1852. X *        tinit calls tgetent, then sets up the global
  1853. X *    variables PC, UP, BC, ospeed appropriately.
  1854. X *
  1855. X */
  1856. X
  1857. X#if 0        /* already included in term.c */
  1858. X
  1859. Xchar tbuf[TBUFSZ];                                /* Buffer for termcap entry */
  1860. Xchar junkbuf[TBUFSZ];                                  /* Big buffer for junk */
  1861. Xchar *junkptr;
  1862. X
  1863. Xtinit(name)
  1864. Xchar *name;
  1865. X{
  1866. X#ifndef AMIGA
  1867. X    struct sgttyb sgbuf;
  1868. X#endif
  1869. X    char *ps;
  1870. X
  1871. X    junkptr = junkbuf;
  1872. X
  1873. X    tgetent(tbuf, name);
  1874. X
  1875. X    ps = tgetstr("pc", &junkptr);
  1876. X    if (ps) PC = *ps;
  1877. X    UP = tgetstr("up", &junkptr);
  1878. X    BC = tgetstr("bc", &junkptr);
  1879. X
  1880. X#ifdef AMIGA
  1881. X    ospeed=0;
  1882. X#else
  1883. X    gtty(1, &sgbuf);
  1884. X    ospeed=sgbuf.sg_ospeed;
  1885. X#endif
  1886. X    return 0;
  1887. X}
  1888. X#endif
  1889. X
  1890. X/*
  1891. X * Module: tputs
  1892. X *
  1893. X * Purpose: decode padding information
  1894. X *
  1895. X * Calling conventions: cp = string to be padded, affcnt = # of items
  1896. X *            affected (lines, characters, whatever),
  1897. X *            outc = routine to output 1 character.
  1898. X *
  1899. X * Returned values: none
  1900. X *
  1901. X * Notes
  1902. X *        cp has padding information ahead of it, in the form
  1903. X *    nnnTEXT or nnn*TEXT. nnn is the number of milliseconds to delay,
  1904. X *    and may be a decimal (nnn.mmm). If the asterisk is given, then
  1905. X *    the delay is multiplied by afcnt. The delay is produced by outputting
  1906. X *    a number of nulls (or other padding char) after printing the
  1907. X *    TEXT.
  1908. X *
  1909. X */
  1910. X
  1911. Xlong _bauds[16]={
  1912. X    0,    50,    75,    110,
  1913. X    134,    150,    200,    300,
  1914. X    600,    1200,    1800,    2400,
  1915. X    4800,    9600,    19200,    19200 };
  1916. X
  1917. Xtputs(cp, affcnt, outc)
  1918. Xchar *cp;                                                 /* string to print */
  1919. Xint affcnt;                                      /* Number of lines affected */
  1920. Xvoid (*outc) __ARGS((unsigned int));                              /* routine to output 1 character */
  1921. X{
  1922. X    long    frac,                    /* 10^(#digits after decimal point) */
  1923. X        counter,                                           /* digits */
  1924. X        atol();
  1925. X
  1926. X    if (isdigit(*cp)) {
  1927. X        counter = 0;
  1928. X        frac = 1000;
  1929. X        while (isdigit(*cp))
  1930. X            counter = counter * 10L + (long)(*cp++ - '0');
  1931. X        if (*cp == '.')
  1932. X            while (isdigit(*++cp)) {
  1933. X                counter = counter * 10L + (long)(*cp++ - '0');
  1934. X                frac = frac * 10;
  1935. X            }
  1936. X        if (*cp!='*') {                 /* multiply by affected lines */
  1937. X            if (affcnt>1) affcnt = 1;
  1938. X        } 
  1939. X        else
  1940. X            cp++;
  1941. X
  1942. X        /* Calculate number of characters for padding counter/frac ms delay */
  1943. X        if (ospeed)
  1944. X            counter = (counter * _bauds[ospeed] * (long)affcnt) / frac;
  1945. X
  1946. X        while (*cp)                                  /* output string */
  1947. X            (*outc)(*cp++);
  1948. X        if (ospeed)
  1949. X            while (counter--)            /* followed by pad characters */
  1950. X                (*outc)(PC);
  1951. X    } 
  1952. X    else
  1953. X        while (*cp)
  1954. X            (*outc)(*cp++);
  1955. X    return 0;
  1956. X}
  1957. X
  1958. X/*
  1959. X * Module: tutil.c
  1960. X *
  1961. X * Purpose: Utility routines for TERMLIB functions.
  1962. X *
  1963. X */
  1964. X
  1965. X    static int
  1966. X_match(s1, s2)                 /* returns length of text common to s1 and s2 */
  1967. Xchar *s1, *s2;
  1968. X{
  1969. X    int i = 0;
  1970. X
  1971. X    while (s1[i] && s1[i] == s2[i])
  1972. X        i++;
  1973. X
  1974. X    return i;
  1975. X}
  1976. X
  1977. X    static char *
  1978. X_find(s, set)   /* finds next c in s that's a member of set, returns pointer */
  1979. Xchar *s, *set;
  1980. X{
  1981. X    for(; *s; s++) {
  1982. X        char    *ptr = set;
  1983. X
  1984. X        while (*ptr && *s != *ptr)
  1985. X            ptr++;
  1986. X
  1987. X        if (*ptr)
  1988. X            return s;
  1989. X    }
  1990. X
  1991. X    return s;
  1992. X}
  1993. X
  1994. X    static char *
  1995. X_addfmt(buf, fmt, val)             /* add val to buf according to format fmt */
  1996. Xchar *buf, *fmt;
  1997. Xint val;
  1998. X{
  1999. X    sprintf(buf, fmt, val);
  2000. X    while (*buf)
  2001. X        buf++;
  2002. X    return buf;
  2003. X}
  2004. END_OF_FILE
  2005. if test 15527 -ne `wc -c <'vim/src/termlib.c'`; then
  2006.     echo shar: \"'vim/src/termlib.c'\" unpacked with wrong size!
  2007. fi
  2008. chmod +x 'vim/src/termlib.c'
  2009. # end of 'vim/src/termlib.c'
  2010. fi
  2011. if test -f 'vim/src/undo.c' -a "${1}" != "-c" ; then 
  2012.   echo shar: Will not clobber existing file \"'vim/src/undo.c'\"
  2013. else
  2014. echo shar: Extracting \"'vim/src/undo.c'\" \(14257 characters\)
  2015. sed "s/^X//" >'vim/src/undo.c' <<'END_OF_FILE'
  2016. X/* vi:ts=4:sw=4
  2017. X *
  2018. X * VIM - Vi IMproved
  2019. X *
  2020. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  2021. X *                            Tim Thompson            twitch!tjt
  2022. X *                            Tony Andrews            onecom!wldrdg!tony 
  2023. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  2024. X */
  2025. X
  2026. X/*
  2027. X * undo.c: multi level undo facility
  2028. X *
  2029. X * The saved lines are stored in a list of lists:
  2030. X *
  2031. X * u_oldhead----------------------------------------------+
  2032. X *                                                        |
  2033. X *                                                        V
  2034. X *              +--------------+    +--------------+    +--------------+
  2035. X * u_newhead--->| u_header     |    | u_header     |    | u_header     |
  2036. X *              |     uh_next------>|     uh_next------>|     uh_next---->NULL
  2037. X *       NULL<--------uh_prev  |<---------uh_prev  |<---------uh_prev  |
  2038. X *              |     uh_entry |    |     uh_entry |    |     uh_entry |
  2039. X *              +--------|-----+    +--------|-----+    +--------|-----+
  2040. X *                       |                   |                   |
  2041. X *                       V                   V                   V
  2042. X *              +--------------+    +--------------+    +--------------+
  2043. X *              | u_entry      |    | u_entry      |    | u_entry      |
  2044. X *              |     ue_next  |    |     ue_next  |    |     ue_next  |
  2045. X *              +--------|-----+    +--------|-----+    +--------|-----+
  2046. X *                       |                   |                   |
  2047. X *                       V                   V                   V
  2048. X *              +--------------+            NULL                NULL
  2049. X *              | u_entry      |
  2050. X *              |     ue_next  |
  2051. X *              +--------|-----+
  2052. X *                       |
  2053. X *                       V
  2054. X *                      etc.
  2055. X *
  2056. X * Each u_entry list contains the information for one undo or redo.
  2057. X * u_curhead points to the header of the last undo (the next redo), or is
  2058. X * NULL if nothing has been undone.
  2059. X *
  2060. X * All data is allocated with alloc_line(), thus it will be freed as soon as
  2061. X * we switch files!
  2062. X */
  2063. X
  2064. X#include "vim.h"
  2065. X#include "globals.h"
  2066. X#include "proto.h"
  2067. X#include "param.h"
  2068. X#include "ops.h"        /* for endop and startop */
  2069. X
  2070. Xstruct u_entry
  2071. X{
  2072. X    struct u_entry    *ue_next;    /* pointer to next entry in list */
  2073. X    linenr_t        ue_top;        /* number of line above undo block */
  2074. X    linenr_t        ue_bot;        /* number of line below undo block */
  2075. X    char            *ue_botptr;    /* pointer to line below undo block */
  2076. X    char            **ue_array;    /* array of lines in undo block */
  2077. X    long            ue_size;    /* number of lines in ue_array */
  2078. X};
  2079. X
  2080. Xstruct u_header
  2081. X{
  2082. X    struct u_header    *uh_next;    /* pointer to next header in list */
  2083. X    struct u_header    *uh_prev;    /* pointer to previous header in list */
  2084. X    struct u_entry    *uh_entry;    /* pointer to first entry */
  2085. X    FPOS             uh_curpos;    /* cursor position before saving */
  2086. X};
  2087. X
  2088. Xstatic struct u_header *u_oldhead = NULL;    /* pointer to oldest header */
  2089. Xstatic struct u_header *u_newhead = NULL;    /* pointer to newest header */
  2090. Xstatic struct u_header *u_curhead = NULL;    /* pointer to current header */
  2091. Xstatic int                u_numhead = 0;        /* current number of headers */
  2092. Xstatic int                u_synced = TRUE;    /* entry lists are synced */
  2093. X
  2094. X/*
  2095. X * variables for "U" command
  2096. X */
  2097. Xstatic char       *u_line_ptr = NULL;        /* saved line for "U" command */
  2098. Xstatic linenr_t u_line_lnum;            /* line number of line in u_line */
  2099. Xstatic colnr_t    u_line_colnr;            /* optional column number */
  2100. X
  2101. Xstatic void u_getbot __ARGS((void));
  2102. Xstatic int u_savecommon __ARGS((linenr_t, linenr_t, int, linenr_t));
  2103. Xstatic void u_undoredo __ARGS((void));
  2104. Xstatic void u_freelist __ARGS((struct u_header *));
  2105. Xstatic void u_freeentry __ARGS((struct u_entry *, long));
  2106. X
  2107. X/*
  2108. X * save the current line for both the "u" and "U" command
  2109. X */
  2110. X    int
  2111. Xu_saveCurpos()
  2112. X{
  2113. X    return (u_save((linenr_t)(Curpos.lnum - 1), (linenr_t)(Curpos.lnum + 1)));
  2114. X}
  2115. X
  2116. X/*
  2117. X * Save the lines between "top" and "bot" for both the "u" and "U" command.
  2118. X * "top" may be 0 and bot may be line_count + 1.
  2119. X * Returns FALSE when lines could not be saved.
  2120. X */
  2121. X    int
  2122. Xu_save(top, bot)
  2123. X    linenr_t top, bot;
  2124. X{
  2125. X    if (top > line_count || top >= bot || bot > line_count + 1)
  2126. X        return FALSE;    /* rely on caller to do error messages */
  2127. X
  2128. X    if (top + 2 == bot)
  2129. X        u_saveline((linenr_t)(top + 1));
  2130. X
  2131. X    return (u_savecommon(top, bot, FALSE, (linenr_t)0));
  2132. X}
  2133. X
  2134. X/*
  2135. X * save the line "lnum" (used by :s command)
  2136. X * the line is handed over to the undo routines
  2137. X * The line is replaced, so the new bottom line is lnum + 1.
  2138. X */
  2139. X    int
  2140. Xu_savesub(lnum)
  2141. X    linenr_t    lnum;
  2142. X{
  2143. X    return (u_savecommon(lnum - 1, lnum + 1, TRUE, lnum + 1));
  2144. X}
  2145. X
  2146. X/*
  2147. X * a new line is inserted before line "lnum" (used by :s command)
  2148. X * The line is inserted, so the new bottom line is lnum + 1.
  2149. X */
  2150. X     int
  2151. Xu_inssub(lnum)
  2152. X    linenr_t    lnum;
  2153. X{
  2154. X    return (u_savecommon(lnum - 1, lnum, TRUE, lnum + 1));
  2155. X}
  2156. X
  2157. X/*
  2158. X * save the lines "lnum" - "lnum" + nlines (used by delete command)
  2159. X * the lines are handed over to the undo routines
  2160. X * The lines are deleted, so the new bottom line is lnum.
  2161. X */
  2162. X    int
  2163. Xu_savedel(lnum, nlines)
  2164. X    linenr_t    lnum;
  2165. X    long        nlines;
  2166. X{
  2167. X    return (u_savecommon(lnum - 1, lnum + nlines, TRUE, lnum));
  2168. X}
  2169. X
  2170. X    static int 
  2171. Xu_savecommon(top, bot, nocopy, newbot)
  2172. X    linenr_t top, bot;
  2173. X    int nocopy;
  2174. X    linenr_t newbot;
  2175. X{
  2176. X    linenr_t        lnum;
  2177. X    long            i;
  2178. X    struct u_header *uhp;
  2179. X    struct u_entry    *uep;
  2180. X    long            size;
  2181. X
  2182. X    /*
  2183. X     * if u_synced == TRUE make a new header
  2184. X     */
  2185. X    if (u_synced)
  2186. X    {
  2187. X        /*
  2188. X         * if we undid more than we redid, free the entry lists before and
  2189. X         * including u_curhead
  2190. X         */
  2191. X        while (u_curhead != NULL)
  2192. X            u_freelist(u_newhead);
  2193. X
  2194. X        /*
  2195. X         * free headers to keep the size right
  2196. X         */
  2197. X        while (u_numhead > p_ul && u_oldhead != NULL)
  2198. X            u_freelist(u_oldhead);
  2199. X
  2200. X        if (p_ul < 0)            /* no undo at all */
  2201. X            goto noundo;
  2202. X
  2203. X        /*
  2204. X         * make a new header entry
  2205. X         */
  2206. X        uhp = (struct u_header *)alloc_line((unsigned)sizeof(struct u_header));
  2207. X        if (uhp == NULL)
  2208. X            goto nomem;
  2209. X        uhp->uh_prev = NULL;
  2210. X        uhp->uh_next = u_newhead;
  2211. X        if (u_newhead != NULL)
  2212. X            u_newhead->uh_prev = uhp;
  2213. X        uhp->uh_entry = NULL;
  2214. X        uhp->uh_curpos = Curpos;    /* save cursor position for undo */
  2215. X        u_newhead = uhp;
  2216. X        if (u_oldhead == NULL)
  2217. X            u_oldhead = uhp;
  2218. X        ++u_numhead;
  2219. X    }
  2220. X    else    /* find line number for ue_botptr for previous u_save() */
  2221. X        u_getbot();
  2222. X
  2223. X    size = bot - top - 1;
  2224. X#ifndef UNIX
  2225. X        /*
  2226. X         * With Amiga and MSDOS we can't handle big undo's, because then
  2227. X         * alloc_line would have to allocate a block larger than 32K
  2228. X         */
  2229. X    if (size >= 8000)
  2230. X        goto nomem;
  2231. X#endif
  2232. X
  2233. X    /*
  2234. X     * add lines in front of entry list
  2235. X     */
  2236. X    uep = (struct u_entry *)alloc_line((unsigned)sizeof(struct u_entry));
  2237. X    if (uep == NULL)
  2238. X        goto nomem;
  2239. X
  2240. X    uep->ue_size = size;
  2241. X    uep->ue_top = top;
  2242. X    uep->ue_botptr = NULL;
  2243. X    if (newbot)
  2244. X        uep->ue_bot = newbot;
  2245. X        /*
  2246. X         * use 0 for ue_bot if bot is below last line or if the buffer is empty, in
  2247. X         * which case the last line may be replaced (e.g. with 'O' command).
  2248. X         */
  2249. X    else if (bot > line_count || bufempty())
  2250. X        uep->ue_bot = 0;
  2251. X    else
  2252. X        uep->ue_botptr = nr2ptr(bot);    /* we have to do ptr2nr(ue_botptr) later */
  2253. X
  2254. X    if (size)
  2255. X    {
  2256. X        if ((uep->ue_array = (char **)alloc_line((unsigned)(sizeof(char *) * size))) == NULL)
  2257. X        {
  2258. X            u_freeentry(uep, 0L);
  2259. X            goto nomem;
  2260. X        }
  2261. X        for (i = 0, lnum = top + 1; i < size; ++i)
  2262. X        {
  2263. X            if (nocopy)
  2264. X                uep->ue_array[i] = nr2ptr(lnum++);
  2265. X            else if ((uep->ue_array[i] = save_line(nr2ptr(lnum++))) == NULL)
  2266. X            {
  2267. X                u_freeentry(uep, i);
  2268. X                goto nomem;
  2269. X            }
  2270. X        }
  2271. X    }
  2272. X    uep->ue_next = u_newhead->uh_entry;
  2273. X    u_newhead->uh_entry = uep;
  2274. X    u_synced = FALSE;
  2275. X    return TRUE;
  2276. X
  2277. Xnomem:
  2278. X    if (ask_yesno("no undo possible; continue anyway") == 'y')
  2279. X    {
  2280. Xnoundo:
  2281. X        if (nocopy)
  2282. X            for (lnum = top + 1; lnum < bot; ++lnum)
  2283. X                free_line(nr2ptr(lnum));
  2284. X        return TRUE;
  2285. X    }
  2286. X    return FALSE;
  2287. X}
  2288. X
  2289. X    void
  2290. Xu_undo(count)
  2291. X    int count;
  2292. X{
  2293. X    /*
  2294. X     * If we get an undo command while executing a macro, we behave like the 
  2295. X     * original vi. If this happens twice in one macro the result will not
  2296. X     * be compatible.
  2297. X     */
  2298. X    if (u_synced == FALSE)
  2299. X    {
  2300. X        u_sync();
  2301. X        count = 1;
  2302. X    }
  2303. X
  2304. X    startop.lnum = 0;            /* unset '[ mark */
  2305. X    endop.lnum = 0;                /* unset '] mark */
  2306. X    while (count--)
  2307. X    {
  2308. X        if (u_curhead == NULL)                        /* first undo */
  2309. X            u_curhead = u_newhead;
  2310. X        else if (p_ul > 0)                            /* multi level undo */
  2311. X            u_curhead = u_curhead->uh_next;            /* get next undo */
  2312. X
  2313. X        if (u_numhead == 0 || u_curhead == NULL)    /* nothing to undo */
  2314. X        {
  2315. X            u_curhead = u_oldhead;                    /* stick u_curhead at end */
  2316. X            beep();
  2317. X            return;
  2318. X        }
  2319. X
  2320. X        u_undoredo();
  2321. X    }
  2322. X}
  2323. X
  2324. X    void
  2325. Xu_redo(count)
  2326. X    int count;
  2327. X{
  2328. X    while (count--)
  2329. X    {
  2330. X        if (u_curhead == NULL || p_ul <= 0)        /* nothing to redo */
  2331. X        {
  2332. X            beep();
  2333. X            return;
  2334. X        }
  2335. X
  2336. X        u_undoredo();
  2337. X
  2338. X        u_curhead = u_curhead->uh_prev;            /* advance for next redo */
  2339. X    }
  2340. X}
  2341. X
  2342. X/*
  2343. X * u_undoredo: common code for undo and redo
  2344. X *
  2345. X * The lines in the file are replaced by the lines in the entry list at u_curhead.
  2346. X * The replaced lines in the file are saved in the entry list for the next undo/redo.
  2347. X */
  2348. X    static void
  2349. Xu_undoredo()
  2350. X{
  2351. X    char        **newarray = NULL;
  2352. X    linenr_t    oldsize;
  2353. X    linenr_t    newsize;
  2354. X    linenr_t    top, bot;
  2355. X    linenr_t    lnum;
  2356. X    linenr_t    newlnum = INVLNUM;
  2357. X    long        i;
  2358. X    long        newcount = 0, oldcount = 0;
  2359. X    struct u_entry *uep, *nuep;
  2360. X    struct u_entry *newlist = NULL;
  2361. X
  2362. X    CHANGED;
  2363. X    for (uep = u_curhead->uh_entry; uep != NULL; uep = nuep)
  2364. X    {
  2365. X        top = uep->ue_top;
  2366. X        bot = uep->ue_bot;
  2367. X        if (bot == 0)
  2368. X            bot = line_count + 1;
  2369. X        if (top > line_count || top >= bot || bot > line_count + 1)
  2370. X        {
  2371. X            emsg("u_undo: line numbers wrong");
  2372. X            return;
  2373. X        }
  2374. X
  2375. X        if (top < newlnum)
  2376. X        {
  2377. X            newlnum = top;
  2378. X            Curpos.lnum = top + 1;
  2379. X        }
  2380. X        oldsize = bot - top - 1;    /* number of lines before undo */
  2381. X
  2382. X        newsize = uep->ue_size;        /* number of lines after undo */
  2383. X
  2384. X        /* delete the lines between top and bot and save them in newarray */
  2385. X        if (oldsize)
  2386. X        {
  2387. X            if ((newarray = (char **)alloc_line((unsigned)(sizeof(char *) * oldsize))) == NULL)
  2388. X            {
  2389. X                /*
  2390. X                 * We have messed up the entry list, repair is impossible.
  2391. X                 * we have to free the rest of the list.
  2392. X                 */
  2393. X                while (uep != NULL)
  2394. X                {
  2395. X                    nuep = uep->ue_next;
  2396. X                    u_freeentry(uep, uep->ue_size);
  2397. X                    uep = nuep;
  2398. X                }
  2399. X                break;
  2400. X            }
  2401. X            /* delete backwards, it goes faster in some cases */
  2402. X            for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
  2403. X                newarray[i] = delsline(lnum, oldsize != newsize);
  2404. X        }
  2405. X
  2406. X        /* adjust the marks if the number of lines does not change */
  2407. X        if (oldsize == newsize)
  2408. X            for (i = 0; i < oldsize; ++i)
  2409. X                adjustmark(newarray[i], uep->ue_array[i]);
  2410. X
  2411. X        /* insert the lines in u_array between top and bot */
  2412. X        if (newsize)
  2413. X        {
  2414. X            for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
  2415. X                appendline(lnum, uep->ue_array[i]);
  2416. X            free_line((char *)uep->ue_array);
  2417. X        }
  2418. X        newcount += newsize;
  2419. X        oldcount += oldsize;
  2420. X        uep->ue_size = oldsize;
  2421. X        uep->ue_array = newarray;
  2422. X        uep->ue_bot = top + newsize + 1;
  2423. X
  2424. X        /*
  2425. X         * insert this entry in front of the new entry list
  2426. X         */
  2427. X        nuep = uep->ue_next;
  2428. X        uep->ue_next = newlist;
  2429. X        newlist = uep;
  2430. X    }
  2431. X
  2432. X    u_curhead->uh_entry = newlist;
  2433. X
  2434. X    /*
  2435. X     * If we deleted or added lines, report the number of less/more lines.
  2436. X     * Otherwise, report the number of changes (this may be incorrect
  2437. X     * in some cases, but it's better than nothing).
  2438. X     */
  2439. X    if ((oldcount -= newcount) != 0)
  2440. X        msgmore(-oldcount);
  2441. X    else if (newcount > p_report)
  2442. X        smsg("%ld change%s", newcount, plural(newcount));
  2443. X
  2444. X    if (u_curhead->uh_curpos.lnum == Curpos.lnum)
  2445. X        Curpos.col = u_curhead->uh_curpos.col;
  2446. X    else
  2447. X        Curpos.col = 0;
  2448. X    updateScreen(CURSUPD);
  2449. X}
  2450. X
  2451. X/*
  2452. X * u_sync: stop adding to the current entry list
  2453. X */
  2454. X    void
  2455. Xu_sync()
  2456. X{
  2457. X    if (u_synced)
  2458. X        return;                /* already synced */
  2459. X    u_getbot();                /* compute ue_bot of previous u_undo */
  2460. X    u_curhead = NULL;
  2461. X}
  2462. X
  2463. X/*
  2464. X * u_getbot(): compute the line number of the previous u_undo
  2465. X */
  2466. X    static void
  2467. Xu_getbot()
  2468. X{
  2469. X    register struct u_entry *uep;
  2470. X
  2471. X    if (u_newhead == NULL || (uep = u_newhead->uh_entry) == NULL)
  2472. X    {
  2473. X        emsg("undo list corrupt");
  2474. X        return;
  2475. X    }
  2476. X
  2477. X    if (uep->ue_botptr != NULL)
  2478. X        if ((uep->ue_bot = ptr2nr(uep->ue_botptr, uep->ue_top)) == 0)
  2479. X        {
  2480. X            emsg("undo line missing");
  2481. X            uep->ue_bot = uep->ue_top + 1;    /* guess what it is */
  2482. X        }
  2483. X
  2484. X    u_synced = TRUE;
  2485. X}
  2486. X
  2487. X/*
  2488. X * u_freelist: free one entry list and adjust the pointers
  2489. X */
  2490. X    static void
  2491. Xu_freelist(uhp)
  2492. X    struct u_header *uhp;
  2493. X{
  2494. X    register struct u_entry *uep, *nuep;
  2495. X
  2496. X    for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
  2497. X    {
  2498. X        nuep = uep->ue_next;
  2499. X        u_freeentry(uep, uep->ue_size);
  2500. X    }
  2501. X
  2502. X    if (u_curhead == uhp)
  2503. X        u_curhead = NULL;
  2504. X
  2505. X    if (uhp->uh_next == NULL)
  2506. X        u_oldhead = uhp->uh_prev;
  2507. X    else
  2508. X        uhp->uh_next->uh_prev = uhp->uh_prev;
  2509. X
  2510. X    if (uhp->uh_prev == NULL)
  2511. X        u_newhead = uhp->uh_next;
  2512. X    else
  2513. X        uhp->uh_prev->uh_next = uhp->uh_next;
  2514. X
  2515. X    free_line((char *)uhp);
  2516. X    --u_numhead;
  2517. X}
  2518. X
  2519. X/*
  2520. X * free entry 'uep' and 'n' lines in uep->ue_array[]
  2521. X */
  2522. X    static void
  2523. Xu_freeentry(uep, n)
  2524. X    struct u_entry *uep;
  2525. X    register long n;
  2526. X{
  2527. X    while (n)
  2528. X        free_line(uep->ue_array[--n]);
  2529. X    free_line((char *)uep);
  2530. X}
  2531. X
  2532. X/*
  2533. X * invalidate the undo buffer; called when storage has already been released
  2534. X */
  2535. X
  2536. X    void
  2537. Xu_clearall()
  2538. X{
  2539. X    u_newhead = u_oldhead = u_curhead = NULL;
  2540. X    u_synced = TRUE;
  2541. X    u_numhead = 0;
  2542. X    u_line_ptr = NULL;
  2543. X    u_line_lnum = 0;
  2544. X}
  2545. X
  2546. X/*
  2547. X * save the line "lnum" for the "U" command
  2548. X */
  2549. X    void
  2550. Xu_saveline(lnum)
  2551. X    linenr_t lnum;
  2552. X{
  2553. X    if (lnum == u_line_lnum)        /* line is already saved */
  2554. X        return;
  2555. X    if (lnum < 1 || lnum > line_count)    /* should never happen */
  2556. X        return;
  2557. X    u_clearline();
  2558. X    u_line_lnum = lnum;
  2559. X    if (Curpos.lnum == lnum)
  2560. X        u_line_colnr = Curpos.col;
  2561. X    else
  2562. X        u_line_colnr = 0;
  2563. X    u_line_ptr = save_line(nr2ptr(lnum));    /* when out of mem alloc() will give a warning */
  2564. X}
  2565. X
  2566. X/*
  2567. X * clear the line saved for the "U" command
  2568. X * (this is used externally for crossing a line while in insert mode)
  2569. X */
  2570. X    void
  2571. Xu_clearline()
  2572. X{
  2573. X    if (u_line_ptr != NULL)
  2574. X    {
  2575. X        free_line(u_line_ptr);
  2576. X        u_line_ptr = NULL;
  2577. X        u_line_lnum = 0;
  2578. X    }
  2579. X}
  2580. X
  2581. X/*
  2582. X * Implementation of the "U" command.
  2583. X * Differentiation from vi: "U" can be undone with the next "U".
  2584. X * We also allow the cursor to be in another line.
  2585. X */
  2586. X    void
  2587. Xu_undoline()
  2588. X{
  2589. X    colnr_t t;
  2590. X
  2591. X    if (u_line_ptr == NULL || u_line_lnum > line_count)
  2592. X    {
  2593. X        beep();
  2594. X        return;
  2595. X    }
  2596. X        /* first save the line for the 'u' command */
  2597. X    u_savecommon(u_line_lnum - 1, u_line_lnum + 1, FALSE, (linenr_t)0);
  2598. X    u_line_ptr = replaceline(u_line_lnum, u_line_ptr);
  2599. X
  2600. X    t = u_line_colnr;
  2601. X    if (Curpos.lnum == u_line_lnum)
  2602. X        u_line_colnr = Curpos.col;
  2603. X    Curpos.col = t;
  2604. X    Curpos.lnum = u_line_lnum;
  2605. X    cursupdate();
  2606. X    updateScreen(VALID_TO_CURSCHAR);
  2607. X}
  2608. END_OF_FILE
  2609. if test 14257 -ne `wc -c <'vim/src/undo.c'`; then
  2610.     echo shar: \"'vim/src/undo.c'\" unpacked with wrong size!
  2611. fi
  2612. chmod +x 'vim/src/undo.c'
  2613. # end of 'vim/src/undo.c'
  2614. fi
  2615. echo shar: End of archive 6 \(of 25\).
  2616. cp /dev/null ark6isdone
  2617. MISSING=""
  2618. 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
  2619.     if test ! -f ark${I}isdone ; then
  2620.     MISSING="${MISSING} ${I}"
  2621.     fi
  2622. done
  2623. if test "${MISSING}" = "" ; then
  2624.     echo You have unpacked all 25 archives.
  2625.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2626. else
  2627.     echo You still need to unpack the following archives:
  2628.     echo "        " ${MISSING}
  2629. fi
  2630. ##  End of shell archive.
  2631. exit 0
  2632.  
  2633. ===============================================================================
  2634. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  2635. Oce Nederland B.V., Research & Development | necessarily represent the position
  2636. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  2637. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  2638. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  2639.  
  2640. exit 0 # Just in case...
  2641.