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

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