home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume41 / vim / part14 < prev    next >
Text File  |  1993-12-20  |  66KB  |  2,853 lines

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i064:  vim - Vi IMitation editor, v2.0, Part14/25
  4. Message-ID: <1993Dec21.035146.28532@sparky.sterling.com>
  5. X-Md4-Signature: e893f42c485c2e2e6fe52ea6624a2a22
  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:51:46 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 64
  14. Archive-name: vim/part14
  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 14 (of 25)."
  25. # Contents:  vim/src/amiga.c vim/src/buffers.c
  26. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:06 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'vim/src/amiga.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'vim/src/amiga.c'\"
  30. else
  31. echo shar: Extracting \"'vim/src/amiga.c'\" \(30444 characters\)
  32. sed "s/^X//" >'vim/src/amiga.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 * amiga.c
  45. X *
  46. X * Amiga system-dependent routines.
  47. X */
  48. X
  49. X#include "vim.h"
  50. X#include "globals.h"
  51. X#include "proto.h"
  52. X#include "param.h"
  53. X
  54. X#include <fcntl.h>
  55. X
  56. X#undef TRUE             /* will be redefined by exec/types.h */
  57. X#undef FALSE
  58. X
  59. X#ifndef LATTICE
  60. X#  include <exec/types.h>
  61. X#  include <exec/exec.h>
  62. X#  include <libraries/dos.h>
  63. X#  include <libraries/dosextens.h>
  64. X#  include <intuition/intuition.h>
  65. X#else
  66. X#  include <proto/dos.h>
  67. X#  include <libraries/dosextens.h>
  68. X#  include <proto/intuition.h>
  69. X#  include <proto/exec.h>
  70. X#endif
  71. X
  72. X#ifndef NO_ARP
  73. X#include <libraries/arpbase.h>        /* for arp.library */
  74. X#endif
  75. X#include <dos/dostags.h>            /* for 2.0 functions */
  76. X#include <dos/dosasl.h>
  77. X
  78. X#if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
  79. X# include <libraries/arp_pragmas.h>
  80. X#endif
  81. X
  82. X/*
  83. X * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  84. X */
  85. X#undef TRUE
  86. X#define TRUE (1)
  87. X#undef FALSE
  88. X#define FALSE (0)
  89. X
  90. X#ifndef AZTEC_C
  91. Xstatic long dos_packet __ARGS((struct MsgPort *, long, long));
  92. X#endif
  93. Xstatic int lock2name __ARGS((BPTR lock, char *buf, long    len));
  94. Xstatic struct FileInfoBlock *get_fib __ARGS((char *));
  95. Xstatic int sortcmp __ARGS((char **a, char **b));
  96. X
  97. Xstatic BPTR                raw_in = (BPTR)NULL;
  98. Xstatic BPTR                raw_out = (BPTR)NULL;
  99. Xstatic int                close_win = FALSE;    /* set if Vim opened the window */
  100. X
  101. Xstruct IntuitionBase    *IntuitionBase = NULL;
  102. X#ifndef NO_ARP
  103. Xstruct ArpBase            *ArpBase = NULL;
  104. X#endif
  105. X
  106. Xstatic struct Window    *wb_window;
  107. Xstatic char                *oldwindowtitle = NULL;
  108. X
  109. X#ifndef NO_ARP
  110. Xint                        dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  111. X#endif
  112. Xint                        size_set = FALSE;    /* set to TRUE if window size was set */
  113. X
  114. X    void
  115. Xwin_resize_on()
  116. X{
  117. X    outstrn("\033[12{");
  118. X}
  119. X
  120. X    void
  121. Xwin_resize_off()
  122. X{
  123. X    outstrn("\033[12}");
  124. X}
  125. X
  126. X    void
  127. Xmch_write(p, len)
  128. X    char    *p;
  129. X    int        len;
  130. X{
  131. X    Write(raw_out, p, (long)len);
  132. X}
  133. X
  134. X/*
  135. X * GetChars(): low level input funcion.
  136. X * Get a characters from the keyboard.
  137. X * If time == 0 do not wait for characters.
  138. X * If time == n wait a short time for characters.
  139. X * If time == -1 wait forever for characters.
  140. X */
  141. X    int
  142. XGetChars(buf, maxlen, time)
  143. X    char    *buf;
  144. X    int        maxlen;
  145. X    int        time;                /* milli seconds */
  146. X{
  147. X    int        len;
  148. X    long    utime;
  149. X    
  150. X    if (time >= 0)
  151. X    {
  152. X        if (time == 0)
  153. X            utime = 100L;            /* time = 0 causes problems in DOS 1.2 */
  154. X        else
  155. X            utime = time * 1000L;    /* convert from milli to micro secs */
  156. X        if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  157. X            return 0;
  158. X    }
  159. X    else    /* time == -1 */
  160. X    {
  161. X    /*
  162. X     * If there is no character available within 2 seconds (default)
  163. X     * write the autoscript file to disk
  164. X     */
  165. X        if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  166. X            updatescript(0);
  167. X    }
  168. X
  169. X    for (;;)        /* repeat until we got a character */
  170. X    {
  171. X        len = Read(raw_in, buf, (long)maxlen);
  172. X        if (len > 0)
  173. X            return len;
  174. X    }
  175. X}
  176. X
  177. X    void
  178. Xsleep(n)
  179. X    int             n;
  180. X{
  181. X#ifndef LATTICE            /* SAS declares void Delay(UNLONG) */
  182. X    void            Delay __ARGS((long));
  183. X#endif
  184. X
  185. X    if (n > 0)
  186. X        Delay((long)(50L * n));
  187. X}
  188. X
  189. X    void
  190. Xvim_delay()
  191. X{
  192. X    Delay(25L);
  193. X}
  194. X
  195. X/*
  196. X * We have no job control, fake it by starting a new shell.
  197. X */
  198. Xvoid
  199. Xmch_suspend()
  200. X{
  201. X    outstr("new shell started\n");
  202. X    call_shell(NULL, 0, TRUE);
  203. X}
  204. X
  205. X#define DOS_LIBRARY     ((UBYTE *) "dos.library")
  206. X
  207. X    void
  208. Xmch_windinit()
  209. X{
  210. X    static char        intlibname[] = "intuition.library";
  211. X
  212. X#ifdef AZTEC_C
  213. X    Enable_Abort = 0;            /* disallow vim to be aborted */
  214. X#endif
  215. X    Columns = 80;
  216. X    Rows = 24;
  217. X
  218. X    /*
  219. X     * Set input and output channels, unless we have opened our own window
  220. X     */
  221. X    if (raw_in == (BPTR)NULL)
  222. X    {
  223. X        raw_in = Input();
  224. X        raw_out = Output();
  225. X    }
  226. X
  227. X    flushbuf();
  228. X
  229. X    wb_window = NULL;
  230. X    if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  231. X    {
  232. X        fprintf(stderr, "cannot open %s!?\n", intlibname);
  233. X        mch_windexit(3);
  234. X    }
  235. X    mch_get_winsize();
  236. X}
  237. X
  238. X#include <workbench/startup.h>
  239. X
  240. X/*
  241. X * Check_win checks whether we have an interactive window.
  242. X * If not, a new window is opened with the newcli command.
  243. X * If we would open a window ourselves, the :sh and :! commands would not
  244. X * work properly (Why? probably because we are then running in a background CLI).
  245. X * This also is the best way to assure proper working in a next Workbench release.
  246. X *
  247. X * For the -e option (quickfix mode) and -x we open our own window and disable :sh.
  248. X * Otherwise the compiler would never know when editing is finished.
  249. X */
  250. X#define BUF2SIZE 320        /* lenght of buffer for argument with complete path */
  251. X
  252. X    void
  253. Xcheck_win(argc, argv)
  254. X    int argc;
  255. X    char **argv;
  256. X{
  257. X    int                i;
  258. X    BPTR            nilfh, fh;
  259. X    char            buf1[20];
  260. X    char            buf2[BUF2SIZE];
  261. X    static char        *(constrings[3]) = {"con:0/0/662/210/",
  262. X                                      "con:0/0/640/200/",
  263. X                                      "con:0/0/320/200/"};
  264. X    static char        winerr[] = "VIM: Can't open window!\n";
  265. X    struct WBArg    *argp;
  266. X    int                ac;
  267. X    char            *av;
  268. X    char            *device = NULL;
  269. X    int                exitval = 4;
  270. X    struct Library    *DosBase;
  271. X    int                usewin = FALSE;
  272. X
  273. X/*
  274. X * check if we are running under DOS 2.0x or higher
  275. X */
  276. X    if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  277. X    {
  278. X        CloseLibrary(DosBase);
  279. X#ifndef NO_ARP
  280. X        dos2 = TRUE;
  281. X#endif
  282. X    }
  283. X    else            /* without arp functions we NEED 2.0 */
  284. X    {
  285. X#ifdef NO_ARP
  286. X        fprintf(stderr, "Need Amigados version 2.04 or later\n");
  287. X        exit(3);
  288. X#else
  289. X                    /* need arp functions for dos 1.x */
  290. X        if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  291. X        {
  292. X            fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
  293. X            exit(3);
  294. X        }
  295. X#endif
  296. X    }
  297. X
  298. X/*
  299. X * scan argv[] for the '-e', '-x' and '-d' arguments
  300. X */
  301. X    for (i = 1; i < argc; ++i)
  302. X        if (argv[i][0] == '-')
  303. X        {
  304. X            switch (argv[i][1])
  305. X            {
  306. X            case 'e':
  307. X            case 'x':
  308. X                usewin = TRUE;
  309. X                break;
  310. X
  311. X            case 'd':
  312. X                if (i < argc - 1)
  313. X                    device = argv[i + 1];
  314. X                break;
  315. X            }
  316. X        }
  317. X
  318. X/*
  319. X * If we were not started from workbench, do not have a '-d' argument and
  320. X * we have been started with an interactive window, use that window.
  321. X */
  322. X    if (argc != 0 && device == NULL &&
  323. X                IsInteractive(Input()) && IsInteractive(Output()))
  324. X        return;
  325. X
  326. X/*
  327. X * If we are in quickfix mode, we open our own window. We can't use the
  328. X * newcli trick below, because the compiler would not know when we are finished.
  329. X * We do the same with the '-x' option, for mail, rn, etc.
  330. X */
  331. X    if (usewin)
  332. X    {
  333. X        /*
  334. X         * Try to open a window. First try the specified device.
  335. X         * Then try a 24 line 80 column window.
  336. X         * If that fails, try two smaller ones.
  337. X         */
  338. X        for (i = -1; i < 3; ++i)
  339. X        {
  340. X            if (i >= 0)
  341. X                device = constrings[i];
  342. X            if (device && (raw_in = Open((UBYTE *)device, (long)MODE_NEWFILE)) != (BPTR)NULL)
  343. X                break;
  344. X        }
  345. X        if (raw_in == (BPTR)NULL)        /* all three failed */
  346. X        {
  347. X            fprintf(stderr, winerr);
  348. X            goto exit;
  349. X        }
  350. X        raw_out = raw_in;
  351. X        close_win = TRUE;
  352. X        return;
  353. X    }
  354. X
  355. X    if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  356. X    {
  357. X        fprintf(stderr, "Cannot open NIL:\n");
  358. X        goto exit;
  359. X    }
  360. X
  361. X    /*
  362. X     * make a unique name for the temp file (which we will not delete!)
  363. X     */
  364. X    sprintf(buf1, "t:nc%ld", buf1);    /* nobody else is using our stack */
  365. X    if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  366. X    {
  367. X        fprintf(stderr, "Cannot create %s\n", buf1);
  368. X        goto exit;
  369. X    }
  370. X    /*
  371. X     * Write the command into the file, put quotes around the arguments that
  372. X     * have a space in them.
  373. X     */
  374. X    if (argc == 0)        /* run from workbench */
  375. X        ac = ((struct WBStartup *)argv)->sm_NumArgs;
  376. X    else
  377. X        ac = argc;
  378. X    for (i = 0; i < ac; ++i)
  379. X    {
  380. X        if (argc == 0)
  381. X        {
  382. X            *buf2 = NUL;
  383. X            argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  384. X            if (argp->wa_Lock)
  385. X                lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  386. X#ifndef NO_ARP
  387. X            if (dos2)        /* use 2.0 function */
  388. X#endif
  389. X                AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  390. X#ifndef NO_ARP
  391. X            else            /* use arp function */
  392. X                TackOn(buf2, argp->wa_Name);
  393. X#endif
  394. X            av = buf2;
  395. X        }
  396. X        else
  397. X            av = argv[i];
  398. X
  399. X        if (av[0] == '-' && av[1] == 'd')        /* skip '-d' option */
  400. X        {
  401. X            ++i;
  402. X            continue;
  403. X        }
  404. X        if (strchr(av, ' '))
  405. X            Write(fh, "\"", 1L);
  406. X        Write(fh, av, (long)strlen(av));
  407. X        if (strchr(av, ' '))
  408. X            Write(fh, "\"", 1L);
  409. X        Write(fh, " ", 1L);
  410. X    }
  411. X    Write(fh, "\nendcli\n", 8L);
  412. X    Close(fh);
  413. X
  414. X/*
  415. X * Try to open a new cli in a window. If '-d' argument was given try to open
  416. X * the specified device. Then try a 24 line 80 column window.
  417. X * If that fails, try two smaller ones.
  418. X */
  419. X    for (i = -1; i < 3; ++i)
  420. X    {
  421. X        if (i >= 0)
  422. X            device = constrings[i];
  423. X        else if (device == NULL)
  424. X            continue;
  425. X        sprintf(buf2, "newcli <nil: >nil: %s from %s", device, buf1);
  426. X#ifndef NO_ARP
  427. X        if (dos2)
  428. X        {
  429. X#endif
  430. X            if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  431. X                break;
  432. X#ifndef NO_ARP
  433. X        }
  434. X        else
  435. X        {
  436. X            if (Execute((UBYTE *)buf2, nilfh, nilfh))
  437. X                break;
  438. X        }
  439. X#endif
  440. X    }
  441. X    if (i == 3)        /* all three failed */
  442. X    {
  443. X        DeleteFile((UBYTE *)buf1);
  444. X        fprintf(stderr, winerr);
  445. X        goto exit;
  446. X    }
  447. X    exitval = 0;    /* The Execute succeeded: exit this program */
  448. X
  449. Xexit:
  450. X#ifndef NO_ARP
  451. X    if (ArpBase)
  452. X        CloseLibrary((struct Library *) ArpBase);
  453. X#endif
  454. X    exit(exitval);
  455. X}
  456. X
  457. X/*
  458. X * fname_case(): Set the case of the filename, if it already exists.
  459. X *                 This will cause the filename to remain exactly the same.
  460. X */
  461. X    void
  462. Xfname_case(name)
  463. X    char *name;
  464. X{
  465. X    register struct FileInfoBlock    *fib;
  466. X    register size_t                    len;
  467. X
  468. X    fib = get_fib(name);
  469. X    if (fib != NULL)
  470. X    {
  471. X        len = strlen(name);
  472. X        if (len == strlen(fib->fib_FileName))    /* safety check */
  473. X            memmove(name, fib->fib_FileName, len);
  474. X        free(fib);
  475. X    }
  476. X}
  477. X
  478. X/*
  479. X * Get the FileInfoBlock for file "fname"
  480. X * The returned structure has to be free()d.
  481. X * Returns NULL on error.
  482. X */
  483. X    static struct FileInfoBlock *
  484. Xget_fib(fname)
  485. X    char *fname;
  486. X{
  487. X    register BPTR                    flock;
  488. X    register struct FileInfoBlock    *fib;
  489. X
  490. X    if (fname == NULL)        /* safety check */
  491. X        return NULL;
  492. X    fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  493. X    if (fib != NULL)
  494. X    {
  495. X        flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  496. X        if (flock == (BPTR)NULL || !Examine(flock, fib))
  497. X        {
  498. X            free(fib);    /* in case of an error the memory is freed here */
  499. X            fib = NULL;
  500. X        }
  501. X        if (flock)
  502. X            UnLock(flock);
  503. X    }
  504. X    return fib;
  505. X}
  506. X
  507. X/*
  508. X * settitle(): set titlebar of our window
  509. X */
  510. Xstatic char *lasttitle = NULL;
  511. X
  512. X    void
  513. Xsettitle(str)
  514. X    char *str;
  515. X{
  516. X
  517. X    if (wb_window != NULL)
  518. X    {
  519. X        free(lasttitle);
  520. X        lasttitle = alloc((unsigned)(strlen(str) + 7));
  521. X        if (lasttitle != NULL)
  522. X        {
  523. X            sprintf(lasttitle, "VIM - %s", str);
  524. X            SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
  525. X        }
  526. X    }
  527. X}
  528. X
  529. X    void
  530. Xresettitle()
  531. X{
  532. X        if (wb_window != NULL && lasttitle != NULL)
  533. X                SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
  534. X}
  535. X
  536. X/*
  537. X * Get name of current directory into buffer 'buf' of length 'len' bytes.
  538. X * Return non-zero for success.
  539. X */
  540. Xdirname(buf, len)
  541. X    char        *buf;
  542. X    int            len;
  543. X{
  544. X    return FullName("", buf, len);
  545. X}
  546. X
  547. X/*
  548. X * get absolute filename into buffer 'buf' of length 'len' bytes
  549. X */
  550. XFullName(fname, buf, len)
  551. X    char        *fname, *buf;
  552. X    int            len;
  553. X{
  554. X    BPTR        l;
  555. X    int            retval = 0;
  556. X
  557. X    if (fname == NULL)    /* always fail */
  558. X        return 0;
  559. X
  560. X    if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)))/* lock the file */
  561. X    {
  562. X        retval = lock2name(l, buf, (long)len);
  563. X        UnLock(l);
  564. X    }
  565. X    if (retval == 0 || *buf == 0 || *buf == ':')
  566. X        strcpy(buf, fname);            /* something failed; use the filename */
  567. X    return retval;
  568. X}
  569. X
  570. X/*
  571. X * Get the full filename from a lock. Use 2.0 function if possible, because
  572. X * the arp function has more restrictions on the path length.
  573. X */
  574. X    static int
  575. Xlock2name(lock, buf, len)
  576. X    BPTR    lock;
  577. X    char    *buf;
  578. X    long    len;
  579. X{
  580. X#ifndef NO_ARP
  581. X    if (dos2)                /* use 2.0 function */
  582. X#endif
  583. X        return (int)NameFromLock(lock, (UBYTE *)buf, len);
  584. X#ifndef NO_ARP
  585. X    else                /* use arp function */
  586. X        return (int)PathName(lock, buf, (long)(len/32));
  587. X#endif
  588. X}
  589. X
  590. X/*
  591. X * get file permissions for 'name'
  592. X */
  593. X    long
  594. Xgetperm(name)
  595. X    char        *name;
  596. X{
  597. X    struct FileInfoBlock    *fib;
  598. X    long                     retval = -1;
  599. X
  600. X    fib = get_fib(name);
  601. X    if (fib != NULL)
  602. X    {
  603. X        retval = fib->fib_Protection;
  604. X        free(fib);
  605. X    }
  606. X    return retval;
  607. X}
  608. X
  609. X/*
  610. X * set file permission for 'name' to 'perm'
  611. X */
  612. Xsetperm(name, perm)
  613. X    char        *name;
  614. X    long        perm;
  615. X{
  616. X    perm &= ~FIBF_ARCHIVE;                /* reset archived bit */
  617. X    return (int)SetProtection((UBYTE *)name, (long)perm);
  618. X}
  619. X
  620. X/*
  621. X * check if "name" is a directory
  622. X */
  623. Xisdir(name)
  624. X    char        *name;
  625. X{
  626. X    struct FileInfoBlock    *fib;
  627. X    int                     retval = -1;
  628. X
  629. X    fib = get_fib(name);
  630. X    if (fib != NULL)
  631. X    {
  632. X        retval = (fib->fib_DirEntryType >= 0);
  633. X        free(fib);
  634. X    }
  635. X    return retval;
  636. X}
  637. X
  638. X/*
  639. X * Careful: mch_windexit() may be called before mch_windinit()!
  640. X */
  641. X    void
  642. Xmch_windexit(r)
  643. X    int             r;
  644. X{
  645. X    if (raw_in)                        /* put terminal in 'normal' mode */
  646. X    {
  647. X        settmode(0);
  648. X        stoptermcap();
  649. X    }
  650. X    if (raw_out)
  651. X    {
  652. X        if (term_console)
  653. X        {
  654. X            win_resize_off();        /* window resize events de-activated */
  655. X            if (size_set)
  656. X                outstr("\233t\233u");        /* reset window size (CSI t CSI u) */
  657. X        }
  658. X        flushbuf();
  659. X    }
  660. X
  661. X    if (wb_window != NULL)            /* disable window title */
  662. X        SetWindowTitles(wb_window, (UBYTE *)oldwindowtitle, (UBYTE *)-1L);
  663. X    stopscript();                    /* remove autoscript file */
  664. X#ifndef NO_ARP
  665. X    if (ArpBase)
  666. X        CloseLibrary((struct Library *) ArpBase);
  667. X#endif
  668. X    if (close_win)
  669. X        Close(raw_in);
  670. X    if (r)
  671. X        printf("Vim exiting with %d\n", r);    /* somehow this makes :cq work!? */
  672. X    exit(r);
  673. X}
  674. X
  675. X/*
  676. X * This is a routine for setting a given stream to raw or cooked mode on the
  677. X * Amiga . This is useful when you are using Lattice C to produce programs
  678. X * that want to read single characters with the "getch()" or "fgetc" call.
  679. X *
  680. X * Written : 18-Jun-87 By Chuck McManis.
  681. X */
  682. X
  683. X#define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  684. X
  685. X/*
  686. X * Function mch_settmode() - Convert the specified file pointer to 'raw' or 'cooked'
  687. X * mode. This only works on TTY's.
  688. X *
  689. X * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  690. X *        getch() will return immediately rather than wait for a return. You
  691. X *        lose editing features though.
  692. X *
  693. X * Cooked: This function returns the designate file pointer to it's normal,
  694. X *        wait for a <CR> mode. This is exactly like raw() except that
  695. X *        it sends a 0 to the console to make it back into a CON: from a RAW:
  696. X */
  697. X    void
  698. Xmch_settmode(raw)
  699. X    int            raw;
  700. X{
  701. X    if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, raw ? -1L : 0L) == 0)
  702. X        fprintf(stderr, "cannot change console mode ?!\n");
  703. X}
  704. X
  705. X/*
  706. X * Code for this routine came from the following :
  707. X *
  708. X * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  709. X *     DOS packet example
  710. X *     Requires 1.2
  711. X *
  712. X * Found on Fish Disk 56.
  713. X *
  714. X * Heavely modified by mool.
  715. X */
  716. X
  717. X#include <devices/conunit.h>
  718. X
  719. X/*
  720. X * try to get the real window size
  721. X * return non-zero for failure
  722. X */
  723. X    int
  724. Xmch_get_winsize()
  725. X{
  726. X    struct ConUnit    *conUnit;
  727. X     char            id_a[sizeof(struct InfoData) + 3];
  728. X    struct InfoData *id;
  729. X
  730. X    if (!term_console)    /* not an amiga window */
  731. X        return 1;
  732. X
  733. X    /* insure longword alignment */
  734. X     id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  735. X
  736. X    /*
  737. X     * Should make console aware of real window size, not the one we set.
  738. X     * Unfortunately, under DOS 2.0x this redraws the window and it
  739. X     * is rarely needed, so we skip it now, unless we changed the size.
  740. X     */
  741. X    if (size_set)
  742. X        outstr("\233t\233u");    /* CSI t CSI u */
  743. X    flushbuf();
  744. X
  745. X    if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 ||
  746. X                (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  747. X    {
  748. X        /* it's not an amiga window, maybe aux device */
  749. X        /* terminal type should be set */
  750. X        term_console = FALSE;
  751. X        return 1;
  752. X    }
  753. X    if (oldwindowtitle == NULL)
  754. X        oldwindowtitle = (char *)wb_window->Title;
  755. X    if (id->id_InUse == (BPTR)NULL)
  756. X    {
  757. X        fprintf(stderr, "mch_get_winsize: not a console??\n");
  758. X        return (2);
  759. X    }
  760. X    conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  761. X
  762. X    /* get window size */
  763. X    Rows = conUnit->cu_YMax + 1;
  764. X    Columns = conUnit->cu_XMax + 1;
  765. X    if (Rows < 0 || Rows > 200)     /* cannot be an amiga window */
  766. X    {
  767. X        Columns = 80;
  768. X        Rows = 24;
  769. X        term_console = FALSE;
  770. X        return 1;
  771. X    }
  772. X    Rows_max = Rows;                /* remember physical max height */
  773. X
  774. X    check_winsize();
  775. X    script_winsize();
  776. X
  777. X    return 0;
  778. X}
  779. X
  780. X/*
  781. X * try to set the real window size
  782. X */
  783. X    void
  784. Xmch_set_winsize()
  785. X{
  786. X    if (term_console)
  787. X    {
  788. X        size_set = TRUE;
  789. X        outchar(CSI);
  790. X        outnum((long)Rows);
  791. X        outchar('t');
  792. X        outchar(CSI);
  793. X        outnum((long)Columns);
  794. X        outchar('u');
  795. X        flushbuf();
  796. X    }
  797. X}
  798. X
  799. X#ifdef SETKEYMAP
  800. X/*
  801. X * load and activate a new keymap for our CLI - DOES NOT WORK -
  802. X * The problem is that after the setting of the keymap the input blocks
  803. X * But the new keymap works allright in another window.
  804. X * Tried but no improvement:
  805. X * - remembering the length, data and command fields in request->io_xxx
  806. X * - settmode(0) first, settmode(1) afterwards
  807. X * - putting the keymap directly in conunit structure
  808. X */
  809. X
  810. X#include <devices/keymap.h>
  811. X
  812. X    void
  813. Xset_keymap(name)
  814. X    char *name;
  815. X{
  816. X     char                    id_a[sizeof(struct InfoData) + 3];
  817. X    struct InfoData            *id;
  818. X    static struct KeyMap    *old;
  819. X    static BPTR                segment = (BPTR)NULL;
  820. X    struct IOStdReq            *request;
  821. X    int                        c;
  822. X
  823. X    if (!term_console)
  824. X        return;
  825. X
  826. X    /* insure longword alignment */
  827. X     id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  828. X
  829. X    if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0)
  830. X    {
  831. X        emsg("dos_packet failed");
  832. X        return;
  833. X    }
  834. X    if (id->id_InUse == (BPTR)NULL)
  835. X    {
  836. X        emsg("not a console??");
  837. X        return;
  838. X    }
  839. X    request = (struct IOStdReq *) id->id_InUse;
  840. X
  841. X    if (segment != (BPTR)NULL)    /* restore old keymap */
  842. X    {
  843. X        request->io_Command = CD_SETKEYMAP;
  844. X        request->io_Length = sizeof(struct KeyMap);
  845. X        request->io_Data = (APTR)old;
  846. X        DoIO((struct IORequest *)request);
  847. X        if (request->io_Error)
  848. X            emsg("Cannot reset keymap");
  849. X        else                /* no error, free the allocated memory */
  850. X        {
  851. X            UnLoadSeg(segment);
  852. X            FreeMem(old, sizeof(struct KeyMap));
  853. X            segment = (BPTR)NULL;
  854. X        }
  855. X    }
  856. X    if (name != NULL)
  857. X    {
  858. X        segment = LoadSeg(name);
  859. X        if (segment == (BPTR)NULL)
  860. X        {
  861. X            emsg("Cannot open keymap file");
  862. X            return;
  863. X        }
  864. X        old = (struct KeyMap *)AllocMem(sizeof(struct KeyMap), MEMF_PUBLIC);
  865. X        if (old == NULL)
  866. X        {
  867. X            emsg(e_outofmem);
  868. X            UnLoadSeg(segment);
  869. X            segment = (BPTR)NULL;
  870. X        }
  871. X        else
  872. X        {
  873. X            request->io_Command = CD_ASKKEYMAP;
  874. X            request->io_Length = sizeof(struct KeyMap);
  875. X            request->io_Data = (APTR)old;
  876. X            DoIO((struct IORequest *)request);
  877. X            if (request->io_Error)
  878. X            {
  879. X                emsg("Cannot get old keymap");
  880. X                UnLoadSeg(segment);
  881. X                segment = (BPTR)NULL;
  882. X                FreeMem(old, sizeof(struct KeyMap));
  883. X            }
  884. X            else
  885. X            {
  886. X                request->io_Command = CD_SETKEYMAP;
  887. X                request->io_Length = sizeof(struct KeyMap);
  888. X                request->io_Data = (APTR)((segment << 2) + 18);
  889. X                DoIO((struct IORequest *)request);
  890. X                if (request->io_Error)
  891. X                    emsg("Cannot set keymap");
  892. X
  893. X                /* test for blocking */
  894. X                request->io_Command = CMD_READ;
  895. X                request->io_Length = 1;
  896. X                request->io_Data = (APTR)&c;
  897. X                DoIO((struct IORequest *)request);    /* BLOCK HERE! */
  898. X                if (request->io_Error)
  899. X                    emsg("Cannot set keymap");
  900. X            }
  901. X        }
  902. X    }
  903. X}
  904. X#endif
  905. X
  906. X#ifndef AZTEC_C
  907. X/*
  908. X * Sendpacket.c
  909. X *
  910. X * An invaluable addition to your Amiga.lib file. This code sends a packet to
  911. X * the given message port. This makes working around DOS lots easier.
  912. X *
  913. X * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  914. X * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  915. X * say 'oml lib:amiga.lib -r sendpacket.o'
  916. X */
  917. X
  918. X/* #include <proto/exec.h> */
  919. X/* #include <proto/dos.h> */
  920. X#include <exec/memory.h>
  921. X
  922. X/*
  923. X * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  924. X * Finkel. This function will send a packet of the given type to the Message
  925. X * Port supplied.
  926. X */
  927. X
  928. X    static long
  929. Xdos_packet(pid, action, arg)
  930. X    struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  931. X    long            action, /* packet type ... (what you want handler to do)   */
  932. X                    arg;    /* single argument */
  933. X{
  934. X# ifndef NO_ARP
  935. X    struct MsgPort            *replyport;
  936. X    struct StandardPacket    *packet;
  937. X    long                    res1;
  938. X
  939. X    if (dos2)
  940. X# endif
  941. X        return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  942. X# ifndef NO_ARP
  943. X
  944. X    replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  945. X    if (!replyport)
  946. X        return (0);
  947. X
  948. X    /* Allocate space for a packet, make it public and clear it */
  949. X    packet = (struct StandardPacket *)
  950. X        AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  951. X    if (!packet) {
  952. X        DeletePort(replyport);
  953. X        return (0);
  954. X    }
  955. X    packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  956. X    packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  957. X    packet->sp_Pkt.dp_Port = replyport;
  958. X    packet->sp_Pkt.dp_Type = action;
  959. X    packet->sp_Pkt.dp_Arg1 = arg;
  960. X
  961. X    PutMsg(pid, (struct Message *)packet);        /* send packet */
  962. X
  963. X    WaitPort(replyport);
  964. X    GetMsg(replyport);
  965. X
  966. X    res1 = packet->sp_Pkt.dp_Res1;
  967. X
  968. X    FreeMem(packet, (long) sizeof(struct StandardPacket));
  969. X    DeletePort(replyport);
  970. X
  971. X    return (res1);
  972. X# endif
  973. X}
  974. X#endif
  975. X
  976. X/*
  977. X * call shell, return non-zero for failure
  978. X */
  979. X    int
  980. Xcall_shell(cmd, filter, cooked)
  981. X        char    *cmd;
  982. X        int        filter;        /* if != 0: called by dofilter() */
  983. X        int        cooked;
  984. X{
  985. X    BPTR mydir;
  986. X    int x;
  987. X#ifndef LATTICE
  988. X    int    use_execute;
  989. X    char *shellcmd = NULL;
  990. X    char *shellarg;
  991. X#endif
  992. X    int    retval = 0;
  993. X
  994. X    if (close_win)
  995. X    {
  996. X        /* if Vim opened a window: Executing a shell may cause crashes */
  997. X        emsg("Cannot execute shell with -e or -x option");
  998. X        return 1;
  999. X    }
  1000. X
  1001. X    if (term_console)
  1002. X        win_resize_off();             /* window resize events de-activated */
  1003. X    flushbuf();
  1004. X
  1005. X    if (cooked)
  1006. X        settmode(0);                 /* set to cooked mode */
  1007. X    mydir = Lock((UBYTE *)"", (long)ACCESS_READ);    /* remember current directory */
  1008. X
  1009. X#ifdef LATTICE                        /* not tested very much */
  1010. X    if (cmd == NULL)
  1011. X    {
  1012. X# ifndef NO_ARP
  1013. X        if (dos2)
  1014. X# endif
  1015. X            x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1016. X# ifndef NO_ARP
  1017. X        else
  1018. X            x = Execute(p_sh, raw_in, raw_out);
  1019. X# endif
  1020. X    }
  1021. X    else
  1022. X    {
  1023. X# ifndef NO_ARP
  1024. X        if (dos2)
  1025. X# endif
  1026. X            x = SystemTags(cmd, SYS_UserShell, TRUE, TAG_DONE);
  1027. X# ifndef NO_ARP
  1028. X        else
  1029. X            x = Execute(cmd, 0L, raw_out);
  1030. X# endif
  1031. X    }
  1032. X# ifdef NO_ARP
  1033. X    if (x < 0)
  1034. X# else
  1035. X    if ((dos2 && x < 0) || (!dos2 && !x))
  1036. X# endif
  1037. X    {
  1038. X        if (cmd == NULL)
  1039. X            emsg2("Cannot execute shell %s", p_sh);
  1040. X        else
  1041. X            emsg2("Cannot execute %s", cmd);
  1042. X        outchar('\n');
  1043. X        retval = 1;
  1044. X    }
  1045. X# ifdef NO_ARP
  1046. X    else if (x)
  1047. X# else
  1048. X    else if (!dos2 || x)
  1049. X# endif
  1050. X    {
  1051. X        if (x = IoErr())
  1052. X        {
  1053. X            smsg("%d returned", x);
  1054. X            outchar('\n');
  1055. X            retval = 1;
  1056. X        }
  1057. X    }
  1058. X#else    /* LATTICE */
  1059. X    if (p_st >= 4 || (p_st >= 2 && !filter))
  1060. X        use_execute = 1;
  1061. X    else
  1062. X        use_execute = 0;
  1063. X    if (!use_execute)
  1064. X    {
  1065. X        /*
  1066. X         * separate shell name from argument
  1067. X         */
  1068. X        shellcmd = strsave(p_sh);
  1069. X        if (shellcmd == NULL)        /* out of memory, use Execute */
  1070. X            use_execute = 1;
  1071. X        else
  1072. X        {
  1073. X            shellarg = shellcmd;
  1074. X            skiptospace(&shellarg);    /* find start of arguments */
  1075. X            if (*shellarg != NUL)
  1076. X            {
  1077. X                *shellarg++ = NUL;
  1078. X                skipspace(&shellarg);
  1079. X            }
  1080. X        }
  1081. X    }
  1082. X    if (cmd == NULL)
  1083. X    {
  1084. X        if (use_execute)
  1085. X        {
  1086. X#ifndef NO_ARP
  1087. X            if (dos2)
  1088. X#endif
  1089. X                x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1090. X#ifndef NO_ARP
  1091. X            else
  1092. X                x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1093. X#endif
  1094. X        }
  1095. X        else
  1096. X            x = fexecl(shellcmd, shellcmd, shellarg, NULL);
  1097. X    }
  1098. X    else if (use_execute)
  1099. X    {
  1100. X#ifndef NO_ARP
  1101. X        if (dos2)
  1102. X#endif
  1103. X            x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1104. X#ifndef NO_ARP
  1105. X        else
  1106. X            x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1107. X#endif
  1108. X    }
  1109. X    else if (p_st & 1)
  1110. X        x = fexecl(shellcmd, shellcmd, shellarg, cmd, NULL);
  1111. X    else
  1112. X        x = fexecl(shellcmd, shellcmd, shellarg, "-c", cmd, NULL);
  1113. X#ifdef NO_ARP
  1114. X    if (x < 0)
  1115. X#else
  1116. X    if ((dos2 && x < 0) || (!dos2 && x))
  1117. X#endif
  1118. X    {
  1119. X        if (use_execute)
  1120. X            emsg2("Cannot execute %s", cmd == NULL ? p_sh : cmd);
  1121. X        else
  1122. X            emsg2("Cannot execute shell %s", shellcmd);
  1123. X        outchar('\n');
  1124. X        retval = 1;
  1125. X    }
  1126. X    else
  1127. X    {
  1128. X        if (use_execute)
  1129. X        {
  1130. X#ifdef NO_ARP
  1131. X            if (x)
  1132. X#else
  1133. X            if (!dos2 || x)
  1134. X#endif
  1135. X                x = IoErr();
  1136. X        }
  1137. X        else
  1138. X            x = wait();
  1139. X        if (x)
  1140. X        {
  1141. X            smsg("%d returned", x);
  1142. X            outchar('\n');
  1143. X            retval = 1;
  1144. X        }
  1145. X    }
  1146. X    free(shellcmd);
  1147. X#endif
  1148. X
  1149. X    if (mydir = CurrentDir(mydir))        /* make sure we stay in the same directory */
  1150. X        UnLock(mydir);
  1151. X    if (cooked)
  1152. X        settmode(1);                     /* set to raw mode */
  1153. X    resettitle();
  1154. X    if (term_console)
  1155. X        win_resize_on();                 /* window resize events activated */
  1156. X    return retval;
  1157. X}
  1158. X
  1159. X/*
  1160. X * check for an "interrupt signal"
  1161. X * We only react to a CTRL-C, but also clear the other break signals to avoid trouble
  1162. X * with lattice-c programs.
  1163. X */
  1164. X    void
  1165. Xbreakcheck()
  1166. X{
  1167. X   if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1168. X        got_int = TRUE;
  1169. X}
  1170. X
  1171. X/* this routine causes manx to use this Chk_Abort() rather than it's own */
  1172. X/* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1173. X/* is zero).  Since we want to check for our own ^C's                    */
  1174. X
  1175. X#ifdef _DCC
  1176. X#define Chk_Abort chkabort
  1177. X#endif
  1178. X
  1179. X    long
  1180. XChk_Abort()
  1181. X{
  1182. X    return(0L);
  1183. X}
  1184. X
  1185. X/*
  1186. X * ExpandWildCard() - this code does wild-card pattern matching using the arp
  1187. X *                      routines. This is based on WildDemo2.c (found in arp1.1
  1188. X *                      distribution). That code's copyright follows :
  1189. X *-------------------------------------------------------------------------
  1190. X * WildDemo2.c - Search filesystem for patterns, and separate into directories
  1191. X *         and files, sorting each separately using DA lists.
  1192. X *
  1193. X * -+=SDB=+-
  1194. X *
  1195. X * Copyright (c) 1987, Scott Ballantyne
  1196. X * Use and abuse as you please.
  1197. X *
  1198. X * num_pat is number of input patterns
  1199. X * pat is array of pointers to input patterns
  1200. X * num_file is pointer to number of matched file names
  1201. X * file is pointer to array of pointers to matched file names
  1202. X * if file_only is TRUE we match only files, no dirs
  1203. X * if list_notfound is TRUE we include not-found entries (probably locked)
  1204. X * return 0 for success, 1 for error (you may loose some memory)
  1205. X *-------------------------------------------------------------------------
  1206. X */
  1207. X
  1208. X/* #include <arpfunctions.h> */
  1209. Xextern void *malloc __ARGS((size_t)), *calloc __ARGS((size_t, size_t));
  1210. Xstatic int insfile __ARGS((char *, int));
  1211. Xstatic void freefiles __ARGS((void));
  1212. X
  1213. X#define ANCHOR_BUF_SIZE (512)
  1214. X#define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1215. X
  1216. X/*
  1217. X * we use this structure to built a list of file names
  1218. X */
  1219. Xstruct onefile
  1220. X{
  1221. X    struct onefile    *next;
  1222. X    char            name[1];    /* really longer */
  1223. X} *namelist = NULL;
  1224. X
  1225. X/*
  1226. X * insert one file into the list of file names
  1227. X * return -1 for failure
  1228. X * return 0 for success
  1229. X */
  1230. X    static int
  1231. Xinsfile(name, isdir)
  1232. X    char    *name;
  1233. X    int        isdir;
  1234. X{
  1235. X    struct onefile *new;
  1236. X
  1237. X    new = (struct onefile *)alloc((unsigned)(sizeof(struct onefile) + strlen(name) + isdir));
  1238. X    if (new == NULL)
  1239. X        return -1;
  1240. X    strcpy(&(new->name[0]), name);
  1241. X    if (isdir)
  1242. X        strcat(&(new->name[0]), "/");
  1243. X    new->next = namelist;
  1244. X    namelist = new;
  1245. X    return 0;
  1246. X}
  1247. X
  1248. X/*
  1249. X * free a whole list of file names
  1250. X */
  1251. X    static void
  1252. Xfreefiles()
  1253. X{
  1254. X    struct onefile *p;
  1255. X
  1256. X    while (namelist)
  1257. X    {
  1258. X        p = namelist->next;
  1259. X        free(namelist);
  1260. X        namelist = p;
  1261. X    }
  1262. X}
  1263. X
  1264. X    static int
  1265. Xsortcmp(a, b)
  1266. X    char **a, **b;
  1267. X{
  1268. X    return strcmp(*a, *b);
  1269. X}
  1270. X
  1271. XExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  1272. X    int             num_pat;
  1273. X    char          **pat;
  1274. X    int            *num_file;
  1275. X    char         ***file;
  1276. X    int            files_only;
  1277. X    int            list_notfound;
  1278. X{
  1279. X    int                     i;
  1280. X    struct AnchorPath        *Anchor;
  1281. X    int                        domatchend = FALSE;
  1282. X    LONG                    Result;
  1283. X    struct onefile            *p;
  1284. X    char                    *errmsg = NULL;
  1285. X    char                    *starbuf, *sp, *dp;
  1286. X    int                        foundone;
  1287. X
  1288. X    *num_file = 0;
  1289. X    *file = (char **)"";
  1290. X
  1291. X    /* Get our AnchorBase */
  1292. X    Anchor = (struct AnchorPath *) calloc((size_t)1, (size_t)ANCHOR_SIZE);
  1293. X    if (!Anchor)
  1294. X        goto OUT_OF_MEMORY;
  1295. X    Anchor->ap_StrLen = ANCHOR_BUF_SIZE;    /* ap_Length not supported anymore */
  1296. X#ifdef APF_DODOT
  1297. X    Anchor->ap_Flags = APF_DODOT | APF_DOWILD;        /* allow '.' for current dir */
  1298. X#else
  1299. X    Anchor->ap_Flags = APF_DoDot | APF_DoWild;        /* allow '.' for current dir */
  1300. X#endif
  1301. X
  1302. X    for (i = 0; i < num_pat; i++)
  1303. X    {
  1304. X#ifndef NO_ARP
  1305. X        if (dos2)
  1306. X        {
  1307. X#endif
  1308. X                /* hack to replace '*' by '#?' */
  1309. X            starbuf = alloc((unsigned)(2 * strlen(pat[i]) + 1));    /* maximum required */
  1310. X            if (starbuf == NULL)
  1311. X                goto OUT_OF_MEMORY;
  1312. X            for (sp = pat[i], dp = starbuf; *sp; ++sp)
  1313. X            {
  1314. X                if (*sp == '*')
  1315. X                {
  1316. X                    *dp++ = '#';
  1317. X                    *dp++ = '?';
  1318. X                }
  1319. X                else
  1320. X                    *dp++ = *sp;
  1321. X            }
  1322. X            *dp = NUL;
  1323. X            Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1324. X            free(starbuf);
  1325. X#ifndef NO_ARP
  1326. X        }
  1327. X        else
  1328. X            Result = FindFirst(pat[i], Anchor);
  1329. X#endif
  1330. X        domatchend = TRUE;
  1331. X        foundone = FALSE;
  1332. X        while (Result == 0)
  1333. X        {
  1334. X            if (!files_only || Anchor->ap_Info.fib_DirEntryType < 0)
  1335. X            {
  1336. X                (*num_file)++;
  1337. X                if (insfile(Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0))
  1338. X                {
  1339. XOUT_OF_MEMORY:
  1340. X                    errmsg = "Out of memory";
  1341. X                    goto Return;
  1342. X                }
  1343. X                foundone = TRUE;
  1344. X            }
  1345. X#ifndef NO_ARP
  1346. X            if (dos2)
  1347. X#endif
  1348. X                Result = MatchNext(Anchor);
  1349. X#ifndef NO_ARP
  1350. X            else
  1351. X                Result = FindNext(Anchor);
  1352. X#endif
  1353. X        }
  1354. X        if (Result == ERROR_BUFFER_OVERFLOW)
  1355. X        {
  1356. X            errmsg = "ANCHOR_BUF_SIZE too small.";
  1357. X            goto Return;
  1358. X        }
  1359. X        if (!foundone)
  1360. X        {
  1361. X            if (list_notfound)    /* put object with error in list */
  1362. X            {
  1363. X                (*num_file)++;
  1364. X                if (insfile(pat[i], FALSE))
  1365. X                    goto OUT_OF_MEMORY;
  1366. X            }
  1367. X            else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
  1368. X            {
  1369. X                errmsg = "I/O ERROR";
  1370. X                goto Return;
  1371. X            }
  1372. X        }
  1373. X#ifndef NO_ARP
  1374. X        if (dos2)
  1375. X#endif
  1376. X            MatchEnd(Anchor);
  1377. X#ifndef NO_ARP
  1378. X        else
  1379. X        {
  1380. X            FreeAnchorChain(Anchor);
  1381. X            Anchor = NULL;            /* is this right or wrong? */
  1382. X        }
  1383. X#endif
  1384. X        domatchend = FALSE;
  1385. X    }
  1386. X
  1387. X    p = namelist;
  1388. X    if (p)
  1389. X    {
  1390. X        *file = (char **) malloc(sizeof(char *) * (*num_file));
  1391. X        if (*file == NULL)
  1392. X            goto OUT_OF_MEMORY;
  1393. X        for (i = *num_file - 1; p; p = p->next, --i)
  1394. X        {
  1395. X            (*file)[i] = (char *) malloc(strlen(p->name) + 1);
  1396. X            if ((*file)[i] == NULL)
  1397. X                goto OUT_OF_MEMORY;
  1398. X            strcpy((*file)[i], p->name);
  1399. X        }
  1400. X        qsort((void *)*file, (size_t)*num_file, sizeof(char *), sortcmp);
  1401. X    }
  1402. XReturn:
  1403. X    if (domatchend)
  1404. X    {
  1405. X#ifndef NO_ARP
  1406. X        if (dos2)
  1407. X#endif
  1408. X            MatchEnd(Anchor);
  1409. X#ifndef NO_ARP
  1410. X        else
  1411. X        {
  1412. X            FreeAnchorChain(Anchor);
  1413. X            Anchor = NULL;            /* is this right or wrong? */
  1414. X        }
  1415. X#endif
  1416. X    }
  1417. X    if (Anchor)
  1418. X        free(Anchor);
  1419. X    freefiles();
  1420. X    if (errmsg)
  1421. X    {
  1422. X        emsg(errmsg);
  1423. X        *num_file = 0;
  1424. X        return 1;
  1425. X    }
  1426. X    return 0;
  1427. X}
  1428. X
  1429. X    void
  1430. XFreeWild(num, file)
  1431. X    int        num;
  1432. X    char    **file;
  1433. X{
  1434. X    if (file == NULL || num == 0)
  1435. X        return;
  1436. X    while (num--)
  1437. X        free(file[num]);
  1438. X    free(file);
  1439. X}
  1440. X
  1441. X    int
  1442. Xhas_wildcard(p)
  1443. X    char *p;
  1444. X{
  1445. X    for ( ; *p; ++p)
  1446. X        if (strchr("*?[(~#", *p) != NULL)
  1447. X            return 1;
  1448. X    return 0;
  1449. X}
  1450. X
  1451. X/*
  1452. X * With 2.0 support for reading local environment variables
  1453. X */
  1454. X
  1455. X    char *
  1456. Xvimgetenv(var)
  1457. X    char *var;
  1458. X{
  1459. X  int len;
  1460. X
  1461. X#ifndef NO_ARP
  1462. X  if (!dos2)
  1463. X        return getenv(var);
  1464. X#endif
  1465. X
  1466. X  len = GetVar((UBYTE *)var, (UBYTE *)IObuff, (long)(IOSIZE - 1), (long)0);
  1467. X
  1468. X  if (len == -1)
  1469. X      return NULL;
  1470. X  else
  1471. X      return IObuff;
  1472. X}
  1473. END_OF_FILE
  1474. if test 30444 -ne `wc -c <'vim/src/amiga.c'`; then
  1475.     echo shar: \"'vim/src/amiga.c'\" unpacked with wrong size!
  1476. fi
  1477. chmod +x 'vim/src/amiga.c'
  1478. # end of 'vim/src/amiga.c'
  1479. fi
  1480. if test -f 'vim/src/buffers.c' -a "${1}" != "-c" ; then 
  1481.   echo shar: Will not clobber existing file \"'vim/src/buffers.c'\"
  1482. else
  1483. echo shar: Extracting \"'vim/src/buffers.c'\" \(29561 characters\)
  1484. sed "s/^X//" >'vim/src/buffers.c' <<'END_OF_FILE'
  1485. X/* vi:ts=4:sw=4
  1486. X *
  1487. X * VIM - Vi IMproved
  1488. X *
  1489. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  1490. X *                            Tim Thompson            twitch!tjt
  1491. X *                            Tony Andrews            onecom!wldrdg!tony 
  1492. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  1493. X */
  1494. X
  1495. X/*
  1496. X * buffers.c
  1497. X *
  1498. X * manipulations with redo buffer and stuff buffer
  1499. X */
  1500. X
  1501. X#include "vim.h"
  1502. X#include "globals.h"
  1503. X#include "proto.h"
  1504. X#include "param.h"
  1505. X
  1506. X/*
  1507. X * structure used to store one block of the stuff/redo/macro buffers
  1508. X */
  1509. Xstruct bufblock
  1510. X{
  1511. X        struct bufblock *b_next;        /* pointer to next bufblock */
  1512. X        u_char            b_str[1];        /* contents (actually longer) */
  1513. X};
  1514. X
  1515. X#define MINIMAL_SIZE 20                 /* minimal size for b_str */
  1516. X
  1517. X/*
  1518. X * header used for the stuff buffer and the redo buffer
  1519. X */
  1520. Xstruct buffheader
  1521. X{
  1522. X        struct bufblock bh_first;        /* first (dummy) block of list */
  1523. X        struct bufblock *bh_curr;        /* bufblock for appending */
  1524. X        int             bh_index;        /* index for reading */
  1525. X        int             bh_space;        /* space in bh_curr for appending */
  1526. X};
  1527. X
  1528. Xstatic struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
  1529. Xstatic struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
  1530. Xstatic struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
  1531. X
  1532. X    /*
  1533. X     * when block_redo is TRUE redo buffer will not be changed
  1534. X     * used by edit() to repeat insertions and 'V' command for redoing
  1535. X     */
  1536. Xstatic int        block_redo = FALSE;
  1537. X
  1538. X/*
  1539. X * structure used for mapping
  1540. X */
  1541. Xstruct mapblock
  1542. X{
  1543. X    struct mapblock *m_next;        /* next mapblock */
  1544. X    char            *m_keys;        /* mapped from */
  1545. X    int                 m_keylen;        /* strlen(m_keys) */
  1546. X    char            *m_str;         /* mapped to */
  1547. X    int              m_mode;        /* valid mode */
  1548. X    int                 m_noremap;        /* if non-zero no re-mapping for m_str */
  1549. X};
  1550. X
  1551. Xstatic struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
  1552. X                                    /* first dummy entry in maplist */
  1553. X
  1554. X/*
  1555. X * variables used by vgetorpeek() and flush_buffers()
  1556. X *
  1557. X * typestr contains all characters that are not consumed yet.
  1558. X * The part in front may contain the result of mappings and @a commands.
  1559. X * The lenght of this part is typemaplen.
  1560. X * After it are characters that come from the terminal.
  1561. X * Some parts of typestr may not be mapped. These parts are remembered in
  1562. X * the noremaplist. 
  1563. X */
  1564. X#define MAXMAPLEN 50                /* maximum length of key sequence to be mapped */
  1565. X                                    /* must be able to hold an Amiga resize report */
  1566. Xstatic char        *typestr = NULL;    /* NUL-terminated buffer for typeahead characters */
  1567. Xstatic char        typebuf[MAXMAPLEN + 3]; /* initial typestr */
  1568. X
  1569. Xstatic int        typemaplen = 0;        /* number of mapped characters in typestr */
  1570. X
  1571. X/* 
  1572. X * parts int typestr that should not be mapped are remembered with a list
  1573. X * of noremap structs. Noremaplist is the first.
  1574. X */
  1575. Xstruct noremap
  1576. X{
  1577. X    int                nr_off;            /* offset to not remappable chars */
  1578. X    int                nr_len;            /* number of not remappable chars */
  1579. X    struct noremap    *nr_next;        /* next entry in the list */
  1580. X};
  1581. X
  1582. Xstatic struct noremap noremaplist = {0, 0, NULL};
  1583. X
  1584. Xstatic void        free_buff __ARGS((struct buffheader *));
  1585. Xstatic u_char    *get_bufcont __ARGS((struct buffheader *, int));
  1586. Xstatic void        add_buff __ARGS((struct buffheader *, char *));
  1587. Xstatic void        add_num_buff __ARGS((struct buffheader *, long));
  1588. Xstatic void        add_char_buff __ARGS((struct buffheader *, int));
  1589. Xstatic u_char    read_stuff __ARGS((int));
  1590. Xstatic int        start_stuff __ARGS((void));
  1591. Xstatic int        read_redo __ARGS((int));
  1592. Xstatic void        gotchars __ARGS((char *, int));
  1593. Xstatic void        init_typestr __ARGS((void));
  1594. Xstatic u_char    vgetorpeek __ARGS((int));
  1595. Xstatic void        showmap __ARGS((struct mapblock *));
  1596. X
  1597. X/*
  1598. X * free and clear a buffer
  1599. X */
  1600. X    static void
  1601. Xfree_buff(buf)
  1602. X    struct buffheader *buf;
  1603. X{
  1604. X        register struct bufblock *p, *np;
  1605. X
  1606. X        for (p = buf->bh_first.b_next; p != NULL; p = np)
  1607. X        {
  1608. X                np = p->b_next;
  1609. X                free((char *)p);
  1610. X        }
  1611. X        buf->bh_first.b_next = NULL;
  1612. X}
  1613. X
  1614. X/*
  1615. X * return the contents of a buffer as a single string
  1616. X */
  1617. X    static u_char *
  1618. Xget_bufcont(buffer, dozero)
  1619. X    struct buffheader    *buffer;
  1620. X    int                    dozero;        /* count == zero is not an error */
  1621. X{
  1622. X        u_long            count = 0;
  1623. X        u_char            *p = NULL;
  1624. X        struct bufblock    *bp;
  1625. X
  1626. X/* compute the total length of the string */
  1627. X        for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  1628. X                count += strlen((char *)bp->b_str);
  1629. X
  1630. X        if ((count || dozero) && (p = (u_char *)lalloc(count + 1, TRUE)) != NULL)
  1631. X        {
  1632. X                *p = NUL;
  1633. X                for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
  1634. X                        strcat((char *)p, (char *)bp->b_str);
  1635. X        }
  1636. X        return (p);
  1637. X}
  1638. X
  1639. X/*
  1640. X * return the contents of the record buffer as a single string
  1641. X *    and clear the record buffer
  1642. X */
  1643. X    u_char *
  1644. Xget_recorded()
  1645. X{
  1646. X    u_char *p;
  1647. X
  1648. X    p = get_bufcont(&recordbuff, TRUE);
  1649. X    free_buff(&recordbuff);
  1650. X    return (p);
  1651. X}
  1652. X
  1653. X/*
  1654. X * return the contents of the redo buffer as a single string
  1655. X */
  1656. X    u_char *
  1657. Xget_inserted()
  1658. X{
  1659. X        return(get_bufcont(&redobuff, FALSE));
  1660. X}
  1661. X
  1662. X/*
  1663. X * add string "s" after the current block of buffer "buf"
  1664. X */
  1665. X    static void
  1666. Xadd_buff(buf, s)
  1667. X    register struct buffheader    *buf;
  1668. X    char                        *s;
  1669. X{
  1670. X    struct bufblock *p;
  1671. X    u_long             n;
  1672. X    u_long             len;
  1673. X
  1674. X    if ((n = strlen(s)) == 0)                /* don't add empty strings */
  1675. X        return;
  1676. X
  1677. X    if (buf->bh_first.b_next == NULL)        /* first add to list */
  1678. X    {
  1679. X        buf->bh_space = 0;
  1680. X        buf->bh_curr = &(buf->bh_first);
  1681. X    }
  1682. X    else if (buf->bh_curr == NULL)            /* buffer has already been read */
  1683. X    {
  1684. X        emsg("Add to read buffer");
  1685. X        return;
  1686. X    }
  1687. X    else if (buf->bh_index != 0)
  1688. X        strcpy((char *)buf->bh_first.b_next->b_str, (char *)buf->bh_first.b_next->b_str + buf->bh_index);
  1689. X    buf->bh_index = 0;
  1690. X
  1691. X    if (buf->bh_space >= n)
  1692. X    {
  1693. X        strcat((char *)buf->bh_curr->b_str, s);
  1694. X        buf->bh_space -= n;
  1695. X    }
  1696. X    else
  1697. X    {
  1698. X        if (n < MINIMAL_SIZE)
  1699. X            len = MINIMAL_SIZE;
  1700. X        else
  1701. X            len = n;
  1702. X        p = (struct bufblock *)lalloc((u_long)(sizeof(struct bufblock) + len), TRUE);
  1703. X        if (p == NULL)
  1704. X            return; /* no space, just forget it */
  1705. X        buf->bh_space = len - n;
  1706. X        strcpy((char *)p->b_str, s);
  1707. X
  1708. X        p->b_next = buf->bh_curr->b_next;
  1709. X        buf->bh_curr->b_next = p;
  1710. X        buf->bh_curr = p;
  1711. X    }
  1712. X    return;
  1713. X}
  1714. X
  1715. X    static void
  1716. Xadd_num_buff(buf, n)
  1717. X    struct buffheader *buf;
  1718. X    long               n;
  1719. X{
  1720. X        char    number[32];
  1721. X
  1722. X        sprintf(number, "%ld", n);
  1723. X        add_buff(buf, number);
  1724. X}
  1725. X
  1726. X    static void
  1727. Xadd_char_buff(buf, c)
  1728. X    struct buffheader *buf;
  1729. X    int               c;
  1730. X{
  1731. X        char    temp[2];
  1732. X
  1733. X        temp[0] = c;
  1734. X        temp[1] = NUL;
  1735. X        add_buff(buf, temp);
  1736. X}
  1737. X
  1738. X/*
  1739. X * get one character from the stuff buffer
  1740. X * If advance == TRUE go to the next char.
  1741. X */
  1742. X    static u_char
  1743. Xread_stuff(advance)
  1744. X    int            advance;
  1745. X{
  1746. X        register u_char c;
  1747. X        register struct bufblock *curr;
  1748. X
  1749. X
  1750. X        if (stuffbuff.bh_first.b_next == NULL)    /* buffer is empty */
  1751. X            return NUL;
  1752. X
  1753. X        curr = stuffbuff.bh_first.b_next;
  1754. X        c = curr->b_str[stuffbuff.bh_index];
  1755. X
  1756. X        if (advance)
  1757. X        {
  1758. X            if (curr->b_str[++stuffbuff.bh_index] == NUL)
  1759. X            {
  1760. X                stuffbuff.bh_first.b_next = curr->b_next;
  1761. X                free((char *)curr);
  1762. X                stuffbuff.bh_index = 0;
  1763. X            }
  1764. X        }
  1765. X        return c;
  1766. X}
  1767. X
  1768. X/*
  1769. X * prepare stuff buffer for reading (if it contains something)
  1770. X */
  1771. X    static int
  1772. Xstart_stuff()
  1773. X{
  1774. X    if (stuffbuff.bh_first.b_next == NULL)
  1775. X        return FALSE;
  1776. X    stuffbuff.bh_curr = &(stuffbuff.bh_first);
  1777. X    stuffbuff.bh_space = 0;
  1778. X    return TRUE;
  1779. X}
  1780. X
  1781. X/*
  1782. X * check if the stuff buffer is empty
  1783. X */
  1784. X    int
  1785. Xstuff_empty()
  1786. X{
  1787. X    return (stuffbuff.bh_first.b_next == NULL);
  1788. X}
  1789. X
  1790. X/*
  1791. X * Remove the contents of the stuff buffer and the mapped characters in the
  1792. X * typeahead buffer (used in case of an error). If 'typeahead' is true,
  1793. X * flush all typeahead characters (used when interrupted by a CTRL-C).
  1794. X */
  1795. X    void
  1796. Xflush_buffers(typeahead)
  1797. X    int typeahead;
  1798. X{
  1799. X    struct noremap *p;
  1800. X
  1801. X    init_typestr();
  1802. X
  1803. X    start_stuff();
  1804. X    while (read_stuff(TRUE) != NUL)
  1805. X        ;
  1806. X
  1807. X    if (typeahead)            /* remove all typeahead */
  1808. X    {
  1809. X            /*
  1810. X             * We have to get all characters, because we may delete the first
  1811. X             * part of an escape sequence.
  1812. X             * In an xterm we get one char at a time and we have to get them all.
  1813. X             */
  1814. X        while (inchar(typestr, MAXMAPLEN, 10))    
  1815. X            ;
  1816. X        *typestr = NUL;
  1817. X    }
  1818. X    else                    /* remove mapped characters only */
  1819. X        strcpy(typestr, typestr + typemaplen);
  1820. X    typemaplen = 0;
  1821. X    noremaplist.nr_len = 0;
  1822. X    noremaplist.nr_off = 0;
  1823. X    while (noremaplist.nr_next)
  1824. X    {
  1825. X        p = noremaplist.nr_next->nr_next;
  1826. X        free(noremaplist.nr_next);
  1827. X        noremaplist.nr_next = p;
  1828. X    }
  1829. X}
  1830. X
  1831. X    void
  1832. XResetRedobuff()
  1833. X{
  1834. X    if (!block_redo)
  1835. X        free_buff(&redobuff);
  1836. X}
  1837. X
  1838. X    void
  1839. XAppendToRedobuff(s)
  1840. X    char           *s;
  1841. X{
  1842. X    if (!block_redo)
  1843. X        add_buff(&redobuff, s);
  1844. X}
  1845. X
  1846. X    void
  1847. XAppendCharToRedobuff(c)
  1848. X    int               c;
  1849. X{
  1850. X    if (!block_redo)
  1851. X        add_char_buff(&redobuff, c);
  1852. X}
  1853. X
  1854. X    void
  1855. XAppendNumberToRedobuff(n)
  1856. X    long             n;
  1857. X{
  1858. X    if (!block_redo)
  1859. X        add_num_buff(&redobuff, n);
  1860. X}
  1861. X
  1862. X    void
  1863. XstuffReadbuff(s)
  1864. X    char           *s;
  1865. X{
  1866. X    add_buff(&stuffbuff, s);
  1867. X}
  1868. X
  1869. X    void
  1870. XstuffcharReadbuff(c)
  1871. X    int               c;
  1872. X{
  1873. X    add_char_buff(&stuffbuff, c);
  1874. X}
  1875. X
  1876. X    void
  1877. XstuffnumReadbuff(n)
  1878. X    long    n;
  1879. X{
  1880. X    add_num_buff(&stuffbuff, n);
  1881. X}
  1882. X
  1883. X/*
  1884. X * Read a character from the redo buffer.
  1885. X * The redo buffer is left as it is.
  1886. X */
  1887. X    static int
  1888. Xread_redo(init)
  1889. X    int            init;
  1890. X{
  1891. X    static struct bufblock    *bp;
  1892. X    static u_char            *p;
  1893. X    int                        c;
  1894. X
  1895. X    if (init)
  1896. X    {
  1897. X        if ((bp = redobuff.bh_first.b_next) == NULL)
  1898. X            return TRUE;
  1899. X        p = bp->b_str;
  1900. X        return FALSE;
  1901. X    }
  1902. X    if ((c = *p) != NUL)
  1903. X    {
  1904. X        if (*++p == NUL && bp->b_next != NULL)
  1905. X        {
  1906. X            bp = bp->b_next;
  1907. X            p = bp->b_str;
  1908. X        }
  1909. X    }
  1910. X    return c;
  1911. X}
  1912. X
  1913. X/*
  1914. X * copy the rest of the redo buffer into the stuff buffer (could be done faster)
  1915. X */
  1916. X    void
  1917. Xcopy_redo()
  1918. X{
  1919. X    register int c;
  1920. X
  1921. X    while ((c = read_redo(FALSE)) != NUL)
  1922. X        stuffcharReadbuff(c);
  1923. X}
  1924. X
  1925. Xextern int redo_Visual_busy;        /* this is in normal.c */
  1926. X
  1927. X/*
  1928. X * Stuff the redo buffer into the stuffbuff.
  1929. X * Insert the redo count into the command.
  1930. X */
  1931. X    int
  1932. Xstart_redo(count)
  1933. X    long count;
  1934. X{
  1935. X    register int c;
  1936. X
  1937. X    if (read_redo(TRUE))    /* init the pointers; return if nothing to redo */
  1938. X        return FALSE;
  1939. X
  1940. X    c = read_redo(FALSE);
  1941. X
  1942. X/* copy the buffer name, if present */
  1943. X    if (c == '"')
  1944. X    {
  1945. X        add_buff(&stuffbuff, "\"");
  1946. X        c = read_redo(FALSE);
  1947. X
  1948. X/* if a numbered buffer is used, increment the number */
  1949. X        if (c >= '1' && c < '9')
  1950. X            ++c;
  1951. X        add_char_buff(&stuffbuff, c);
  1952. X        c = read_redo(FALSE);
  1953. X    }
  1954. X
  1955. X    if (c == 'v')    /* redo Visual */
  1956. X    {
  1957. X        Visual = Curpos;
  1958. X        redo_Visual_busy = TRUE;
  1959. X        c = read_redo(FALSE);
  1960. X    }
  1961. X
  1962. X/* try to enter the count (in place of a previous count) */
  1963. X    if (count)
  1964. X    {
  1965. X        while (isdigit(c))        /* skip "old" count */
  1966. X            c = read_redo(FALSE);
  1967. X        add_num_buff(&stuffbuff, count);
  1968. X    }
  1969. X
  1970. X/* copy from the redo buffer into the stuff buffer */
  1971. X    add_char_buff(&stuffbuff, c);
  1972. X    copy_redo();
  1973. X    return TRUE;
  1974. X}
  1975. X
  1976. X/*
  1977. X * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
  1978. X * the redo buffer into the stuffbuff.
  1979. X */
  1980. X    int
  1981. Xstart_redo_ins()
  1982. X{
  1983. X    register u_char c;
  1984. X
  1985. X    if (read_redo(TRUE))
  1986. X        return FALSE;
  1987. X    start_stuff();
  1988. X
  1989. X/* skip the count and the command character */
  1990. X    while ((c = read_redo(FALSE)) != NUL)
  1991. X    {
  1992. X        c = TO_UPPER(c);
  1993. X        if (strchr("AIRO", c) != NULL)
  1994. X        {
  1995. X            if (c == 'O')
  1996. X                stuffReadbuff(NL_STR);
  1997. X            break;
  1998. X        }
  1999. X    }
  2000. X
  2001. X/* copy the typed text from the redo buffer into the stuff buffer */
  2002. X    copy_redo();
  2003. X    block_redo = TRUE;
  2004. X    return TRUE;
  2005. X}
  2006. X
  2007. X    void
  2008. Xset_redo_ins()
  2009. X{
  2010. X    block_redo = TRUE;
  2011. X}
  2012. X
  2013. X    void
  2014. Xstop_redo_ins()
  2015. X{
  2016. X    block_redo = FALSE;
  2017. X}
  2018. X
  2019. X/*
  2020. X * insert a string in front of the typeahead buffer (for '@' command and vgetorpeek)
  2021. X */
  2022. X    int
  2023. Xins_typestr(str, noremap)
  2024. X    char    *str;
  2025. X    int        noremap;
  2026. X{
  2027. X    register char    *s;
  2028. X    register int    newlen;
  2029. X    register int    addlen;
  2030. X
  2031. X    init_typestr();
  2032. X
  2033. X    /*
  2034. X     * In typestr there must always be room for MAXMAPLEN + 3 characters
  2035. X     */
  2036. X    addlen = strlen(str);
  2037. X    newlen = strlen(typestr) + addlen + MAXMAPLEN + 3;
  2038. X    if (newlen < 0)                /* string is getting too long */
  2039. X    {
  2040. X        emsg(e_toocompl);        /* also calls flush_buffers */
  2041. X        setcursor();
  2042. X        return -1;
  2043. X    }
  2044. X    s = alloc(newlen);
  2045. X    if (s == NULL)                /* out of memory */
  2046. X        return -1;
  2047. X
  2048. X    strcpy(s, str);
  2049. X    strcat(s, typestr);
  2050. X    if (typestr != typebuf)
  2051. X        free(typestr);
  2052. X    typestr = s;
  2053. X    typemaplen += addlen;        /* the inserted string is not typed */
  2054. X    if (noremap)
  2055. X    {
  2056. X        if (noremaplist.nr_off == 0)
  2057. X            noremaplist.nr_len += addlen;
  2058. X        else
  2059. X        {
  2060. X            struct noremap *p;
  2061. X
  2062. X            p = (struct noremap *)alloc((int)sizeof(struct noremap));
  2063. X            if (p != NULL)
  2064. X            {
  2065. X                p->nr_next = noremaplist.nr_next;
  2066. X                p->nr_off = noremaplist.nr_off;
  2067. X                p->nr_len = noremaplist.nr_len;
  2068. X                noremaplist.nr_next = p;
  2069. X                noremaplist.nr_len = addlen;
  2070. X                noremaplist.nr_off = 0;
  2071. X            }
  2072. X        }
  2073. X    }
  2074. X    else if (noremaplist.nr_len)
  2075. X        noremaplist.nr_off += addlen;
  2076. X    return 0;
  2077. X}
  2078. X
  2079. X/*
  2080. X * remove "len" characters from the front of typestr
  2081. X */
  2082. X    void
  2083. Xdel_typestr(len)
  2084. X    int    len;
  2085. X{
  2086. X    struct noremap *p;
  2087. X
  2088. X    strcpy(typestr, typestr + len);        /* remove chars from the buffer */
  2089. X    if ((typemaplen -= len) <= 0)        /* adjust typemaplen */
  2090. X        typemaplen = 0;
  2091. X    while (len)                            /* adjust noremaplist */
  2092. X    {
  2093. X        if (noremaplist.nr_off >= len)
  2094. X        {
  2095. X            noremaplist.nr_off -= len;
  2096. X            break;
  2097. X        }
  2098. X        len -= noremaplist.nr_off;
  2099. X        noremaplist.nr_off = 0;
  2100. X        if (noremaplist.nr_len > len)
  2101. X        {
  2102. X            noremaplist.nr_len -= len;
  2103. X            break;
  2104. X        }
  2105. X        len -= noremaplist.nr_len;
  2106. X        p = noremaplist.nr_next;
  2107. X        if (p == NULL)
  2108. X        {
  2109. X            noremaplist.nr_len = 0;
  2110. X            break;
  2111. X        }
  2112. X        noremaplist.nr_next = p->nr_next;
  2113. X        noremaplist.nr_len = p->nr_len;
  2114. X        noremaplist.nr_off = p->nr_off;
  2115. X        free(p);
  2116. X    }
  2117. X}
  2118. X
  2119. Xextern int arrow_used;            /* this is in edit.c */
  2120. X
  2121. X/*
  2122. X * Write typed characters to script file.
  2123. X * If recording is on put the character in the recordbuffer.
  2124. X */
  2125. X    static void
  2126. Xgotchars(s, len)
  2127. X    char    *s;
  2128. X    int        len;
  2129. X{
  2130. X    while (len--)
  2131. X    {
  2132. X        updatescript(*s & 255);
  2133. X
  2134. X        if (Recording)
  2135. X            add_char_buff(&recordbuff, (*s & 255));
  2136. X        ++s;
  2137. X    }
  2138. X
  2139. X            /* do not sync in insert mode, unless cursor key has been used */
  2140. X    if (!(State & (INSERT + CMDLINE)) || arrow_used)        
  2141. X        u_sync();
  2142. X}
  2143. X
  2144. X/*
  2145. X * Initialize typestr to point to typebuf.
  2146. X * Alloc() cannot be used here: In out-of-memory situations it would
  2147. X * be impossible to type anything.
  2148. X */
  2149. X    static void
  2150. Xinit_typestr()
  2151. X{
  2152. X    if (typestr == NULL)
  2153. X    {
  2154. X        typestr = typebuf;
  2155. X        typebuf[0] = NUL;
  2156. X    }
  2157. X}
  2158. X
  2159. X#define NEEDMORET 9999        /* value for incomplete mapping or key-code */
  2160. X
  2161. X/*
  2162. X * get a character: 1. from the stuffbuffer
  2163. X *                    2. from the typeahead buffer
  2164. X *                    3. from the user
  2165. X *
  2166. X * KeyTyped is set to TRUE in the case the user typed the key.
  2167. X * If advance is TRUE, we really get the character. Otherwise we just look
  2168. X * whether there is a character available.
  2169. X */
  2170. X    static u_char
  2171. Xvgetorpeek(advance)
  2172. X    int        advance;
  2173. X{
  2174. X    register int    c;
  2175. X    int                n = 0;        /* init for GCC */
  2176. X    int                len;
  2177. X#ifdef AMIGA
  2178. X    char            *s;
  2179. X#endif
  2180. X    register struct mapblock *mp;
  2181. X    int                timedout = FALSE;    /* waited for more than 1 second
  2182. X                                                for mapping to complete */
  2183. X    int                mapdepth = 0;        /* check for recursive mapping */
  2184. X    int                mode_deleted = FALSE;    /* set when mode has been deleted */
  2185. X
  2186. X    init_typestr();
  2187. X    start_stuff();
  2188. X    if (typemaplen == 0)
  2189. X        Exec_reg = FALSE;
  2190. X    do
  2191. X    {
  2192. X        c = read_stuff(advance);
  2193. X        if (c != NUL && !got_int)
  2194. X            KeyTyped = FALSE;
  2195. X        else
  2196. X        {
  2197. X            /*
  2198. X             * Loop until we either find a matching mapped key, or we
  2199. X             * are sure that it is not a mapped key.
  2200. X             * If a mapped key sequence is found we go back to the start to
  2201. X             * try re-mapping.
  2202. X             */
  2203. X
  2204. X            for (;;)
  2205. X            {
  2206. X                len = strlen(typestr);
  2207. X                breakcheck();                /* check for CTRL-C */
  2208. X                if (got_int)
  2209. X                {
  2210. X                    c = inchar(typestr, MAXMAPLEN, 0);    /* flush all input */
  2211. X                    /*
  2212. X                     * If inchar returns TRUE (script file was active) or we are
  2213. X                     * inside a mapping, get out of insert mode.
  2214. X                     * Otherwise we behave like having gotten a CTRL-C.
  2215. X                     * As a result typing CTRL-C in insert mode will
  2216. X                     * really insert a CTRL-C.
  2217. X                     */
  2218. X                    if ((c || typemaplen) && (State & (INSERT + CMDLINE)))
  2219. X                        c = ESC;
  2220. X                    else
  2221. X                        c = Ctrl('C');
  2222. X                    flush_buffers(TRUE);        /* flush all typeahead */
  2223. X                    break;
  2224. X                }
  2225. X                else if (len > 0)    /* see if we have a mapped key sequence */
  2226. X                {
  2227. X                    /*
  2228. X                     * walk through the maplist until we find an
  2229. X                     * entry that matches (if not timed out).
  2230. X                     */
  2231. X                    mp = NULL;
  2232. X                    if (!timedout && (typemaplen == 0 || (p_remap &&
  2233. X                            (noremaplist.nr_len == 0 || noremaplist.nr_off != 0)))
  2234. X                            && !((State & (INSERT + CMDLINE)) && p_paste))
  2235. X                    {
  2236. X                        for (mp = maplist.m_next; mp; mp = mp->m_next)
  2237. X                        {
  2238. X                            if ((mp->m_mode & ABBREV) || !(mp->m_mode & State))
  2239. X                                continue;
  2240. X                            n = mp->m_keylen;
  2241. X                            if (noremaplist.nr_off != 0 && n > noremaplist.nr_off)
  2242. X                                continue;
  2243. X                            if (!strncmp(mp->m_keys, typestr, (size_t)(n > len ? len : n)))
  2244. X                                break;
  2245. X                        }
  2246. X                    }
  2247. X                    if (mp == NULL)                    /* no match found */
  2248. X                    {
  2249. X                            /*
  2250. X                             * check if we have a terminal code, when
  2251. X                             *    mapping is allowed,
  2252. X                             *  keys have not been mapped,
  2253. X                             *    and not an ESC sequence, not in insert mode or
  2254. X                             *        p_ek is on,
  2255. X                             *    and when not timed out,
  2256. X                             */
  2257. X                        if (State != NOMAPPING &&
  2258. X                                typemaplen == 0 &&
  2259. X                                (typestr[0] != ESC || p_ek || !(State & INSERT)) &&
  2260. X                                !timedout)
  2261. X                            n = check_termcode(typestr);
  2262. X                        else
  2263. X                            n = 0;
  2264. X                        if (n == 0)        /* no matching terminal code */
  2265. X                        {
  2266. X#ifdef AMIGA                    /* check for window bounds report */
  2267. X                            if (typemaplen == 0 && (typestr[0] & 0xff) == CSI)
  2268. X                            {
  2269. X                                for (s = typestr + 1; isdigit(*s) || *s == ';' || *s == ' '; ++s)
  2270. X                                    ;
  2271. X                                if (*s == 'r' || *s == '|')    /* found one */
  2272. X                                {
  2273. X                                    strcpy(typestr, s + 1);
  2274. X                                    set_winsize(0, 0, FALSE);        /* get size and redraw screen */
  2275. X                                    continue;
  2276. X                                }
  2277. X                                if (*s == NUL)        /* need more characters */
  2278. X                                    n = -1;
  2279. X                            }
  2280. X                            if (n != -1)            /* got a single character */
  2281. X#endif
  2282. X                            {
  2283. X                                c = typestr[0] & 255;
  2284. X                                if (typemaplen)
  2285. X                                    KeyTyped = FALSE;
  2286. X                                else
  2287. X                                {
  2288. X                                    KeyTyped = TRUE;
  2289. X                                    if (advance)    /* write char to script file(s) */
  2290. X                                        gotchars(typestr, 1);
  2291. X                                }
  2292. X                                if (advance)        /* remove chars from typestr */
  2293. X                                    del_typestr(1);
  2294. X                                break;        /* got character, break for loop */
  2295. X                            }
  2296. X                        }
  2297. X                        if (n > 0)        /* full matching terminal code */
  2298. X                            continue;    /* try mapping again */
  2299. X
  2300. X                        /* partial match: get some more characters */
  2301. X                        n = NEEDMORET;
  2302. X                    }
  2303. X                    if (n <= len)        /* complete match */
  2304. X                    {
  2305. X                        if (n > typemaplen)        /* write chars to script file(s) */
  2306. X                            gotchars(typestr + typemaplen, n - typemaplen);
  2307. X
  2308. X                        del_typestr(n);    /* remove the mapped keys */
  2309. X
  2310. X                        /*
  2311. X                         * Put the replacement string in front of mapstr.
  2312. X                         * The depth check catches ":map x y" and ":map y x".
  2313. X                         */
  2314. X                        if (++mapdepth == 1000)
  2315. X                        {
  2316. X                            emsg("recursive mapping");
  2317. X                            if (State == CMDLINE)
  2318. X                                redrawcmdline();
  2319. X                            else
  2320. X                                setcursor();
  2321. X                            flush_buffers(FALSE);
  2322. X                            mapdepth = 0;        /* for next one */
  2323. X                            c = -1;
  2324. X                            break;
  2325. X                        }
  2326. X                        if (ins_typestr(mp->m_str, mp->m_noremap) < 0)
  2327. X                        {
  2328. X                            c = -1;
  2329. X                            break;
  2330. X                        }
  2331. X                        continue;
  2332. X                    }
  2333. X                }
  2334. X                /*
  2335. X                 * special case: if we get an <ESC> in insert mode and there are
  2336. X                 * no more characters at once, we pretend to go out of insert mode.
  2337. X                 * This prevents the one second delay after typing an <ESC>.
  2338. X                 * If we get something after all, we may have to redisplay the
  2339. X                 * mode. That the cursor is in the wrong place does not matter.
  2340. X                 */
  2341. X                c = 0;
  2342. X                if (advance && len == 1 && typestr[0] == ESC && typemaplen == 0 && (State & INSERT) && (p_timeout || (n == NEEDMORET && p_ttimeout)) && (c = inchar(typestr + len, 2, 0)) == 0)
  2343. X                {
  2344. X                    if (p_smd)
  2345. X                    {
  2346. X                        delmode();
  2347. X                        mode_deleted = TRUE;
  2348. X                    }
  2349. X                    if (Curscol)        /* move cursor one left if possible */
  2350. X                        --Curscol;
  2351. X                    else if (p_wrap && Curpos.col != 0 && Cursrow)
  2352. X                    {
  2353. X                            --Cursrow;
  2354. X                            Curscol = Columns - 1;
  2355. X                    }
  2356. X                    setcursor();
  2357. X                    flushbuf();
  2358. X                }
  2359. X                len += c;
  2360. X
  2361. X                if (len >= typemaplen + MAXMAPLEN)    /* buffer full, don't map */
  2362. X                {
  2363. X                    timedout = TRUE;
  2364. X                    continue;
  2365. X                }
  2366. X                c = inchar(typestr + len, typemaplen + MAXMAPLEN - len, !advance ? 0 : ((len == 0 || !(p_timeout || (p_ttimeout && n == NEEDMORET))) ? -1 : (int)p_tm));
  2367. X                if (c <= NUL)        /* no character available */
  2368. X                {
  2369. X                    if (!advance)
  2370. X                        break;
  2371. X                    if (len)                /* timed out */
  2372. X                    {
  2373. X                        timedout = TRUE;
  2374. X                        continue;
  2375. X                    }
  2376. X                }
  2377. X                else
  2378. X                {
  2379. X                    if (mode_deleted)        /* character entered after ESC */
  2380. X                    {
  2381. X                        showmode();
  2382. X                        mode_deleted = FALSE;
  2383. X                    }
  2384. X                }
  2385. X            }        /* for (;;) */
  2386. X        }        /* if (!character from stuffbuf) */
  2387. X
  2388. X                        /* if advance is FALSE don't loop on NULs */
  2389. X    } while (c < 0 || (advance && c == NUL));
  2390. X
  2391. X        /* delete "INSERT" message if we return an ESC */
  2392. X    if (c == ESC && p_smd && !mode_deleted && (State & INSERT))
  2393. X        delmode();
  2394. X
  2395. X    return (u_char) c;
  2396. X}
  2397. X
  2398. X    u_char
  2399. Xvgetc()
  2400. X{
  2401. X    return (vgetorpeek(TRUE));
  2402. X}
  2403. X
  2404. X    u_char
  2405. Xvpeekc()
  2406. X{
  2407. X    return (vgetorpeek(FALSE));
  2408. X}
  2409. X
  2410. X/*
  2411. X * map[!]                    : show all key mappings
  2412. X * map[!] {lhs}                : show key mapping for {lhs}
  2413. X * map[!] {lhs} {rhs}        : set key mapping for {lhs} to {rhs}
  2414. X * noremap[!] {lhs} {rhs}    : same, but no remapping for {rhs}
  2415. X * unmap[!] {lhs}            : remove key mapping for {lhs}
  2416. X * abbr                        : show all abbreviations
  2417. X * abbr {lhs}                : show abbreviations for {lhs}
  2418. X * abbr {lhs} {rhs}            : set abbreviation for {lhs} to {rhs}
  2419. X * noreabbr {lhs} {rhs}        : same, but no remapping for {rhs}
  2420. X * unabbr {lhs}                : remove abbreviation for {lhs}
  2421. X *
  2422. X * maptype == 1 for unmap command, 2 for noremap command.
  2423. X *
  2424. X * keys is pointer to any arguments.
  2425. X *
  2426. X * for :map      mode is NORMAL 
  2427. X * for :map!  mode is INSERT + CMDLINE
  2428. X * for :cmap  mode is CMDLINE
  2429. X * for :imap  mode is INSERT 
  2430. X * for :abbr  mode is INSERT + CMDLINE + ABBREV
  2431. X * for :iabbr mode is INSERT + ABBREV
  2432. X * for :cabbr mode is CMDLINE + ABBREV
  2433. X * 
  2434. X * Return 0 for success
  2435. X *          1 for invalid arguments
  2436. X *          2 for no match
  2437. X *          3 for ambiguety
  2438. X *          4 for out of mem
  2439. X */
  2440. X    int
  2441. Xdomap(maptype, keys, mode)
  2442. X    int        maptype;
  2443. X    char    *keys;
  2444. X    int        mode;
  2445. X{
  2446. X    struct mapblock        *mp, *mprev;
  2447. X    char                *arg;
  2448. X    char                *p;
  2449. X    int                    n = 0;            /* init for GCC */
  2450. X    int                    len = 0;        /* init for GCC */
  2451. X    char                *newstr;
  2452. X    int                    hasarg;
  2453. X    int                    haskey;
  2454. X    int                    did_it = FALSE;
  2455. X    int                    abbrev = 0;
  2456. X    int                    round;
  2457. X
  2458. X    if (mode & ABBREV)        /* not a mapping but an abbreviation */
  2459. X    {
  2460. X        abbrev = ABBREV;
  2461. X        mode &= ~ABBREV;
  2462. X    }
  2463. X/*
  2464. X * find end of keys and remove CTRL-Vs in it
  2465. X */
  2466. X    p = keys;
  2467. X    while (*p && *p != ' ' && *p != '\t')
  2468. X    {
  2469. X        if (*p == Ctrl('V') && p[1] != NUL)
  2470. X            strcpy(p, p + 1);            /* remove CTRL-V */
  2471. X        ++p;
  2472. X    }
  2473. X    if (*p != NUL)
  2474. X        *p++ = NUL;
  2475. X    skipspace(&p);
  2476. X    arg = p;
  2477. X    hasarg = (*arg != NUL);
  2478. X    haskey = (*keys != NUL);
  2479. X
  2480. X        /* check for :unmap with not one argument */
  2481. X    if (maptype == 1 && (!haskey || hasarg))    
  2482. X        return 1;
  2483. X
  2484. X/*
  2485. X * remove CTRL-Vs from argument
  2486. X */
  2487. X    while (*p)
  2488. X    {
  2489. X        if (*p == Ctrl('V') && p[1] != NUL)
  2490. X            strcpy(p, p + 1);            /* remove CTRL-V */
  2491. X        ++p;
  2492. X    }
  2493. X
  2494. X/*
  2495. X * check arguments and translate function keys
  2496. X */
  2497. X    if (haskey)
  2498. X    {
  2499. X        if (*keys == '#' && isdigit(*(keys + 1)))    /* function key */
  2500. X        {
  2501. X            if (*++keys == '0')
  2502. X                *(u_char *)keys = K_F10;
  2503. X            else
  2504. X                *keys += K_F1 - '1';
  2505. X        }
  2506. X        len = strlen(keys);
  2507. X        if (len > MAXMAPLEN)            /* maximum lenght of MAXMAPLEN chars */
  2508. X            return 2;
  2509. X    }
  2510. X
  2511. X    if (haskey && hasarg && abbrev)        /* will add an abbreviation */
  2512. X        no_abbr = FALSE;
  2513. X
  2514. X#ifdef AMIGA
  2515. X    if (!haskey || (maptype != 1 && !hasarg))
  2516. X        settmode(0);                /* set cooked mode so output can be halted */
  2517. X#endif
  2518. X/*
  2519. X * Find an entry in the maplist that matches.
  2520. X * For :unmap we may loop two times: once to try to unmap an entry with a
  2521. X * matching 'from' part, a second time, if the first fails, to unmap an
  2522. X * entry with a matching 'to' part. This was done to allow ":ab foo bar" to be
  2523. X * unmapped by typing ":unab foo", where "foo" will be replaced by "bar" because
  2524. X * of the abbreviation.
  2525. X */
  2526. X    for (round = 0; (round == 0 || maptype == 1) && round <= 1 && !did_it; ++round)
  2527. X    {
  2528. X        for (mp = maplist.m_next, mprev = &maplist; mp; mprev = mp, mp = mp->m_next)
  2529. X        {
  2530. X                                        /* skip entries with wrong mode */
  2531. X            if (!(mp->m_mode & mode) || (mp->m_mode & ABBREV) != abbrev)
  2532. X                continue;
  2533. X            if (!haskey)                        /* show all entries */
  2534. X            {
  2535. X                showmap(mp);
  2536. X                did_it = TRUE;
  2537. X            }
  2538. X            else                                /* do we have a match? */
  2539. X            {
  2540. X                if (round)        /* second round: try 'to' string for unmap */
  2541. X                {
  2542. X                    n = strlen(mp->m_str);
  2543. X                    p = mp->m_str;
  2544. X                }
  2545. X                else
  2546. X                {
  2547. X                    n = mp->m_keylen;
  2548. X                    p = mp->m_keys;
  2549. X                }
  2550. X                if (!strncmp(p, keys, (size_t)(n < len ? n : len)))
  2551. X                {
  2552. X                    if (maptype == 1)            /* delete entry */
  2553. X                    {
  2554. X                        if (n != len)            /* not a full match */
  2555. X                            continue;
  2556. X                        /*
  2557. X                         * We reset the indicated mode bits. If nothing is left the
  2558. X                         * entry is deleted below.
  2559. X                         */
  2560. X                        mp->m_mode &= (~mode | ABBREV);
  2561. X                        did_it = TRUE;            /* remember that we did something */
  2562. X                    }
  2563. X                    else if (!hasarg)            /* show matching entry */
  2564. X                    {
  2565. X                        showmap(mp);
  2566. X                        did_it = TRUE;
  2567. X                    }
  2568. X                    else if (n != len)            /* new entry is ambigious */
  2569. X                    {
  2570. X                        return 3;
  2571. X                    }
  2572. X                    else
  2573. X                    {
  2574. X                        mp->m_mode &= (~mode | ABBREV);        /* remove mode bits */
  2575. X                        if (!(mp->m_mode & ~ABBREV) && !did_it)    /* reuse existing entry */
  2576. X                        {
  2577. X                            newstr = strsave(arg);
  2578. X                            if (newstr == NULL)
  2579. X                                return 4;            /* no mem */
  2580. X                            free(mp->m_str);
  2581. X                            mp->m_str = newstr;
  2582. X                            mp->m_noremap = maptype;
  2583. X                            mp->m_mode = mode + abbrev;
  2584. X                            did_it = TRUE;
  2585. X                        }
  2586. X                    }
  2587. X                    if (!(mp->m_mode & ~ABBREV))        /* entry can be deleted */
  2588. X                    {
  2589. X                        free(mp->m_keys);
  2590. X                        free(mp->m_str);
  2591. X                        mprev->m_next = mp->m_next;
  2592. X                        free(mp);
  2593. X                        mp = mprev;                    /* continue with next entry */
  2594. X                    }
  2595. X                }
  2596. X            }
  2597. X        }
  2598. X    }
  2599. X
  2600. X    if (maptype == 1)                        /* delete entry */
  2601. X    {
  2602. X        if (did_it)
  2603. X            return 0;                        /* removed OK */
  2604. X        else
  2605. X            return 2;                        /* no match */
  2606. X    }
  2607. X
  2608. X    if (!haskey || !hasarg)                    /* print entries */
  2609. X    {
  2610. X#ifdef AMIGA
  2611. X        settmode(1);
  2612. X#endif
  2613. X        if (did_it)
  2614. X            wait_return(TRUE);
  2615. X        else if (abbrev)
  2616. X            msg("No abbreviation found");
  2617. X        else
  2618. X            msg("No mapping found");
  2619. X        return 0;                            /* listing finished */
  2620. X    }
  2621. X
  2622. X    if (did_it)                    /* have added the new entry already */
  2623. X        return 0;
  2624. X/*
  2625. X * get here when we have to add a new entry
  2626. X */
  2627. X        /* allocate a new entry for the maplist */
  2628. X    mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
  2629. X    if (mp == NULL)
  2630. X        return 4;            /* no mem */
  2631. X    mp->m_keys = strsave(keys);
  2632. X    mp->m_str = strsave(arg);
  2633. X    if (mp->m_keys == NULL || mp->m_str == NULL)
  2634. X    {
  2635. X            free(mp->m_keys);
  2636. X            free(mp->m_str);
  2637. X            free(mp);
  2638. X            return 4;        /* no mem */
  2639. X    }
  2640. X    mp->m_keylen = strlen(mp->m_keys);
  2641. X    mp->m_noremap = maptype;
  2642. X    mp->m_mode = mode + abbrev;
  2643. X
  2644. X    /* add the new entry in front of the maplist */
  2645. X    mp->m_next = maplist.m_next;
  2646. X    maplist.m_next = mp;
  2647. X
  2648. X    return 0;                /* added OK */
  2649. X}
  2650. X
  2651. X    static void
  2652. Xshowmap(mp)
  2653. X    struct mapblock *mp;
  2654. X{
  2655. X    int len;
  2656. X
  2657. X    if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
  2658. X        outstr("! ");
  2659. X    else if (mp->m_mode & INSERT)
  2660. X        outstr("i ");
  2661. X    else if (mp->m_mode & CMDLINE)
  2662. X        outstr("c ");
  2663. X    len = outtrans(mp->m_keys, -1);    /* get length of what we have written */
  2664. X    do
  2665. X    {
  2666. X        outchar(' ');                /* padd with blanks */
  2667. X        ++len;
  2668. X    } while (len < 12);
  2669. X    if (mp->m_noremap)
  2670. X        outchar('*');
  2671. X    else
  2672. X        outchar(' ');
  2673. X    outtrans(mp->m_str, -1);
  2674. X    outchar('\n');
  2675. X    flushbuf();
  2676. X}
  2677. X
  2678. X/*
  2679. X * Check for an abbreviation.
  2680. X * Cursor is at ptr[col]. When inserting, mincol is where insert started.
  2681. X * "c" is the character typed before check_abbr was called.
  2682. X */
  2683. X    int
  2684. Xcheck_abbr(c, ptr, col, mincol)
  2685. X    int        c;
  2686. X    char    *ptr;
  2687. X    int        col;
  2688. X    int        mincol;
  2689. X{
  2690. X    int                len;
  2691. X    int                j;
  2692. X    char            tb[3];
  2693. X    struct mapblock *mp;
  2694. X
  2695. X    for (len = col; len > 0 && isidchar(ptr[len - 1]); --len)
  2696. X        ;
  2697. X    if (len < mincol)
  2698. X        len = mincol;
  2699. X    if (len < col)                /* there is a word in front of the cursor */
  2700. X    {
  2701. X        ptr += len;
  2702. X        len = col - len;
  2703. X        for (mp = maplist.m_next; mp; mp = mp->m_next)
  2704. X        {
  2705. X                    /* find entries with right mode and keys */
  2706. X            if ((mp->m_mode & ABBREV) == ABBREV &&
  2707. X                        (mp->m_mode & State) &&
  2708. X                        mp->m_keylen == len &&
  2709. X                        !strncmp(mp->m_keys, ptr, (size_t)len))
  2710. X                break;
  2711. X        }
  2712. X        if (mp)                                /* found a match */
  2713. X        {
  2714. X            j = 0;
  2715. X            if (c < 0x100 && (c < ' ' || c > '~'))
  2716. X                tb[j++] = Ctrl('V');        /* special char needs CTRL-V */
  2717. X            tb[j++] = c;
  2718. X            tb[j] = NUL;
  2719. X            ins_typestr(tb, TRUE);            /* insert the last typed char */
  2720. X            ins_typestr(mp->m_str, mp->m_noremap);    /* insert the to string */
  2721. X            while (len--)
  2722. X                ins_typestr("\b", TRUE);    /* delete the from string */
  2723. X            return TRUE;
  2724. X        }
  2725. X    }
  2726. X    return FALSE;
  2727. X}
  2728. X
  2729. X/*
  2730. X * Write map commands for the current mappings to an .exrc file.
  2731. X * Return 1 on error.
  2732. X */
  2733. X    int
  2734. Xmakemap(fd)
  2735. X    FILE *fd;
  2736. X{
  2737. X    struct mapblock *mp;
  2738. X    char            c1;
  2739. X    char             *p;
  2740. X
  2741. X    for (mp = maplist.m_next; mp; mp = mp->m_next)
  2742. X    {
  2743. X        c1 = NUL;
  2744. X        p = "map";
  2745. X        switch (mp->m_mode)
  2746. X        {
  2747. X        case NORMAL:
  2748. X            break;
  2749. X        case CMDLINE + INSERT:
  2750. X            p = "map!";
  2751. X            break;
  2752. X        case CMDLINE:
  2753. X            c1 = 'c';
  2754. X            break;
  2755. X        case INSERT:
  2756. X            c1 = 'i';
  2757. X            break;
  2758. X        case INSERT + CMDLINE + ABBREV:
  2759. X            p = "abbr";
  2760. X            break;
  2761. X        case CMDLINE + ABBREV:
  2762. X            c1 = 'c';
  2763. X            p = "abbr";
  2764. X            break;
  2765. X        case INSERT + ABBREV:
  2766. X            c1 = 'i';
  2767. X            p = "abbr";
  2768. X            break;
  2769. X        default:
  2770. X            emsg("makemap: Illegal mode");
  2771. X            return 1;
  2772. X        }
  2773. X        if (c1 && putc(c1, fd) < 0)
  2774. X            return 1;
  2775. X        if (mp->m_noremap && fprintf(fd, "nore") < 0)
  2776. X            return 1;
  2777. X        if (fprintf(fd, p) < 0)
  2778. X            return 1;
  2779. X
  2780. X        if (    putc(' ', fd) < 0 || putescstr(fd, mp->m_keys, FALSE) < 0 ||
  2781. X                putc(' ', fd) < 0 || putescstr(fd, mp->m_str, FALSE) < 0 ||
  2782. X#ifdef MSDOS
  2783. X                putc('\r', fd) < 0 ||
  2784. X#endif
  2785. X                putc('\n', fd) < 0)
  2786. X            return 1;
  2787. X    }
  2788. X    return 0;
  2789. X}
  2790. X
  2791. X    int
  2792. Xputescstr(fd, str, set)
  2793. X    FILE        *fd;
  2794. X    char        *str;
  2795. X    int            set;        /* TRUE for makeset, FALSE for makemap */
  2796. X{
  2797. X    for ( ; *str; ++str)
  2798. X    {
  2799. X        /*
  2800. X         * some characters have to be escaped with CTRL-V to
  2801. X         * prevent them from misinterpreted in DoOneCmd().
  2802. X         * A space has to be escaped with a backslash to
  2803. X         * prevent it to be misinterpreted in doset().
  2804. X         */
  2805. X        if (*str < ' ' || *str > '~' || (*str == ' ' && !set))
  2806. X        {
  2807. X            if (putc(Ctrl('V'), fd) < 0)
  2808. X                return -1;
  2809. X        }
  2810. X        else if ((set && *str == ' ') || *str == '|')
  2811. X        {
  2812. X            if (putc('\\', fd) < 0)
  2813. X                return -1;
  2814. X        }
  2815. X        if (putc(*str, fd) < 0)
  2816. X            return -1;
  2817. X    }
  2818. X    return 0;
  2819. X}
  2820. END_OF_FILE
  2821. if test 29561 -ne `wc -c <'vim/src/buffers.c'`; then
  2822.     echo shar: \"'vim/src/buffers.c'\" unpacked with wrong size!
  2823. fi
  2824. chmod +x 'vim/src/buffers.c'
  2825. # end of 'vim/src/buffers.c'
  2826. fi
  2827. echo shar: End of archive 14 \(of 25\).
  2828. cp /dev/null ark14isdone
  2829. MISSING=""
  2830. 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
  2831.     if test ! -f ark${I}isdone ; then
  2832.     MISSING="${MISSING} ${I}"
  2833.     fi
  2834. done
  2835. if test "${MISSING}" = "" ; then
  2836.     echo You have unpacked all 25 archives.
  2837.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2838. else
  2839.     echo You still need to unpack the following archives:
  2840.     echo "        " ${MISSING}
  2841. fi
  2842. ##  End of shell archive.
  2843. exit 0
  2844.  
  2845. ===============================================================================
  2846. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  2847. Oce Nederland B.V., Research & Development | necessarily represent the position
  2848. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  2849. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  2850. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  2851.  
  2852. exit 0 # Just in case...
  2853.