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

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i075:  vim - Vi IMitation editor, v2.0, Part25/25
  4. Message-ID: <1993Dec21.173113.2657@sparky.sterling.com>
  5. X-Md4-Signature: 75d519b1526121030dbe7fef13f39e44
  6. Keywords: utility, editor, vi, vim
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: Sterling Software
  9. Date: Tue, 21 Dec 1993 17:31:13 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 75
  14. Archive-name: vim/part25
  15. Environment: UNIX, AMIGA, MS-DOS
  16. Supersedes: vim: Volume 37, Issue 1-24
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 25 (of 25)."
  25. # Contents:  vim/src/cmdline.c
  26. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:09 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'vim/src/cmdline.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'vim/src/cmdline.c'\"
  30. else
  31. echo shar: Extracting \"'vim/src/cmdline.c'\" \(60249 characters\)
  32. sed "s/^X//" >'vim/src/cmdline.c' <<'END_OF_FILE'
  33. X/* vi:ts=4:sw=4
  34. X *
  35. X * VIM - Vi IMproved
  36. X *
  37. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  38. X *                            Tim Thompson            twitch!tjt
  39. X *                            Tony Andrews            onecom!wldrdg!tony 
  40. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  41. X */
  42. X
  43. X/*
  44. X * cmdline.c: functions for reading in the command line and executing it
  45. X */
  46. X
  47. X#include "vim.h"
  48. X#include "globals.h"
  49. X#include "proto.h"
  50. X#include "param.h"
  51. X#include "cmdtab.h"
  52. X#include "ops.h"            /* included because we call functions in ops.c */
  53. X#include "fcntl.h"            /* for chdir() */
  54. X
  55. X#ifdef LATTICE
  56. X# define mktemp(a)    tmpnam(a)
  57. X#endif
  58. X
  59. X/*
  60. X * the history list of alternate files
  61. X */
  62. X#define NUMALTFILES 20
  63. X
  64. Xstatic char    *altfiles[NUMALTFILES];    /* alternate files */
  65. Xstatic char    *saltfiles[NUMALTFILES];    /* alternate files without path */
  66. Xstatic linenr_t altlnum[NUMALTFILES];    /* line # in alternate file */
  67. Xstatic linenr_t doecmdlnum = 0;            /* line # in new file for doecmd() */
  68. X
  69. X/*
  70. X * variables shared between getcmdline() and redrawcmdline()
  71. X */
  72. Xstatic int         cmdlen;        /* number of chars on command line */
  73. Xstatic int         cmdpos;        /* current cursor position */
  74. Xstatic int         cmdslen;        /* lenght of command line on screen */
  75. Xstatic int         cmdspos;        /* cursor position on screen */
  76. Xstatic int         cmdfirstc;     /* ':', '/' or '?' */
  77. Xstatic u_char    *cmdbuff;        /* pointer to command line buffer */
  78. X
  79. X/*
  80. X * The next two variables contain the bounds of any range given in a command.
  81. X * They are set by docmdline().
  82. X */
  83. Xstatic linenr_t     line1, line2;
  84. X
  85. Xstatic int            forceit;
  86. Xstatic int            regname;
  87. Xstatic int            quitmore = 0;
  88. Xstatic int          cmd_numfiles = -1;      /* number of files found by
  89. X                                                    filename completion */
  90. X
  91. Xstatic void        putcmdline __ARGS((int, u_char *));
  92. Xstatic void        cmdchecklen __ARGS((void));
  93. Xstatic void        cursorcmd __ARGS((void));
  94. Xstatic int        ccheck_abbr __ARGS((int));
  95. Xstatic u_char    *DoOneCmd __ARGS((u_char *));
  96. Xstatic void        dobang __ARGS((int, u_char *));
  97. Xstatic int        autowrite __ARGS((void));
  98. Xstatic int        dowrite __ARGS((u_char *, int));
  99. Xstatic int        doecmd __ARGS((char *, char *));
  100. Xstatic void        doshell __ARGS((char *));
  101. Xstatic void        dofilter __ARGS((u_char *, int, int));
  102. Xstatic void        domake __ARGS((char *));
  103. Xstatic int        doarglist __ARGS((char *));
  104. Xstatic int        check_readonly __ARGS((void));
  105. Xstatic int        check_changed __ARGS((int));
  106. Xstatic int        check_more __ARGS((int));
  107. Xstatic void        setaltfname __ARGS((char *, char *, linenr_t, int));
  108. Xstatic void        nextwild __ARGS((u_char *, int));
  109. Xstatic void        showmatches __ARGS((char *, int));
  110. Xstatic char        *addstar __ARGS((char *, int));
  111. Xstatic linenr_t get_address __ARGS((u_char **));
  112. Xstatic void        do_align __ARGS((linenr_t, linenr_t, int, int));
  113. X
  114. Xextern char        *mktemp __ARGS((char *));
  115. X
  116. Xextern int global_busy, global_wait;    /* shared with csearch.c, message.c */
  117. X
  118. X/*
  119. X * getcmdline() - accept a command line starting with ':', '!', '/', or '?'
  120. X *
  121. X * For searches the optional matching '?' or '/' is removed.
  122. X */
  123. X
  124. X    int
  125. Xgetcmdline(firstc, buff)
  126. X    int            firstc;     /* either ':', '/', or '?' */
  127. X    u_char        *buff;         /* buffer for command string */
  128. X{
  129. X    register u_char     c;
  130. X             int        nextc = 0;
  131. X    register int        i;
  132. X             int        retval;
  133. X             int        hiscnt;                /* current history line in use */
  134. X    static     char         **history = NULL;    /* history table */
  135. X    static     int        hislen = 0;         /* actual lengt of history table */
  136. X             int        newlen;                /* new length of history table */
  137. X    static     int        hisidx = -1;        /* last entered entry */
  138. X             char        **temp;
  139. X             char        *lookfor = NULL;    /* string to match */
  140. X             int        j = -1;
  141. X             int        gotesc = FALSE;        /* TRUE when last char typed was <ESC> */
  142. X
  143. X/*
  144. X * set some variables for redrawcmd()
  145. X */
  146. X    cmdfirstc = firstc;
  147. X    cmdbuff = buff;
  148. X    cmdlen = cmdpos = 0;
  149. X    cmdslen = cmdspos = 1;
  150. X    State = CMDLINE;
  151. X    gotocmdline(TRUE, firstc);
  152. X
  153. X/*
  154. X * if size of history table changed, reallocate it
  155. X */
  156. X    newlen = (int)p_hi;
  157. X    if (newlen != hislen)                        /* history length changed */
  158. X    {
  159. X        if (newlen)
  160. X            temp = (char **)lalloc((u_long)(newlen * sizeof(char *)), TRUE);
  161. X        else
  162. X            temp = NULL;
  163. X        if (newlen == 0 || temp != NULL)
  164. X        {
  165. X            if (newlen > hislen)            /* array becomes bigger */
  166. X            {
  167. X                for (i = 0; i <= hisidx; ++i)
  168. X                    temp[i] = history[i];
  169. X                j = i;
  170. X                for ( ; i <= newlen - (hislen - hisidx); ++i)
  171. X                    temp[i] = NULL;
  172. X                for ( ; j < hislen; ++i, ++j)
  173. X                    temp[i] = history[j];
  174. X            }
  175. X            else                            /* array becomes smaller */
  176. X            {
  177. X                j = hisidx;
  178. X                for (i = newlen - 1; ; --i)
  179. X                {
  180. X                    if (i >= 0)
  181. X                        temp[i] = history[j];    /* copy newest entries */
  182. X                    else
  183. X                        free(history[j]);        /* remove older entries */
  184. X                    if (--j < 0)
  185. X                        j = hislen - 1;
  186. X                    if (j == hisidx)
  187. X                        break;
  188. X                }
  189. X                hisidx = newlen - 1;
  190. X            }
  191. X            free(history);
  192. X            history = temp;
  193. X            hislen = newlen;
  194. X        }
  195. X    }
  196. X    hiscnt = hislen;            /* set hiscnt to impossible history value */
  197. X
  198. X#ifdef DIGRAPHS
  199. X    dodigraph(-1);                /* init digraph typahead */
  200. X#endif
  201. X
  202. X    /* collect the command string, handling '\b', @ and much more */
  203. X    for (;;)
  204. X    {
  205. X        cursorcmd();    /* set the cursor on the right spot */
  206. X        if (nextc)        /* character remaining from CTRL-V */
  207. X        {
  208. X            c = nextc;
  209. X            nextc = 0;
  210. X        }
  211. X        else
  212. X        {
  213. X            c = vgetc();
  214. X            if (c == Ctrl('C') && got_int)
  215. X                got_int = FALSE;
  216. X        }
  217. X
  218. X        if (lookfor && c != K_SDARROW && c != K_SUARROW)
  219. X        {
  220. X            free(lookfor);
  221. X            lookfor = NULL;
  222. X        }
  223. X
  224. X        if (cmd_numfiles > 0 && !(c == p_wc && KeyTyped) && c != Ctrl('N') &&
  225. X                        c != Ctrl('P') && c != Ctrl('A') && c != Ctrl('L'))
  226. X            (void)ExpandOne(NULL, FALSE, -2);    /* may free expanded file names */
  227. X
  228. X#ifdef DIGRAPHS
  229. X        c = dodigraph(c);
  230. X#endif
  231. X
  232. X        if (c == '\n' || c == '\r' || (c == ESC && !KeyTyped))
  233. X        {
  234. X            if (ccheck_abbr(c + 0x100))
  235. X                continue;
  236. X            outchar('\r');
  237. X            flushbuf();
  238. X            break;
  239. X        }
  240. X
  241. X            /* hitting <ESC> twice means: abandon command line */
  242. X            /* wildcard expansion is only done when the key is really typed, not
  243. X               when it comes from a macro */
  244. X        if (c == p_wc && !gotesc && KeyTyped)
  245. X        {
  246. X            if (cmd_numfiles > 0)    /* typed p_wc twice */
  247. X                nextwild(buff, 3);
  248. X            else                    /* typed p_wc first time */
  249. X                nextwild(buff, 0);
  250. X            if (c == ESC)
  251. X                gotesc = TRUE;
  252. X            continue;
  253. X        }
  254. X        gotesc = FALSE;
  255. X
  256. X        if (c == K_ZERO)        /* NUL is stored as NL */
  257. X            c = '\n';
  258. X
  259. X        switch (c)
  260. X        {
  261. X        case BS:
  262. X        case DEL:
  263. X        case Ctrl('W'):
  264. X                /*
  265. X                 * delete current character is the same as backspace on next
  266. X                 * character, except at end of line
  267. X                 */
  268. X                if (c == DEL && cmdpos != cmdlen)
  269. X                    ++cmdpos;
  270. X                if (cmdpos > 0)
  271. X                {
  272. X                    j = cmdpos;
  273. X                    if (c == Ctrl('W'))
  274. X                    {
  275. X                        while (cmdpos && isspace(buff[cmdpos - 1]))
  276. X                            --cmdpos;
  277. X                        i = isidchar(buff[cmdpos - 1]);
  278. X                        while (cmdpos && !isspace(buff[cmdpos - 1]) && isidchar(buff[cmdpos - 1]) == i)
  279. X                            --cmdpos;
  280. X                    }
  281. X                    else
  282. X                        --cmdpos;
  283. X                    cmdlen -= j - cmdpos;
  284. X                    i = cmdpos;
  285. X                    while (i < cmdlen)
  286. X                        buff[i++] = buff[j++];
  287. X                    redrawcmd();
  288. X                }
  289. X                else if (cmdlen == 0 && c != Ctrl('W'))
  290. X                {
  291. X                    retval = FALSE;
  292. X                    msg("");
  293. X                    goto returncmd;     /* back to cmd mode */
  294. X                }
  295. X                continue;
  296. X
  297. X/*        case '@':    only in very old vi */
  298. X        case Ctrl('U'):
  299. Xclearline:
  300. X                cmdpos = 0;
  301. X                cmdlen = 0;
  302. X                cmdslen = 1;
  303. X                cmdspos = 1;
  304. X                redrawcmd();
  305. X                continue;
  306. X
  307. X        case ESC:            /* get here if p_wc != ESC or when ESC typed twice */
  308. X        case Ctrl('C'):
  309. X                retval = FALSE;
  310. X                msg("");
  311. X                goto returncmd;     /* back to cmd mode */
  312. X
  313. X        case Ctrl('D'):
  314. X            {
  315. X                for (i = cmdpos; i > 0 && buff[i - 1] != ' '; --i)
  316. X                        ;
  317. X                showmatches((char *)&buff[i], cmdpos - i);
  318. X                for (i = Rows_max - Rows; i; --i)
  319. X                    outchar('\n');
  320. X
  321. X                redrawcmd();
  322. X                continue;
  323. X            }
  324. X
  325. X        case K_RARROW:
  326. X        case K_SRARROW:
  327. X                do
  328. X                {
  329. X                        if (cmdpos >= cmdlen)
  330. X                                break;
  331. X                        cmdspos += charsize(buff[cmdpos]);
  332. X                        ++cmdpos;
  333. X                }
  334. X                while (c == K_SRARROW && buff[cmdpos] != ' ');
  335. X                continue;
  336. X
  337. X        case K_LARROW:
  338. X        case K_SLARROW:
  339. X                do
  340. X                {
  341. X                        if (cmdpos <= 0)
  342. X                                break;
  343. X                        --cmdpos;
  344. X                        cmdspos -= charsize(buff[cmdpos]);
  345. X                }
  346. X                while (c == K_SLARROW && buff[cmdpos - 1] != ' ');
  347. X                continue;
  348. X
  349. X        case Ctrl('B'):        /* begin of command line */
  350. X                cmdpos = 0;
  351. X                cmdspos = 1;
  352. X                continue;
  353. X
  354. X        case Ctrl('E'):        /* end of command line */
  355. X                cmdpos = cmdlen;
  356. X                buff[cmdlen] = NUL;
  357. X                cmdspos = strsize((char *)buff) + 1;
  358. X                continue;
  359. X
  360. X        case Ctrl('A'):        /* all matches */
  361. X                nextwild(buff, 4);
  362. X                continue;
  363. X
  364. X        case Ctrl('L'):        /* longest common part */
  365. X                nextwild(buff, 5);
  366. X                continue;
  367. X
  368. X        case Ctrl('N'):        /* next match */
  369. X        case Ctrl('P'):        /* previous match */
  370. X                if (cmd_numfiles > 0)
  371. X                {
  372. X                    nextwild(buff, (c == Ctrl('P')) ? 2 : 1);
  373. X                    continue;
  374. X                }
  375. X
  376. X        case K_UARROW:
  377. X        case K_DARROW:
  378. X        case K_SUARROW:
  379. X        case K_SDARROW:
  380. X                if (hislen == 0)        /* no history */
  381. X                    continue;
  382. X
  383. X                i = hiscnt;
  384. X            
  385. X                    /* save current command string */
  386. X                if (c == K_SUARROW || c == K_SDARROW)
  387. X                {
  388. X                    buff[cmdpos] = NUL;
  389. X                    if (lookfor == NULL && (lookfor = strsave((char *)buff)) == NULL)
  390. X                        continue;
  391. X
  392. X                    j = strlen(lookfor);
  393. X                }
  394. X                for (;;)
  395. X                {
  396. X                        /* one step backwards */
  397. X                    if (c == K_UARROW || c == K_SUARROW || c == Ctrl('P'))
  398. X                    {
  399. X                        if (hiscnt == hislen)    /* first time */
  400. X                            hiscnt = hisidx;
  401. X                        else if (hiscnt == 0 && hisidx != hislen - 1)
  402. X                            hiscnt = hislen - 1;
  403. X                        else if (hiscnt != hisidx + 1)
  404. X                            --hiscnt;
  405. X                        else                    /* at top of list */
  406. X                            break;
  407. X                    }
  408. X                    else    /* one step forwards */
  409. X                    {
  410. X                        if (hiscnt == hisidx)    /* on last entry, clear the line */
  411. X                        {
  412. X                            hiscnt = hislen;
  413. X                            goto clearline;
  414. X                        }
  415. X                        if (hiscnt == hislen)    /* not on a history line, nothing to do */
  416. X                            break;
  417. X                        if (hiscnt == hislen - 1)    /* wrap around */
  418. X                            hiscnt = 0;
  419. X                        else
  420. X                            ++hiscnt;
  421. X                    }
  422. X                    if (hiscnt < 0 || history[hiscnt] == NULL)
  423. X                    {
  424. X                        hiscnt = i;
  425. X                        break;
  426. X                    }
  427. X                    if ((c != K_SUARROW && c != K_SDARROW) || hiscnt == i ||
  428. X                            strncmp(history[hiscnt], lookfor, (size_t)j) == 0)
  429. X                        break;
  430. X                }
  431. X
  432. X                if (hiscnt != i)        /* jumped to other entry */
  433. X                {
  434. X                    strcpy((char *)buff, history[hiscnt]);
  435. X                    cmdpos = cmdlen = strlen((char *)buff);
  436. X                    redrawcmd();
  437. X                }
  438. X                continue;
  439. X
  440. X        case Ctrl('V'):
  441. X                putcmdline('^', buff);
  442. X                c = get_literal(&nextc);    /* get next (two) character(s) */
  443. X                break;
  444. X
  445. X#ifdef DIGRAPHS
  446. X        case Ctrl('K'):
  447. X                putcmdline('?', buff);
  448. X                  c = vgetc();
  449. X                putcmdline(c, buff);
  450. X                c = getdigraph(c, vgetc());
  451. X                break;
  452. X#endif /* DIGRAPHS */
  453. X        }
  454. X
  455. X        /* we come here if we have a normal character */
  456. X
  457. X        if (!isidchar(c) && ccheck_abbr(c))
  458. X            continue;
  459. X
  460. X        if (cmdlen < CMDBUFFSIZE - 2)
  461. X        {
  462. X                for (i = cmdlen++; i > cmdpos; --i)
  463. X                        buff[i] = buff[i - 1];
  464. X                buff[cmdpos] = c;
  465. X                outtrans((char *)(buff + cmdpos), cmdlen - cmdpos);
  466. X                ++cmdpos;
  467. X                i = charsize(c);
  468. X                cmdslen += i;
  469. X                cmdspos += i;
  470. X        }
  471. X        cmdchecklen();
  472. X    }
  473. X    retval = TRUE;                /* when we get here we have a valid command line */
  474. X
  475. Xreturncmd:
  476. X    buff[cmdlen] = NUL;
  477. X    if (hislen != 0 && cmdlen != 0)        /* put line in history buffer */
  478. X    {
  479. X        if (++hisidx == hislen)
  480. X            hisidx = 0;
  481. X        free(history[hisidx]);
  482. X        history[hisidx] = strsave((char *)buff);
  483. X    }
  484. X
  485. X    /*
  486. X     * If the screen was shifted up, redraw the whole screen (later).
  487. X     * If the line is too long, clear it, so ruler and shown command do
  488. X     * not get printed in the middle of it.
  489. X     */
  490. X    if (cmdoffset)
  491. X        must_redraw = CLEAR;
  492. X    else if (cmdslen >= sc_col)
  493. X        gotocmdline(TRUE, NUL);
  494. X    State = NORMAL;
  495. X    script_winsize_pp();
  496. X    return retval;
  497. X}
  498. X
  499. X/*
  500. X * put a character on the command line.
  501. X * Used for CTRL-V and CTRL-K
  502. X */
  503. X    static void
  504. Xputcmdline(c, buff)
  505. X    int        c;
  506. X    u_char    *buff;
  507. X{
  508. X    int        len;
  509. X    char    buf[2];
  510. X
  511. X    buf[0] = c;
  512. X    buf[1] = 0;
  513. X    len = outtrans(buf, 1);
  514. X    outtrans((char *)(buff + cmdpos), cmdlen - cmdpos);
  515. X    cmdslen += len;
  516. X    cmdchecklen();
  517. X    cmdslen -= len;
  518. X    cursorcmd();
  519. X}
  520. X
  521. X/*
  522. X * Check if the command line spans more than one screen line.
  523. X * The maximum number of lines is remembered.
  524. X */
  525. X    static void
  526. Xcmdchecklen()
  527. X{
  528. X    if (cmdslen / (int)Columns > cmdoffset)
  529. X        cmdoffset = cmdslen / (int)Columns;
  530. X}
  531. X
  532. X/*
  533. X * this fuction is called when the screen size changes
  534. X */
  535. X    void
  536. Xredrawcmdline()
  537. X{
  538. X        cmdoffset = 0;
  539. X        redrawcmd();
  540. X        cursorcmd();
  541. X}
  542. X
  543. X/*
  544. X * Redraw what is currently on the command line.
  545. X */
  546. X    void
  547. Xredrawcmd()
  548. X{
  549. X    register int i;
  550. X
  551. X    windgoto((int)Rows - 1 - cmdoffset, 0);
  552. X    outchar(cmdfirstc);
  553. X    cmdslen = 1;
  554. X    cmdspos = 1;
  555. X    outtrans((char *)cmdbuff, cmdlen);
  556. X    for (i = 0; i < cmdlen; )
  557. X    {
  558. X        cmdslen += charsize(cmdbuff[i]);
  559. X        if (++i == cmdpos)
  560. X                cmdspos = cmdslen;
  561. X    }
  562. X    for (i = (cmdoffset + 1) * (int)Columns - cmdslen; --i > 0; )
  563. X        outchar(' ');
  564. X    cmdchecklen();
  565. X}
  566. X
  567. X    static void
  568. Xcursorcmd()
  569. X{
  570. X    windgoto((int)Rows - 1 - cmdoffset + (cmdspos / (int)Columns), cmdspos % (int)Columns);
  571. X}
  572. X
  573. X/*
  574. X * Check the word in front of the cursor for an abbreviation.
  575. X * Called when the non-id character "c" has been entered.
  576. X * When an abbreviation is recognized it is removed from the text with
  577. X * backspaces and the replacement string is inserted, followed by "c".
  578. X */
  579. X    static int
  580. Xccheck_abbr(c)
  581. X    int c;
  582. X{
  583. X    if (p_paste || no_abbr)            /* no abbreviations or in paste mode */
  584. X        return FALSE;
  585. X    
  586. X    return check_abbr(c, (char *)cmdbuff, cmdpos, 0);
  587. X}
  588. X
  589. X/*
  590. X * docmdline(): execute an Ex command line
  591. X *
  592. X * 1. If no line given, get one.
  593. X * 2. Split up in parts separated with '|'.
  594. X *
  595. X * This function may be called recursively!
  596. X */
  597. X    void
  598. Xdocmdline(cmdline)
  599. X    u_char        *cmdline;
  600. X{
  601. X    u_char        buff[CMDBUFFSIZE];        /* command line */
  602. X    u_char        *nextcomm;
  603. X
  604. X/*
  605. X * 1. If no line given: get one.
  606. X */
  607. X    if (cmdline == NULL)
  608. X    {
  609. X        if (!getcmdline(':', buff))
  610. X            return;
  611. X    }
  612. X    else
  613. X    {
  614. X        if (strlen((char *)cmdline) > (size_t)(CMDBUFFSIZE - 2))
  615. X        {
  616. X            emsg(e_toolong);
  617. X            return;
  618. X        }
  619. X        /* Make a copy of the command so we can mess with it. */
  620. X        strcpy((char *)buff, (char *)cmdline);
  621. X    }
  622. X
  623. X/*
  624. X * 2. Loop for each '|' separated command.
  625. X *    DoOneCmd will set nextcommand to NULL if there is no trailing '|'.
  626. X */
  627. X    for (;;)
  628. X    {
  629. X        nextcomm = DoOneCmd(buff);
  630. X        if (nextcomm == NULL)
  631. X            break;
  632. X        strcpy((char *)buff, (char *)nextcomm);
  633. X    }
  634. X}
  635. X
  636. X/*
  637. X * Execute one Ex command.
  638. X *
  639. X * 2. skip comment lines and leading space
  640. X * 3. parse range
  641. X * 4. parse command
  642. X * 5. parse arguments
  643. X * 6. switch on command name
  644. X *
  645. X * This function may be called recursively!
  646. X */
  647. X    static u_char *
  648. XDoOneCmd(buff)
  649. X    u_char *buff;
  650. X{
  651. X    u_char                cmdbuf[CMDBUFFSIZE];    /* for '%' and '#' expansion */
  652. X    u_char                c;
  653. X    register u_char        *p;
  654. X    char                *q;
  655. X    u_char                *cmd, *arg;
  656. X    int                 i;
  657. X    int                    cmdidx;
  658. X    int                    argt;
  659. X    register linenr_t    lnum;
  660. X    long                n;
  661. X    int                    addr_count;    /* number of address specifications */
  662. X    FPOS                pos;
  663. X    int                    append = FALSE;            /* write with append */
  664. X    int                    usefilter = FALSE;        /* filter instead of file name */
  665. X    u_char                *nextcomm;
  666. X
  667. X    if (quitmore)
  668. X        --quitmore;        /* when not editing the last file :q has to be typed twice */
  669. X/*
  670. X * 2. skip comment lines and leading space, colons or bars
  671. X */
  672. X    for (cmd = buff; *cmd && strchr(" \t:|", *cmd) != NULL; cmd++)
  673. X        ;
  674. X
  675. X    nextcomm = NULL;        /* default: no next command */
  676. X    if (strchr("#\"", *cmd) != NULL)    /* ignore comment and empty lines */
  677. X        goto doend;
  678. X
  679. X/*
  680. X * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
  681. X *
  682. X * where 'addr' is:
  683. X *
  684. X * %          (entire file)
  685. X * $  [+-NUM]
  686. X * 'x [+-NUM] (where x denotes a currently defined mark)
  687. X * .  [+-NUM]
  688. X * [+-NUM]..
  689. X * NUM
  690. X *
  691. X * The cmd pointer is updated to point to the first character following the
  692. X * range spec. If an initial address is found, but no second, the upper bound
  693. X * is equal to the lower.
  694. X */
  695. X
  696. X    addr_count = 0;
  697. X    --cmd;
  698. X    do
  699. X    {
  700. X        ++cmd;                            /* skip ',' or ';' */
  701. X        line1 = line2;
  702. X        line2 = Curpos.lnum;            /* default is current line number */
  703. X        skipspace((char **)&cmd);
  704. X        lnum = get_address(&cmd);
  705. X        if (lnum == INVLNUM)
  706. X        {
  707. X            if (*cmd == '%')            /* '%' - all lines */
  708. X            {
  709. X                ++cmd;
  710. X                line1 = 1;
  711. X                line2 = line_count;
  712. X                ++addr_count;
  713. X            }
  714. X        }
  715. X        else
  716. X            line2 = lnum;
  717. X        addr_count++;
  718. X
  719. X        if (*cmd == ';')
  720. X        {
  721. X            if (line2 == 0)
  722. X                Curpos.lnum = 1;
  723. X            else
  724. X                Curpos.lnum = line2;
  725. X        }
  726. X    } while (*cmd == ',' || *cmd == ';');
  727. X
  728. X    /* One address given: set start and end lines */
  729. X    if (addr_count == 1)
  730. X    {
  731. X        line1 = line2;
  732. X            /* ... but only implicit: really no address given */
  733. X        if (lnum == INVLNUM)
  734. X            addr_count = 0;
  735. X    }
  736. X
  737. X    if (line1 > line2 || line2 > line_count)
  738. X    {
  739. X        emsg(e_invrange);
  740. X        goto doend;
  741. X    }
  742. X
  743. X/*
  744. X * 4. parse command
  745. X */
  746. X
  747. X    skipspace((char **)&cmd);
  748. X
  749. X    /*
  750. X     * If we got a line, but no command, then go to the line.
  751. X     */
  752. X    if (*cmd == NUL || *cmd == '"' || (*cmd == '|' && (nextcomm = cmd) != NULL))
  753. X    {
  754. X        if (addr_count != 0)
  755. X        {
  756. X            if (line2 == 0)
  757. X                Curpos.lnum = 1;
  758. X            else
  759. X                Curpos.lnum = line2;
  760. X            Curpos.col = 0;
  761. X            cursupdate();
  762. X        }
  763. X        goto doend;
  764. X    }
  765. X
  766. X    /*
  767. X     * isolate the command and search for it in the command table
  768. X     */
  769. X    p = cmd;
  770. X    if (*cmd != 'k')
  771. X        while (isalpha(*p))
  772. X            ++p;
  773. X    if (p == cmd && strchr("@!=><&k", *p) != NULL)    /* non-alpha or 'k' command */
  774. X        ++p;
  775. X    i = (int)(p - cmd);
  776. X
  777. X    for (cmdidx = 0; cmdidx < CMD_SIZE; ++cmdidx)
  778. X        if (strncmp(cmdnames[cmdidx].cmd_name, (char *)cmd, (size_t)i) == 0)
  779. X            break;
  780. X
  781. X    if (i == 0 || cmdidx == CMD_SIZE)
  782. X    {
  783. X        emsg(e_invcmd);
  784. X        goto doend;
  785. X    }
  786. X
  787. X    if (*p == '!')                    /* forced commands */
  788. X    {
  789. X        ++p;
  790. X        forceit = TRUE;
  791. X    }
  792. X    else
  793. X        forceit = FALSE;
  794. X
  795. X/*
  796. X * 5. parse arguments
  797. X */
  798. X    argt = cmdnames[cmdidx].cmd_argt;
  799. X
  800. X    if (!(argt & RANGE) && addr_count)
  801. X    {
  802. X        emsg(e_norange);
  803. X        goto doend;
  804. X    }
  805. X
  806. X    if (!(argt & ZEROR))            /* zero in range not allowed */
  807. X    {
  808. X        if (line1 == 0)
  809. X            line1 = 1;
  810. X        if (line2 == 0)
  811. X            line2 = 1;
  812. X    }
  813. X
  814. X    /*
  815. X     * for the :make command we insert the 'makeprg' option here,
  816. X     * so things like % get expanded
  817. X     */
  818. X    if (cmdidx == CMD_make)
  819. X    {
  820. X        if (strlen(p_mp) + strlen((char *)p) + 2 >= (unsigned)CMDBUFFSIZE)
  821. X        {
  822. X            emsg(e_toolong);
  823. X            goto doend;
  824. X        }
  825. X        strcpy((char *)cmdbuf, p_mp);
  826. X        strcat((char *)cmdbuf, " ");
  827. X        strcat((char *)cmdbuf, (char *)p);
  828. X        strcpy((char *)buff, (char *)cmdbuf);
  829. X        p = buff;
  830. X    }
  831. X
  832. X    arg = p;                        /* remember start of argument */
  833. X    skipspace((char **)&arg);
  834. X
  835. X    if ((argt & NEEDARG) && *arg == NUL)
  836. X    {
  837. X        emsg(e_argreq);
  838. X        goto doend;
  839. X    }
  840. X
  841. X    /*
  842. X     * check for '|' to separate commands and '"' to start comments
  843. X     */
  844. X    if (argt & TRLBAR)
  845. X    {
  846. X        while (*p)
  847. X        {
  848. X            if (*p == Ctrl('V'))
  849. X            {
  850. X                if (argt & USECTRLV)    /* skip the CTRL-V and next char */
  851. X                    ++p;
  852. X                else                    /* remove CTRL-V and skip next char */
  853. X                    strcpy((char *)p, (char *)p + 1);
  854. X            }
  855. X            else if ((*p == '"' && !(argt & NOTRLCOM)) || *p == '|')
  856. X            {
  857. X                if (*(p - 1) == '\\')    /* remove the backslash */
  858. X                {
  859. X                    strcpy((char *)p - 1, (char *)p);
  860. X                    --p;
  861. X                }
  862. X                else
  863. X                {
  864. X                    if (*p == '|')
  865. X                        nextcomm = p + 1;
  866. X                    *p = NUL;
  867. X                    break;
  868. X                }
  869. X            }
  870. X            ++p;
  871. X        }
  872. X        if (!(argt & NOTRLCOM))            /* remove trailing spaces */
  873. X        {
  874. X            q = (char *)arg + strlen((char *)arg);
  875. X            while (--q > (char *)arg && isspace(q[0]) && q[-1] != '\\' && q[-1] != Ctrl('V'))
  876. X                *q = NUL;
  877. X        }
  878. X    }
  879. X
  880. X    if ((argt & DFLALL) && addr_count == 0)
  881. X    {
  882. X        line1 = 1;
  883. X        line2 = line_count;
  884. X    }
  885. X
  886. X    regname = 0;
  887. X        /* accept numbered register only when no count allowed (:put) */
  888. X    if ((argt & REGSTR) && (isalpha(*arg) || *arg == '.' || *arg == '"' || (!(argt & COUNT) && isdigit(*arg))))
  889. X    {
  890. X        regname = *arg;
  891. X        ++arg;
  892. X        skipspace((char **)&arg);
  893. X    }
  894. X
  895. X    if ((argt & COUNT) && isdigit(*arg))
  896. X    {
  897. X        n = getdigits((char **)&arg);
  898. X        skipspace((char **)&arg);
  899. X        if (n <= 0)
  900. X        {
  901. X            emsg(e_zerocount);
  902. X            goto doend;
  903. X        }
  904. X        line1 = line2;
  905. X        line2 += n - 1;
  906. X    }
  907. X
  908. X    if (!(argt & EXTRA) && strchr("|\"#", *arg) == NULL)    /* no arguments allowed */
  909. X    {
  910. X        emsg(e_trailing);
  911. X        goto doend;
  912. X    }
  913. X
  914. X    if (cmdidx == CMD_write)
  915. X    {
  916. X        if (*arg == '>')                        /* append */
  917. X        {
  918. X            if (*++arg != '>')                /* typed wrong */
  919. X            {
  920. X                emsg("Use w or w>>");
  921. X                goto doend;
  922. X            }
  923. X            ++arg;
  924. X            skipspace((char **)&arg);
  925. X            append = TRUE;
  926. X        }
  927. X        else if (*arg == '!')                    /* :w !filter */
  928. X        {
  929. X            ++arg;
  930. X            usefilter = TRUE;
  931. X        }
  932. X    }
  933. X
  934. X    if (cmdidx == CMD_read)
  935. X    {
  936. X        usefilter = forceit;                    /* :r! filter if forceit */
  937. X        if (*arg == '!')                        /* :r !filter */
  938. X        {
  939. X            ++arg;
  940. X            usefilter = TRUE;
  941. X        }
  942. X    }
  943. X
  944. X    /*
  945. X     * change '%' to Filename, '#' to altfile
  946. X     */
  947. X    if (argt & XFILE)
  948. X    {
  949. X        for (p = arg; *p; ++p)
  950. X        {
  951. X            c = *p;
  952. X            if (c != '%' && c != '#')    /* nothing to expand */
  953. X                continue;
  954. X            if (*(p - 1) == '\\')        /* remove escaped char */
  955. X            {
  956. X                strcpy((char *)p - 1, (char *)p);
  957. X                --p;
  958. X                continue;
  959. X            }
  960. X
  961. X            n = 1;                /* length of what we expand */
  962. X            if (c == '#' && *(p + 1) == '<')
  963. X            {                    /* "#<": current file name without extension */
  964. X                n = 2;
  965. X                c = '<';
  966. X            }
  967. X            if (c == '%' || c == '<')
  968. X            {
  969. X                if (check_fname())
  970. X                    goto doend;
  971. X                q = xFilename;
  972. X            }
  973. X            else
  974. X            {
  975. X                q = (char *)p + 1;
  976. X                i = (int)getdigits(&q);
  977. X                n = q - (char *)p;
  978. X
  979. X                if (i >= NUMALTFILES || altfiles[i] == NULL)
  980. X                {
  981. X                        emsg(e_noalt);
  982. X                        goto doend;
  983. X                }
  984. X                doecmdlnum = altlnum[i];
  985. X                if (did_cd)
  986. X                    q = altfiles[i];
  987. X                else
  988. X                    q = saltfiles[i];
  989. X            }
  990. X            i = strlen((char *)arg) + strlen(q) + 3;
  991. X            if (nextcomm)
  992. X                i += strlen((char *)nextcomm);
  993. X            if (i > CMDBUFFSIZE)
  994. X            {
  995. X                emsg(e_toolong);
  996. X                goto doend;
  997. X            }
  998. X            /*
  999. X             * we built the new argument in cmdbuf[], then copy it back to buff[]
  1000. X             */
  1001. X            *p = NUL;                            /* truncate at the '#' or '%' */
  1002. X            strcpy((char *)cmdbuf, (char *)arg);/* copy up to there */
  1003. X            i = p - arg;                        /* remember the lenght */
  1004. X            strcat((char *)cmdbuf, q);            /* append the file name */
  1005. X            if (c == '<' && (arg = (u_char *)strrchr(q, '.')) != NULL &&
  1006. X                            arg >= (u_char *)gettail(q))    /* remove extension */
  1007. X                *((char *)cmdbuf + ((char *)arg - q) + i) = NUL;
  1008. X            i = strlen((char *)cmdbuf);            /* remember the end of the filename */
  1009. X            strcat((char *)cmdbuf, (char *)p+n);/* append what is after '#' or '%' */
  1010. X            p = buff + i - 1;                    /* remember where to continue */
  1011. X            if (nextcomm)                        /* append next command */
  1012. X            {
  1013. X                i = strlen((char *)cmdbuf) + 1;
  1014. X                strcpy((char *)cmdbuf + i, (char *)nextcomm);
  1015. X                nextcomm = buff + i;
  1016. X            }
  1017. X            strcpy((char *)buff, (char *)cmdbuf);/* copy back to buff[] */
  1018. X            arg = buff;
  1019. X        }
  1020. X
  1021. X        /*
  1022. X         * One file argument: expand wildcards.
  1023. X         * Don't do this with ":r !command" or ":w !command".
  1024. X         */
  1025. X        if (argt & NOSPC)
  1026. X        {
  1027. X            if (has_wildcard((char *)arg) && !usefilter)
  1028. X            {
  1029. X                if ((p = (u_char *)ExpandOne(arg, TRUE, -1)) == NULL)
  1030. X                    goto doend;
  1031. X                if (strlen((char *)p) + arg - buff < CMDBUFFSIZE - 2)
  1032. X                    strcpy((char *)arg, (char *)p);
  1033. X                else
  1034. X                    emsg(e_toolong);
  1035. X                free(p);
  1036. X            }
  1037. X        }
  1038. X    }
  1039. X
  1040. X/*
  1041. X * 6. switch on command name
  1042. X */
  1043. X    switch (cmdidx)
  1044. X    {
  1045. X        case CMD_quit:
  1046. X                if (!check_more(FALSE))        /* if more files we won't exit */
  1047. X                    exiting = TRUE;
  1048. X                if (check_changed(FALSE) || check_more(TRUE))
  1049. X                {
  1050. X                    exiting = FALSE;
  1051. X                    settmode(1);
  1052. X                    break;
  1053. X                }
  1054. X                getout(0);
  1055. X
  1056. X        case CMD_stop:
  1057. X        case CMD_suspend:
  1058. X                if (!forceit && Changed)
  1059. X                    autowrite();
  1060. X                gotocmdend();
  1061. X                flushbuf();
  1062. X                stoptermcap();
  1063. X                mch_suspend();        /* call machine specific function */
  1064. X                starttermcap();
  1065. X                must_redraw = CLEAR;
  1066. X                break;
  1067. X
  1068. X        case CMD_xit:
  1069. X        case CMD_wq:
  1070. X                if (!check_more(FALSE))        /* if more files we won't exit */
  1071. X                    exiting = TRUE;
  1072. X                if (((cmdidx == CMD_wq || Changed) &&
  1073. X                     (check_readonly() || !dowrite(arg, FALSE))) ||
  1074. X                    check_more(TRUE))
  1075. X                {
  1076. X                    exiting = FALSE;
  1077. X                    settmode(1);
  1078. X                    break;
  1079. X                }
  1080. X                getout(0);
  1081. X
  1082. X        case CMD_args:
  1083. X                if (numfiles == 0)            /* no file name list */
  1084. X                {
  1085. X                    if (!check_fname())        /* check for no file name at all */
  1086. X                        smsg("[%s]", Filename);
  1087. X                    break;
  1088. X                }
  1089. X                gotocmdline(TRUE, NUL);
  1090. X                for (i = 0; i < numfiles; ++i)
  1091. X                {
  1092. X                    if (i == curfile)
  1093. X                        outchar('[');
  1094. X                    outstrn(files[i]);
  1095. X                    if (i == curfile)
  1096. X                        outchar(']');
  1097. X                    outchar(' ');
  1098. X                }
  1099. X                outchar('\n');
  1100. X                wait_return(TRUE);
  1101. X                break;
  1102. X
  1103. X        case CMD_wnext:
  1104. X                n = line2;
  1105. X                line1 = 1;
  1106. X                line2 = line_count;
  1107. X                dowrite(arg, FALSE);
  1108. X                line2 = n;
  1109. X                arg = (u_char *)"";        /* no file list */
  1110. X                /*FALLTHROUGH*/
  1111. X
  1112. X        case CMD_next:
  1113. X                if (check_changed(TRUE))
  1114. X                    break;
  1115. X                if (*arg != NUL)        /* redefine file list */
  1116. X                {
  1117. X                    if (doarglist((char *)arg))
  1118. X                        break;
  1119. X                    i = 0;
  1120. X                }
  1121. X                else
  1122. X                {
  1123. X                    if (addr_count == 0)
  1124. X                        i = curfile + 1;
  1125. X                    else
  1126. X                        i = curfile + (int)line2;
  1127. X                }
  1128. X
  1129. Xdonextfile:        if (i < 0 || i >= numfiles)
  1130. X                {
  1131. X                    emsg(e_nomore);
  1132. X                    break;
  1133. X                }
  1134. X                if (check_changed(TRUE))
  1135. X                    break;
  1136. X                curfile = i;
  1137. X                doecmd(files[curfile], NULL);
  1138. X                break;
  1139. X
  1140. X        case CMD_previous:
  1141. X        case CMD_Next:
  1142. X                if (addr_count == 0)
  1143. X                    i = curfile - 1;
  1144. X                else
  1145. X                    i = curfile - (int)line2;
  1146. X                goto donextfile;
  1147. X
  1148. X        case CMD_rewind:
  1149. X                i = 0;
  1150. X                goto donextfile;
  1151. X
  1152. X        case CMD_write:
  1153. X                if (usefilter)        /* input lines to shell command */
  1154. X                    dofilter(arg, TRUE, FALSE);
  1155. X                else
  1156. X                    dowrite(arg, append);
  1157. X                break;
  1158. X
  1159. X        case CMD_edit:
  1160. X        case CMD_ex:
  1161. X        case CMD_visual:
  1162. X                doecmd((char *)arg, NULL);
  1163. X                break;
  1164. X
  1165. X        case CMD_file:
  1166. X                if (*arg != NUL)
  1167. X                {
  1168. X                    setfname((char *)arg, NULL);
  1169. X                    NotEdited = TRUE;
  1170. X                    maketitle();
  1171. X                }
  1172. X                fileinfo(did_cd);        /* print full filename if :cd used */
  1173. X                break;
  1174. X
  1175. X        case CMD_files:
  1176. X#ifdef AMIGA
  1177. X                settmode(0);            /* set cooked mode, so output can be halted */
  1178. X#endif
  1179. X                for (i = 0; i < NUMALTFILES; ++i)
  1180. X                {
  1181. X                    if (altfiles[i])
  1182. X                    {
  1183. X                        sprintf(IObuff, "%2d \"%s\" line %ld\n", i, altfiles[i], (long)altlnum[i]);
  1184. X                        outstrn(IObuff);
  1185. X                    }
  1186. X                    flushbuf();
  1187. X                }
  1188. X#ifdef AMIGA
  1189. X                settmode(1);
  1190. X#endif
  1191. X                wait_return(TRUE);
  1192. X                break;
  1193. X
  1194. X        case CMD_read:
  1195. X                if (usefilter)
  1196. X                {
  1197. X                    dofilter(arg, FALSE, TRUE);            /* :r!cmd */
  1198. X                    break;
  1199. X                }
  1200. X                if (!u_save(line2, (linenr_t)(line2 + 1)))
  1201. X                    break;
  1202. X                if (readfile((char *)arg, NULL, line2, FALSE))
  1203. X                {
  1204. X                    emsg(e_notopen);
  1205. X                    break;
  1206. X                }
  1207. X                updateScreen(NOT_VALID);
  1208. X                break;
  1209. X
  1210. X        case CMD_cd:
  1211. X        case CMD_chdir:
  1212. X#ifdef UNIX
  1213. X                /*
  1214. X                 * for UNIX ":cd" means: go to home directory
  1215. X                 */
  1216. X                if (*arg == NUL)     /* use IObuff for home directory name */
  1217. X                {
  1218. X                    expand_env("$HOME", IObuff, IOSIZE);
  1219. X                    arg = (u_char *)IObuff;
  1220. X                }
  1221. X#endif
  1222. X                if (*arg != NUL)
  1223. X                {
  1224. X                    if (!did_cd)
  1225. X                    {
  1226. X                        scriptfullpath();
  1227. X                        xFilename = Filename;
  1228. X                    }
  1229. X                    did_cd = TRUE;
  1230. X                    if (chdir((char *)arg))
  1231. X                        emsg(e_failed);
  1232. X                    break;
  1233. X                }
  1234. X                /*FALLTHROUGH*/
  1235. X
  1236. X        case CMD_pwd:
  1237. X                if (dirname(IObuff, IOSIZE))
  1238. X                    msg(IObuff);
  1239. X                else
  1240. X                    emsg(e_unknown);
  1241. X                break;
  1242. X
  1243. X        case CMD_equal:
  1244. X                smsg("line %ld", (long)line2);
  1245. X                break;
  1246. X
  1247. X        case CMD_list:
  1248. X                i = p_list;
  1249. X                p_list = 1;
  1250. X        case CMD_number:
  1251. X        case CMD_print:
  1252. X#ifdef AMIGA
  1253. X                settmode(0);            /* set cooked mode, so output can be halted */
  1254. X#endif
  1255. X                gotocmdline(TRUE, NUL);    /* clear command line */
  1256. X                n = 0;
  1257. X                for (;;)
  1258. X                {
  1259. X                    if (p_nu || cmdidx == CMD_number)
  1260. X                    {
  1261. X                        sprintf(IObuff, "%7ld ", (long)line1);
  1262. X                        outstrn(IObuff);
  1263. X                        n += 8;
  1264. X                    }
  1265. X                    n += prt_line(nr2ptr(line1));
  1266. X                    if (++line1 > line2)
  1267. X                        break;
  1268. X                    outchar('\n');
  1269. X                    flushbuf();
  1270. X                    n = Columns;        /* call wait_return later */
  1271. X                }
  1272. X#ifdef AMIGA
  1273. X                settmode(1);
  1274. X#endif
  1275. X
  1276. X                if (cmdidx == CMD_list)
  1277. X                    p_list = i;
  1278. X
  1279. X                    /*
  1280. X                     * if we have one line that runs into the shown command,
  1281. X                     * or more than one line, call wait_return()
  1282. X                     */
  1283. X                if (n >= sc_col || global_busy)
  1284. X                {
  1285. X                    outchar('\n');
  1286. X                    wait_return(TRUE);
  1287. X                }
  1288. X                break;
  1289. X
  1290. X        case CMD_shell:
  1291. X                doshell(NULL);
  1292. X                break;
  1293. X
  1294. X        case CMD_tag:
  1295. X                dotag((char *)arg, 0, addr_count ? (int)line2 : 1);
  1296. X                break;
  1297. X
  1298. X        case CMD_pop:
  1299. X                dotag("", 1, addr_count ? (int)line2 : 1);
  1300. X                break;
  1301. X
  1302. X        case CMD_tags:
  1303. X                dotags();
  1304. X                break;
  1305. X
  1306. X        case CMD_marks:
  1307. X                domarks();
  1308. X                break;
  1309. X
  1310. X        case CMD_jumps:
  1311. X                dojumps();
  1312. X                break;
  1313. X
  1314. X        case CMD_digraphs:
  1315. X#ifdef DIGRAPHS
  1316. X                if (*arg)
  1317. X                    putdigraph((char *)arg);
  1318. X                else
  1319. X                    listdigraphs();
  1320. X#else
  1321. X                emsg("No digraphs in this version");
  1322. X#endif /* DIGRAPHS */
  1323. X                break;
  1324. X
  1325. X        case CMD_set:
  1326. X                doset((char *)arg);
  1327. X                break;
  1328. X
  1329. X        case CMD_abbreviate:
  1330. X        case CMD_cabbrev:
  1331. X        case CMD_iabbrev:
  1332. X        case CMD_cnoreabbrev:
  1333. X        case CMD_inoreabbrev:
  1334. X        case CMD_noreabbrev:
  1335. X        case CMD_unabbreviate:
  1336. X        case CMD_cunabbrev:
  1337. X        case CMD_iunabbrev:
  1338. X                i = ABBREV;
  1339. X                goto doabbr;        /* almost the same as mapping */
  1340. X
  1341. X        case CMD_cmap:
  1342. X        case CMD_imap:
  1343. X        case CMD_map:
  1344. X        case CMD_cnoremap:
  1345. X        case CMD_inoremap:
  1346. X        case CMD_noremap:
  1347. X                /*
  1348. X                 * If we are sourcing .exrc or .vimrc in current directory we
  1349. X                 * print the mappings for security reasons.
  1350. X                 */
  1351. X                if (secure)
  1352. X                {
  1353. X                    secure = 2;
  1354. X                    outtrans((char *)cmd, -1);
  1355. X                    outchar('\n');
  1356. X                }
  1357. X        case CMD_cunmap:
  1358. X        case CMD_iunmap:
  1359. X        case CMD_unmap:
  1360. X                i = 0;
  1361. Xdoabbr:
  1362. X                if (*cmd == 'c')        /* cmap, cunmap, cnoremap, etc. */
  1363. X                {
  1364. X                    i += CMDLINE;
  1365. X                    ++cmd;
  1366. X                }
  1367. X                else if (*cmd == 'i')    /* imap, iunmap, inoremap, etc. */
  1368. X                {
  1369. X                    i += INSERT;
  1370. X                    ++cmd;
  1371. X                }
  1372. X                else if (forceit || i)    /* map!, unmap!, noremap!, abbrev */
  1373. X                    i += INSERT + CMDLINE;
  1374. X                else
  1375. X                    i += NORMAL;            /* map, unmap, noremap */
  1376. X                switch (domap((*cmd == 'n') ? 2 : (*cmd == 'u'), (char *)arg, i))
  1377. X                {
  1378. X                    case 1: emsg(e_invarg);
  1379. X                            break;
  1380. X                    case 2: emsg(e_nomap);
  1381. X                            break;
  1382. X                    case 3: emsg(e_ambmap);
  1383. X                            break;
  1384. X                }
  1385. X                break;
  1386. X
  1387. X        case CMD_display:
  1388. X                outchar('\n');
  1389. X                dodis();        /* display buffer contents */
  1390. X                break;
  1391. X
  1392. X        case CMD_help:
  1393. X                help();
  1394. X                break;
  1395. X
  1396. X        case CMD_version:
  1397. X                msg(longVersion);
  1398. X                break;
  1399. X
  1400. X        case CMD_winsize:
  1401. X                line1 = getdigits((char **)&arg);
  1402. X                skipspace((char **)&arg);
  1403. X                line2 = getdigits((char **)&arg);
  1404. X                set_winsize((int)line1, (int)line2, TRUE);
  1405. X                break;
  1406. X
  1407. X        case CMD_delete:
  1408. X        case CMD_yank:
  1409. X        case CMD_rshift:
  1410. X        case CMD_lshift:
  1411. X                yankbuffer = regname;
  1412. X                startop.lnum = line1;
  1413. X                endop.lnum = line2;
  1414. X                nlines = line2 - line1 + 1;
  1415. X                mtype = MLINE;
  1416. X                Curpos.lnum = line1;
  1417. X                switch (cmdidx)
  1418. X                {
  1419. X                case CMD_delete:
  1420. X                    dodelete();
  1421. X                    break;
  1422. X                case CMD_yank:
  1423. X                    doyank(FALSE);
  1424. X                    break;
  1425. X                case CMD_rshift:
  1426. X                    doshift(RSHIFT);
  1427. X                    break;
  1428. X                case CMD_lshift:
  1429. X                    doshift(LSHIFT);
  1430. X                    break;
  1431. X                }
  1432. X                break;
  1433. X
  1434. X        case CMD_put:
  1435. X                yankbuffer = regname;
  1436. X                Curpos.lnum = line2;
  1437. X                doput(forceit ? BACKWARD : FORWARD, -1L);
  1438. X                break;
  1439. X
  1440. X        case CMD_t:
  1441. X        case CMD_copy:
  1442. X        case CMD_move:
  1443. X                n = get_address(&arg);
  1444. X                if (n == INVLNUM)
  1445. X                {
  1446. X                    emsg(e_invaddr);
  1447. X                    break;
  1448. X                }
  1449. X
  1450. X                if (cmdidx == CMD_move)
  1451. X                {
  1452. X                    if (n >= line1 && n < line2 && line2 > line1)
  1453. X                    {
  1454. X                        emsg("Move lines into themselves");
  1455. X                        break;
  1456. X                    }
  1457. X                    if (n >= line1)
  1458. X                    {
  1459. X                        --n;
  1460. X                        Curpos.lnum = n - (line2 - line1) + 1;
  1461. X                    }
  1462. X                    else
  1463. X                        Curpos.lnum = n + 1;
  1464. X                    while (line1 <= line2)
  1465. X                    {
  1466. X                            /* this undo is not efficient, but it works */
  1467. X                        u_save(line1 - 1, line1 + 1);
  1468. X                        q = delsline(line1, FALSE);
  1469. X                        u_save(n, n + 1);
  1470. X                        appendline(n, q);
  1471. X                        if (n < line1)
  1472. X                        {
  1473. X                            ++n;
  1474. X                            ++line1;
  1475. X                        }
  1476. X                        else
  1477. X                            --line2;
  1478. X                    }
  1479. X                }
  1480. X                else
  1481. X                {
  1482. X                    /*
  1483. X                     * there are three situations:
  1484. X                     * 1. destination is above line1
  1485. X                     * 2. destination is between line1 and line2
  1486. X                     * 3. destination is below line2
  1487. X                     *
  1488. X                     * n = destination (when starting)
  1489. X                     * Curpos.lnum = destination (while copying)
  1490. X                     * line1 = start of source (while copying)
  1491. X                     * line2 = end of source (while copying)
  1492. X                     */
  1493. X                    u_save(n, n + 1);
  1494. X                    Curpos.lnum = n;
  1495. X                    lnum = line2 - line1 + 1;
  1496. X                    while (line1 <= line2)
  1497. X                    {
  1498. X                        appendline(Curpos.lnum, save_line(nr2ptr(line1)));
  1499. X                                /* situation 2: skip already copied lines */
  1500. X                        if (line1 == n)
  1501. X                            line1 = Curpos.lnum;
  1502. X                        ++line1;
  1503. X                        if (Curpos.lnum < line1)
  1504. X                            ++line1;
  1505. X                        if (Curpos.lnum < line2)
  1506. X                            ++line2;
  1507. X                        ++Curpos.lnum;
  1508. X                    }
  1509. X                    msgmore((long)lnum);
  1510. X                }
  1511. X                u_clearline();
  1512. X                Curpos.col = 0;
  1513. X                updateScreen(NOT_VALID);
  1514. X                break;
  1515. X
  1516. X        case CMD_and:
  1517. X        case CMD_substitute:
  1518. X                dosub(line1, line2, (char *)arg, &nextcomm);
  1519. X                break;
  1520. X
  1521. X        case CMD_join:
  1522. X                Curpos.lnum = line1;
  1523. X                if (line1 == line2)
  1524. X                {
  1525. X                    if (line2 == line_count)
  1526. X                    {
  1527. X                        beep();
  1528. X                        break;
  1529. X                    }
  1530. X                    ++line2;
  1531. X                }
  1532. X                dodojoin(line2 - line1 + 1, !forceit, TRUE);
  1533. X                break;
  1534. X
  1535. X        case CMD_global:
  1536. X                if (forceit)
  1537. X                    *cmd = 'v';
  1538. X        case CMD_vglobal:
  1539. X                doglob(*cmd, line1, line2, (char *)arg);
  1540. X                break;
  1541. X
  1542. X        case CMD_at:                /* :[addr]@r */
  1543. X                Curpos.lnum = line2;
  1544. X                if (!doexecbuf(*arg))        /* put the register in mapbuf */
  1545. X                    beep();
  1546. X                else
  1547. X                    docmdline(NULL);        /* execute from the mapbuf */
  1548. X                break;
  1549. X
  1550. X        case CMD_bang:
  1551. X                dobang(addr_count, arg);
  1552. X                break;
  1553. X
  1554. X        case CMD_undo:
  1555. X                u_undo(1);
  1556. X                break;
  1557. X
  1558. X        case CMD_redo:
  1559. X                u_redo(1);
  1560. X                break;
  1561. X
  1562. X        case CMD_source:
  1563. X                if (forceit)    /* :so! read vi commands */
  1564. X                    openscript((char *)arg);
  1565. X                else if (dosource((char *)arg))        /* :so read ex commands */
  1566. X                    emsg(e_notopen);
  1567. X                break;
  1568. X
  1569. X        case CMD_mkvimrc:
  1570. X                if (*arg == NUL)
  1571. X                    arg = (u_char *)VIMRC_FILE;
  1572. X                /*FALLTHROUGH*/
  1573. X
  1574. X        case CMD_mkexrc:
  1575. X                {
  1576. X                    FILE    *fd;
  1577. X
  1578. X                    if (*arg == NUL)
  1579. X                        arg = (u_char *)EXRC_FILE;
  1580. X#ifdef UNIX
  1581. X                        /* with Unix it is possible to open a directory */
  1582. X                    if (isdir((char *)arg) > 0)
  1583. X                    {
  1584. X                        emsg2("\"%s\" is a directory", (char *)arg);
  1585. X                        break;
  1586. X                    }
  1587. X#endif
  1588. X                    if (!forceit && (fd = fopen((char *)arg, "r")) != NULL)
  1589. X                    {
  1590. X                        fclose(fd);
  1591. X                        emsg2("\"%s\" exists (use ! to override)", (char *)arg);
  1592. X                        break;
  1593. X                    }
  1594. X
  1595. X                    if ((fd = fopen((char *)arg, "w")) == NULL)
  1596. X                    {
  1597. X                        emsg2("Cannot open \"%s\" for writing", (char *)arg);
  1598. X                        break;
  1599. X                    }
  1600. X                    if (makemap(fd) || makeset(fd) || fclose(fd))
  1601. X                        emsg(e_write);
  1602. X                    break;
  1603. X                }
  1604. X
  1605. X        case CMD_cc:
  1606. X                    qf_jump(atoi((char *)arg));
  1607. X                    break;
  1608. X
  1609. X        case CMD_cf:
  1610. X                    if (*arg != NUL)
  1611. X                    {
  1612. X                        /*
  1613. X                         * Great trick: Insert 'ef=' before arg.
  1614. X                         * Always ok, because "cf " must be there.
  1615. X                         */
  1616. X                        arg -= 3;
  1617. X                        arg[0] = 'e';
  1618. X                        arg[1] = 'f';
  1619. X                        arg[2] = '=';
  1620. X                        doset((char *)arg);
  1621. X                    }
  1622. X                    qf_init();
  1623. X                    break;
  1624. X
  1625. X        case CMD_cl:
  1626. X                    qf_list();
  1627. X                    break;
  1628. X
  1629. X        case CMD_cn:
  1630. X                    qf_jump(-1);
  1631. X                    break;
  1632. X
  1633. X        case CMD_cp:
  1634. X                    qf_jump(-2);
  1635. X                    break;
  1636. X
  1637. X        case CMD_cq:
  1638. X                    getout(1);        /* this does not always work. why? */
  1639. X
  1640. X        case CMD_mark:
  1641. X        case CMD_k:
  1642. X                    pos = Curpos;            /* save Curpos */
  1643. X                    Curpos.lnum = line2;
  1644. X                    Curpos.col = 0;
  1645. X                    setmark(*arg);            /* set mark */
  1646. X                    Curpos = pos;            /* restore Curpos */
  1647. X                    break;
  1648. X
  1649. X#ifdef SETKEYMAP
  1650. X        case CMD_setkeymap:
  1651. X                    set_keymap(arg);
  1652. X                    break;
  1653. X#endif
  1654. X
  1655. X        case CMD_center:
  1656. X        case CMD_right:
  1657. X        case CMD_left:
  1658. X                    do_align(line1, line2, atoi((char *)arg),
  1659. X                            cmdidx == CMD_center ? 0 : cmdidx == CMD_right ? 1 : -1);
  1660. X                    break;
  1661. X
  1662. X        case CMD_make:
  1663. X                    domake((char *)arg);
  1664. X                    break;
  1665. X
  1666. X        default:
  1667. X                    emsg(e_invcmd);
  1668. X    }
  1669. X
  1670. X
  1671. Xdoend:
  1672. X    forceit = FALSE;        /* reset now so it can be used in getfile() */
  1673. X    return nextcomm;
  1674. X}
  1675. X
  1676. X/*
  1677. X * handle the :! command.
  1678. X * We replace the extra bangs by the previously entered command and remember
  1679. X * the command.
  1680. X */
  1681. X    static void
  1682. Xdobang(addr_count, arg)
  1683. X    int        addr_count;
  1684. X    u_char    *arg;
  1685. X{
  1686. X    static    char    *prevcmd = NULL;        /* the previous command */
  1687. X    char            *t;
  1688. X    char            *trailarg;
  1689. X    int             len;
  1690. X
  1691. X    /*
  1692. X     * Disallow shell commands from .exrc and .vimrc in current directory for
  1693. X     * security reasons.
  1694. X     */
  1695. X    if (secure)
  1696. X    {
  1697. X        secure = 2;
  1698. X        emsg(e_curdir);
  1699. X        return;
  1700. X    }
  1701. X    len = strlen((char *)arg) + 1;
  1702. X
  1703. X    if (Changed)
  1704. X        autowrite();
  1705. X    /*
  1706. X     * try to find an embedded bang, like in :!<cmd> ! [args]
  1707. X     * (:!! is indicated by the 'forceit' variable)
  1708. X     */
  1709. X    trailarg = (char *)arg;
  1710. X    skiptospace(&trailarg);
  1711. X    skipspace(&trailarg);
  1712. X    if (*trailarg == '!')
  1713. X        *trailarg++ = NUL;
  1714. X    else
  1715. X        trailarg = NULL;
  1716. X
  1717. X    if (forceit || trailarg != NULL)            /* use the previous command */
  1718. X    {
  1719. X        if (prevcmd == NULL)
  1720. X        {
  1721. X            emsg(e_noprev);
  1722. X            return;
  1723. X        }
  1724. X        len += strlen(prevcmd) * (trailarg != NULL && forceit ? 2 : 1);
  1725. X    }
  1726. X
  1727. X    if (len > CMDBUFFSIZE)
  1728. X    {
  1729. X        emsg(e_toolong);
  1730. X        return;
  1731. X    }
  1732. X    if ((t = alloc(len)) == NULL)
  1733. X        return;
  1734. X    *t = NUL;
  1735. X    if (forceit)
  1736. X        strcpy(t, prevcmd);
  1737. X    strcat(t, (char *)arg);
  1738. X    if (trailarg != NULL)
  1739. X    {
  1740. X        strcat(t, prevcmd);
  1741. X        strcat(t, trailarg);
  1742. X    }
  1743. X    free(prevcmd);
  1744. X    prevcmd = t;
  1745. X
  1746. X    if (bangredo)            /* put cmd in redo buffer for ! command */
  1747. X    {
  1748. X        AppendToRedobuff(prevcmd);
  1749. X        AppendToRedobuff("\n");
  1750. X        bangredo = FALSE;
  1751. X    }
  1752. X        /* echo the command */
  1753. X    gotocmdline(TRUE, ':');
  1754. X    if (addr_count)                        /* :range! */
  1755. X    {
  1756. X        outnum((long)line1);
  1757. X        outchar(',');
  1758. X        outnum((long)line2);
  1759. X    }
  1760. X    outchar('!');
  1761. X    outtrans(prevcmd, -1);
  1762. X
  1763. X    if (addr_count == 0)                /* :! */
  1764. X        doshell(prevcmd); 
  1765. X    else                                /* :range! */
  1766. X        dofilter((u_char *)prevcmd, TRUE, TRUE);
  1767. X}
  1768. X
  1769. X    static int
  1770. Xautowrite()
  1771. X{
  1772. X    if (!p_aw || check_readonly() || check_fname())
  1773. X        return FALSE;
  1774. X    return (writeit(Filename, sFilename, (linenr_t)1, line_count, 0, 0, TRUE));
  1775. X}
  1776. X
  1777. X    static int
  1778. Xdowrite(arg, append)
  1779. X    u_char    *arg;
  1780. X    int        append;
  1781. X{
  1782. X    FILE    *f;
  1783. X    int        other;
  1784. X
  1785. X    /*
  1786. X     * if we have a new file name put it in the list of alternate file names
  1787. X     */
  1788. X    other = otherfile((char *)arg);
  1789. X    if (*arg != NUL && other)
  1790. X        setaltfname(strsave((char *)arg), strsave((char *)arg), (linenr_t)1, TRUE);
  1791. X
  1792. X    /*
  1793. X     * writing to the current file is not allowed in readonly mode
  1794. X     */
  1795. X    if ((*arg == NUL || !other) && check_readonly())
  1796. X        return FALSE;
  1797. X
  1798. X    /*
  1799. X     * write to current file
  1800. X     */
  1801. X    if (*arg == NUL || !other)
  1802. X    {
  1803. X        if (check_fname())
  1804. X            return FALSE;
  1805. X        return (writeit(Filename, sFilename, line1, line2, append, forceit, TRUE));
  1806. X    }
  1807. X
  1808. X    /*
  1809. X     * write to other file; overwriting only allowed with '!'
  1810. X     */
  1811. X    if (!forceit && !append && !p_wa && (f = fopen((char *)arg, "r")) != NULL)
  1812. X    {                                /* don't overwrite existing file */
  1813. X            fclose(f);
  1814. X#ifdef UNIX
  1815. X                /* with UNIX it is possible to open a directory */
  1816. X            if (isdir((char *)arg) > 0)
  1817. X                emsg2("\"%s\" is a directory", (char *)arg);
  1818. X            else
  1819. X#endif
  1820. X                emsg(e_exists);
  1821. X            return 0;
  1822. X    }
  1823. X    return (writeit((char *)arg, NULL, line1, line2, append, forceit, TRUE));
  1824. X}
  1825. X
  1826. X    static int
  1827. Xdoecmd(arg, sarg)
  1828. X    char        *arg;
  1829. X    char        *sarg;
  1830. X{
  1831. X    int            setalt;
  1832. X    char        *command = NULL;
  1833. X    int            redraw_save;
  1834. X    linenr_t    newlnum;
  1835. X
  1836. X    newlnum = doecmdlnum;
  1837. X    doecmdlnum = 0;                        /* reset it for next time */
  1838. X
  1839. X    if (*arg == '+')        /* :e +[command] file */
  1840. X    {
  1841. X        ++arg;
  1842. X        if (isspace(*arg))
  1843. X            command = "$";
  1844. X        else
  1845. X        {
  1846. X            command = arg;
  1847. X            while (*arg && !isspace(*arg))
  1848. X                ++arg;
  1849. X        }
  1850. X        if (*arg)
  1851. X            *arg++ = NUL;
  1852. X        
  1853. X        skipspace(&arg);
  1854. X    }
  1855. X
  1856. X    if (sarg == NULL)
  1857. X        sarg = arg;
  1858. X
  1859. X#ifdef AMIGA
  1860. X    fname_case(arg);                /* set correct case for filename */
  1861. X#endif
  1862. X
  1863. X    setalt = (*arg != NUL && otherfile(arg));
  1864. X    if (check_changed(FALSE))
  1865. X    {
  1866. X        if (setalt)
  1867. X            setaltfname(strsave(arg), strsave(sarg), (linenr_t)1, TRUE);
  1868. X        return FALSE;
  1869. X    }
  1870. X    if (setalt)
  1871. X    {
  1872. X        setaltfname(Filename, sFilename, Curpos.lnum, FALSE);
  1873. X        Filename = NULL;
  1874. X        sFilename = NULL;
  1875. X        setfname(arg, sarg);
  1876. X    }
  1877. X    else if (newlnum == 0)
  1878. X        newlnum = Curpos.lnum;
  1879. X    maketitle();
  1880. X    if (check_fname())
  1881. X        return FALSE;
  1882. X
  1883. X    /* clear mem and read file */
  1884. X    freeall();
  1885. X    filealloc();
  1886. X    startop.lnum = 0;    /* clear '[ and '] marks */
  1887. X    endop.lnum = 0;
  1888. X
  1889. X    redraw_save = RedrawingDisabled;
  1890. X    RedrawingDisabled = TRUE;        /* don't redraw until the cursor is in
  1891. X                                     * the right line */
  1892. X    startscript();                    /* re-start auto script file */
  1893. X    readfile(Filename, sFilename, (linenr_t)0, TRUE);
  1894. X    if (newlnum && command == NULL)
  1895. X    {
  1896. X        if (newlnum != INVLNUM)
  1897. X            Curpos.lnum = newlnum;
  1898. X        else
  1899. X            Curpos.lnum = line_count;
  1900. X        Curpos.col = 0;
  1901. X    }
  1902. X    UNCHANGED;
  1903. X    if (command)
  1904. X        docmdline((u_char *)command);
  1905. X    RedrawingDisabled = redraw_save;    /* cursupdate() will redraw the screen later */
  1906. X    if (p_im)
  1907. X        stuffReadbuff("i");            /* start editing in insert mode */
  1908. X    return TRUE;
  1909. X}
  1910. X
  1911. X    static void
  1912. Xdoshell(cmd)
  1913. X    char    *cmd;
  1914. X{
  1915. X    /*
  1916. X     * Disallow shell commands from .exrc and .vimrc in current directory for
  1917. X     * security reasons.
  1918. X     */
  1919. X    if (secure)
  1920. X    {
  1921. X        secure = 2;
  1922. X        emsg(e_curdir);
  1923. X        return;
  1924. X    }
  1925. X    stoptermcap();
  1926. X    outchar('\n');                    /* shift screen one line up */
  1927. X
  1928. X        /* warning message before calling the shell */
  1929. X    if (p_warn && Changed)
  1930. X    {
  1931. X        gotocmdline(TRUE, NUL);
  1932. X        outstr("[No write since last change]\n");
  1933. X    }
  1934. X    call_shell(cmd, 0, TRUE);
  1935. X
  1936. X#ifdef AMIGA
  1937. X    wait_return(!term_console);        /* see below */
  1938. X#else
  1939. X    wait_return(TRUE);                /* includes starttermcap() */
  1940. X#endif
  1941. X
  1942. X    /*
  1943. X     * In an Amiga window redrawing is caused by asking the window size.
  1944. X     * If we got an interrupt this will not work. The chance that the window
  1945. X     * size is wrong is very small, but we need to redraw the screen.
  1946. X     */
  1947. X#ifdef AMIGA
  1948. X    if (term_console)
  1949. X    {
  1950. X        outstr("\033[0 q");     /* get window size */
  1951. X        if (got_int)
  1952. X            must_redraw = CLEAR;    /* if got_int is TRUE we have to redraw */
  1953. X        else
  1954. X            must_redraw = FALSE;    /* no extra redraw needed */
  1955. X    }
  1956. X#endif /* AMIGA */
  1957. X}
  1958. X
  1959. X/*
  1960. X * dofilter: filter lines through a command given by the user
  1961. X *
  1962. X * We use temp files and the call_shell() routine here. This would normally
  1963. X * be done using pipes on a UNIX machine, but this is more portable to
  1964. X * the machines we usually run on. The call_shell() routine needs to be able
  1965. X * to deal with redirection somehow, and should handle things like looking
  1966. X * at the PATH env. variable, and adding reasonable extensions to the
  1967. X * command name given by the user. All reasonable versions of call_shell()
  1968. X * do this.
  1969. X * We use input redirection if do_in is TRUE.
  1970. X * We use output redirection if do_out is TRUE.
  1971. X */
  1972. X    static void
  1973. Xdofilter(buff, do_in, do_out)
  1974. X    u_char        *buff;
  1975. X    int            do_in, do_out;
  1976. X{
  1977. X#ifdef LATTICE
  1978. X    char        itmp[L_tmpnam];        /* use tmpnam() */
  1979. X    char        otmp[L_tmpnam];
  1980. X#else
  1981. X    char        itmp[TMPNAMELEN];
  1982. X    char        otmp[TMPNAMELEN];
  1983. X#endif
  1984. X    linenr_t     linecount;
  1985. X
  1986. X    /*
  1987. X     * Disallow shell commands from .exrc and .vimrc in current directory for
  1988. X     * security reasons.
  1989. X     */
  1990. X    if (secure)
  1991. X    {
  1992. X        secure = 2;
  1993. X        emsg(e_curdir);
  1994. X        return;
  1995. X    }
  1996. X    if (*buff == NUL)        /* no filter command */
  1997. X        return;
  1998. X    linecount = line2 - line1 + 1;
  1999. X    Curpos.lnum = line1;
  2000. X    Curpos.col = 0;
  2001. X    /* cursupdate(); */
  2002. X
  2003. X    /*
  2004. X     * 1. Form temp file names
  2005. X     * 2. Write the lines to a temp file
  2006. X     * 3. Run the filter command on the temp file
  2007. X     * 4. Read the output of the command into the buffer
  2008. X     * 5. Delete the original lines to be filtered
  2009. X     * 6. Remove the temp files
  2010. X     */
  2011. X
  2012. X#ifndef LATTICE
  2013. X    /* for lattice we use tmpnam(), which will make its own name */
  2014. X    strcpy(itmp, TMPNAME1);
  2015. X    strcpy(otmp, TMPNAME2);
  2016. X#endif
  2017. X
  2018. X    if ((do_in && *mktemp(itmp) == NUL) || (do_out && *mktemp(otmp) == NUL))
  2019. X    {
  2020. X        emsg(e_notmp);
  2021. X        return;
  2022. X    }
  2023. X
  2024. X/*
  2025. X * ! command will be overwritten by next mesages
  2026. X * This is a trade off between showing the command and not scrolling the
  2027. X * text one line up (problem on slow terminals).
  2028. X */
  2029. X    must_redraw = CLEAR;        /* screen has been shifted up one line */
  2030. X    if (do_in && !writeit(itmp, NULL, line1, line2, FALSE, 0, FALSE))
  2031. X    {
  2032. X        outchar('\n');            /* keep message from writeit() */
  2033. X        emsg(e_notcreate);
  2034. X        return;
  2035. X    }
  2036. X    if (!do_out)
  2037. X        outchar('\n');
  2038. X
  2039. X#ifdef UNIX
  2040. X/*
  2041. X * put braces around the command (for concatenated commands)
  2042. X */
  2043. X     sprintf(IObuff, "(%s)", (char *)buff);
  2044. X    if (do_in)
  2045. X    {
  2046. X        strcat(IObuff, " < ");
  2047. X        strcat(IObuff, itmp);
  2048. X    }
  2049. X    if (do_out)
  2050. X    {
  2051. X        strcat(IObuff, " > ");
  2052. X        strcat(IObuff, otmp);
  2053. X    }
  2054. X#else
  2055. X/*
  2056. X * for shells that don't understand braces around commands, at least allow
  2057. X * the use of commands in a pipe.
  2058. X */
  2059. X    strcpy(IObuff, (char *)buff);
  2060. X    if (do_in)
  2061. X    {
  2062. X        char        *p;
  2063. X    /*
  2064. X     * If there is a pipe, we have to put the '<' in front of it
  2065. X     */
  2066. X        p = strchr(IObuff, '|');
  2067. X        if (p)
  2068. X            *p = NUL;
  2069. X        strcat(IObuff, " < ");
  2070. X        strcat(IObuff, itmp);
  2071. X        p = strchr((char *)buff, '|');
  2072. X        if (p)
  2073. X            strcat(IObuff, p);
  2074. X    }
  2075. X    if (do_out)
  2076. X    {
  2077. X        strcat(IObuff, " > ");
  2078. X        strcat(IObuff, otmp);
  2079. X    }
  2080. X#endif
  2081. X
  2082. X    call_shell(IObuff, 1, FALSE);    /* errors are ignored, so you can see the error
  2083. X                                   messages from the command; use 'u' to fix the
  2084. X                                   text */
  2085. X
  2086. X    if (do_out)
  2087. X    {
  2088. X        if (!u_save((linenr_t)(line2), (linenr_t)(line2 + 1)))
  2089. X        {
  2090. X            linecount = 0;
  2091. X            goto error;
  2092. X        }
  2093. X        if (readfile(otmp, NULL, line2, FALSE))
  2094. X        {
  2095. X            outchar ('\n');
  2096. X            emsg(e_notread);
  2097. X            linecount = 0;
  2098. X            goto error;
  2099. X        }
  2100. X
  2101. X        if (do_in)
  2102. X        {
  2103. X            Curpos.lnum = line1;
  2104. X            dellines(linecount, TRUE, TRUE);
  2105. X        }
  2106. X    }
  2107. X    else
  2108. X    {
  2109. Xerror:
  2110. X        wait_return(FALSE);
  2111. X    }
  2112. X    updateScreen(CLEAR);        /* do this before messages below */
  2113. X
  2114. X    if (linecount > p_report)
  2115. X    {
  2116. X        if (!do_in && do_out)
  2117. X            msgmore(linecount);
  2118. X        else
  2119. X            smsg("%ld lines filtered", (long)linecount);
  2120. X    }
  2121. X    remove(itmp);
  2122. X    remove(otmp);
  2123. X    return;
  2124. X}
  2125. X
  2126. X    static void
  2127. Xdomake(arg)
  2128. X    char *arg;
  2129. X{
  2130. X    if (*p_ef == NUL)
  2131. X    {
  2132. X        emsg("errorfile option not set");
  2133. X        return;
  2134. X    }
  2135. X    if (Changed)
  2136. X        autowrite();
  2137. X    remove(p_ef);
  2138. X    outchar(':');
  2139. X    outstr(arg);        /* show what we are doing */
  2140. X#ifdef UNIX
  2141. X    sprintf(IObuff, "%s |& tee %s", arg, p_ef);
  2142. X#else
  2143. X    sprintf(IObuff, "%s > %s", arg, p_ef);
  2144. X#endif
  2145. X    doshell(IObuff);
  2146. X#ifdef AMIGA
  2147. X    flushbuf();
  2148. X    vpeekc();        /* read window status report and redraw before message */
  2149. X#endif
  2150. X    qf_init();
  2151. X    remove(p_ef);
  2152. X}
  2153. X
  2154. X/* 
  2155. X * Redefine the argument list to 'str'.
  2156. X * Return TRUE for failure.
  2157. X */
  2158. X    static int
  2159. Xdoarglist(str)
  2160. X    char *str;
  2161. X{
  2162. X    int        new_numfiles = 0;
  2163. X    char    **new_files = NULL;
  2164. X    int        exp_numfiles;
  2165. X    char    **exp_files;
  2166. X    char    **t;
  2167. X    char    *p;
  2168. X    int        inquote;
  2169. X    int        i;
  2170. X
  2171. X    while (*str)
  2172. X    {
  2173. X        /*
  2174. X         * create a new entry in new_files[]
  2175. X         */
  2176. X        t = (char **)lalloc((u_long)(sizeof(char *) * (new_numfiles + 1)), TRUE);
  2177. X        if (t != NULL)
  2178. X            for (i = new_numfiles; --i >= 0; )
  2179. X                t[i] = new_files[i];
  2180. X        free(new_files);
  2181. X        if (t == NULL)
  2182. X            return TRUE;
  2183. X        new_files = t;
  2184. X        new_files[new_numfiles++] = str;
  2185. X
  2186. X        /*
  2187. X         * isolate one argument, taking quotes
  2188. X         */
  2189. X        inquote = FALSE;
  2190. X        for (p = str; *str; ++str)
  2191. X        {
  2192. X            if (*str == '\\' && *(str + 1) != NUL)
  2193. X                *p++ = *++str;
  2194. X            else
  2195. X            {
  2196. X                if (!inquote && isspace(*str))
  2197. X                    break;
  2198. X                if (*str == '"')
  2199. X                    inquote ^= TRUE;
  2200. X                else
  2201. X                    *p++ = *str;
  2202. X            }
  2203. X        }
  2204. X        skipspace(&str);
  2205. X        *p = NUL;
  2206. X    }
  2207. X    
  2208. X    if (ExpandWildCards(new_numfiles, new_files, &exp_numfiles, &exp_files, FALSE, TRUE) != 0)
  2209. X        return TRUE;
  2210. X    else if (exp_numfiles == 0)
  2211. X    {
  2212. X        emsg(e_nomatch);
  2213. X        return TRUE;
  2214. X    }
  2215. X    if (files_exp)            /* files[] has been allocated, free it */
  2216. X        FreeWild(numfiles, files);
  2217. X    else
  2218. X        files_exp = TRUE;
  2219. X    files = exp_files;
  2220. X    numfiles = exp_numfiles;
  2221. X
  2222. X    return FALSE;
  2223. X}
  2224. X
  2225. X    void
  2226. Xgotocmdline(clr, firstc)
  2227. X    int                clr;
  2228. X    int                firstc;
  2229. X{
  2230. X    int        i;
  2231. X
  2232. X    if (clr)            /* clear the bottom line(s) */
  2233. X    {
  2234. X        for (i = 0; i <= cmdoffset; ++i)
  2235. X        {
  2236. X            windgoto((int)Rows - i - 1, 0);
  2237. X            clear_line();
  2238. X        }
  2239. X        redraw_msg = TRUE;
  2240. X    }
  2241. X    windgoto((int)Rows - cmdoffset - 1, 0);
  2242. X    if (firstc)
  2243. X        outchar(firstc);
  2244. X}
  2245. X
  2246. X    void
  2247. Xgotocmdend()
  2248. X{
  2249. X    windgoto((int)Rows - 1, 0);
  2250. X    outchar('\n');
  2251. X}
  2252. X
  2253. X    static int
  2254. Xcheck_readonly()
  2255. X{
  2256. X    if (!forceit && p_ro)
  2257. X    {
  2258. X        emsg(e_readonly);
  2259. X        return TRUE;
  2260. X    }
  2261. X    return FALSE;
  2262. X}
  2263. X
  2264. X    static int
  2265. Xcheck_changed(checkaw)
  2266. X    int        checkaw;
  2267. X{
  2268. X    if (!forceit && Changed && (!checkaw || !autowrite()))
  2269. X    {
  2270. X        emsg(e_nowrtmsg);
  2271. X        return TRUE;
  2272. X    }
  2273. X    return FALSE;
  2274. X}
  2275. X
  2276. X    int
  2277. Xcheck_fname()
  2278. X{
  2279. X    if (Filename == NULL)
  2280. X    {
  2281. X        emsg(e_noname);
  2282. X        return TRUE;
  2283. X    }
  2284. X    return FALSE;
  2285. X}
  2286. X
  2287. X    static int
  2288. Xcheck_more(message)
  2289. X    int message;            /* when FALSE check only, no messages */
  2290. X{
  2291. X    if (!forceit && curfile + 1 < numfiles && quitmore == 0)
  2292. X    {
  2293. X        if (message)
  2294. X        {
  2295. X            emsg(e_more);
  2296. X            quitmore = 2;            /* next try to quit is allowed */
  2297. X        }
  2298. X        return TRUE;
  2299. X    }
  2300. X    return FALSE;
  2301. X}
  2302. X
  2303. X/*
  2304. X * try to abandon current file and edit "fname"
  2305. X * return 1 for "normal" error, 2 for "not written" error, 0 for success
  2306. X * -1 for succesfully opening another file
  2307. X */
  2308. X    int
  2309. Xgetfile(fname, sfname, setpm)
  2310. X    char    *fname;
  2311. X    char    *sfname;
  2312. X    int        setpm;
  2313. X{
  2314. X    int other;
  2315. X
  2316. X    other = otherfile(fname);
  2317. X    if (other && !forceit && Changed && !autowrite())
  2318. X    {
  2319. X        emsg(e_nowrtmsg);
  2320. X        return 2;        /* file has been changed */
  2321. X    }
  2322. X    if (setpm)
  2323. X        setpcmark();
  2324. X    if (!other)
  2325. X        return 0;        /* it's in the same file */
  2326. X    if (doecmd(fname, sfname))
  2327. X        return -1;        /* opened another file */
  2328. X    return 1;            /* error encountered */
  2329. X}
  2330. X
  2331. X/*
  2332. X * return TRUE if alternate file n is the same as the current file
  2333. X */
  2334. X    int
  2335. Xsamealtfile(n)
  2336. X    int            n;
  2337. X{
  2338. X    if (n < NUMALTFILES && altfiles[n] != NULL && Filename != NULL &&
  2339. X                    fnamecmp(altfiles[n], Filename) == 0)
  2340. X        return TRUE;
  2341. X    return FALSE;
  2342. X}
  2343. X
  2344. X/*
  2345. X * get alternate file n
  2346. X * set linenr to lnum or altlnum if lnum == 0
  2347. X * if (setpm) setpcmark
  2348. X * return 1 for failure, 0 for success
  2349. X */
  2350. X    int
  2351. Xgetaltfile(n, lnum, setpm)
  2352. X    int            n;
  2353. X    linenr_t    lnum;
  2354. X    int            setpm;
  2355. X{
  2356. X    if (n < 0 || n >= NUMALTFILES || altfiles[n] == NULL)
  2357. X    {
  2358. X        emsg(e_noalt);
  2359. X        return 1;
  2360. X    }
  2361. X    if (lnum == 0)
  2362. X        lnum = altlnum[n];        /* altlnum may be changed by getfile() */
  2363. X    RedrawingDisabled = TRUE;
  2364. X    if (getfile(altfiles[n], saltfiles[n], setpm) <= 0)
  2365. X    {
  2366. X        RedrawingDisabled = FALSE;
  2367. X        if (lnum == 0 || lnum > line_count)        /* check for valid lnum */
  2368. X            Curpos.lnum = 1;
  2369. X        else
  2370. X            Curpos.lnum = lnum;
  2371. X
  2372. X        Curpos.col = 0;
  2373. X        return 0;
  2374. X    }
  2375. X    RedrawingDisabled = FALSE;
  2376. X    return 1;
  2377. X}
  2378. X
  2379. X/*
  2380. X * get name of "n"th alternate file
  2381. X */
  2382. X     char *
  2383. Xgetaltfname(n)
  2384. X    int n;
  2385. X{
  2386. X    if (n >= NUMALTFILES)
  2387. X        return NULL;
  2388. X    return altfiles[n];
  2389. X}
  2390. X
  2391. X/*
  2392. X * put name "arg" in the list of alternate files.
  2393. X * "arg" must have been allocated
  2394. X * "lnum" is the default line number when jumping to the file
  2395. X * "newfile" must be TRUE when "arg" != current file
  2396. X */
  2397. X    static void
  2398. Xsetaltfname(arg, sarg, lnum, newfile)
  2399. X    char        *arg;
  2400. X    char        *sarg;
  2401. X    linenr_t    lnum;
  2402. X    int            newfile;
  2403. X{
  2404. X    int i;
  2405. X
  2406. X    free(altfiles[NUMALTFILES - 1]);
  2407. X    free(saltfiles[NUMALTFILES - 1]);
  2408. X    for (i = NUMALTFILES - 1; i > 0; --i)
  2409. X    {
  2410. X        altfiles[i] = altfiles[i - 1];
  2411. X        saltfiles[i] = saltfiles[i - 1];
  2412. X        altlnum[i] = altlnum[i - 1];
  2413. X    }
  2414. X    incrmarks();        /* increment file number for all jumpmarks */
  2415. X    incrtags();            /* increment file number for all tags */
  2416. X    if (newfile)
  2417. X    {
  2418. X        decrmarks();        /* decrement file number for jumpmarks in current file */
  2419. X        decrtags();            /* decrement file number for tags in current file */
  2420. X    }
  2421. X
  2422. X    altfiles[0] = arg;
  2423. X    saltfiles[0] = sarg;
  2424. X    altlnum[0] = lnum;
  2425. X}
  2426. X
  2427. X    static void
  2428. Xnextwild(buff, type)
  2429. X    u_char *buff;
  2430. X    int        type;
  2431. X{
  2432. X    int        i;
  2433. X    char    *p1, *p2;
  2434. X    int        oldlen;
  2435. X    int        difflen;
  2436. X
  2437. X    outstr("...");        /* show that we are busy */
  2438. X    flushbuf();
  2439. X    i = cmdslen;
  2440. X    cmdslen = cmdpos + 4;
  2441. X    cmdchecklen();        /* check if we caused a scrollup */
  2442. X    cmdslen = i;
  2443. X
  2444. X    for (i = cmdpos; i > 0 && buff[i - 1] != ' '; --i)
  2445. X        ;
  2446. X    oldlen = cmdpos - i;
  2447. X
  2448. X        /* add a "*" to the file name and expand it */
  2449. X    if ((p1 = addstar((char *)&buff[i], oldlen)) != NULL)
  2450. X    {
  2451. X        if ((p2 = ExpandOne((u_char *)p1, FALSE, type)) != NULL)
  2452. X        {
  2453. X            if (cmdlen + (difflen = strlen(p2) - oldlen) > CMDBUFFSIZE - 4)
  2454. X                emsg(e_toolong);
  2455. X            else
  2456. X            {
  2457. X                strncpy((char *)&buff[cmdpos + difflen], (char *)&buff[cmdpos], (size_t)(cmdlen - cmdpos));
  2458. X                strncpy((char *)&buff[i], p2, strlen(p2));
  2459. X                cmdlen += difflen;
  2460. X                cmdpos += difflen;
  2461. X            }
  2462. X            free(p2);
  2463. X        }
  2464. X        free(p1);
  2465. X    }
  2466. X    redrawcmd();
  2467. X}
  2468. X
  2469. X/*
  2470. X * Do wildcard expansion on the string 'str'.
  2471. X * Return a pointer to alloced memory containing the new string.
  2472. X * Return NULL for failure.
  2473. X *
  2474. X * mode = -2: only release file names
  2475. X * mode = -1: normal expansion, do not keep file names
  2476. X * mode =  0: normal expansion, keep file names
  2477. X * mode =  1: use next match in multiple match
  2478. X * mode =  2: use previous match in multiple match
  2479. X * mode =  3: use next match in multiple match and wrap to first
  2480. X * mode =  4: return all matches concatenated
  2481. X * mode =  5: return longest matched part
  2482. X */
  2483. X    char *
  2484. XExpandOne(str, list_notfound, mode)
  2485. X    u_char    *str;
  2486. X    int        list_notfound;
  2487. X    int        mode;
  2488. X{
  2489. X    char        *ss = NULL;
  2490. X    static char **cmd_files = NULL;      /* list of input files */
  2491. X    static int    findex;
  2492. X    int            i, found = 0;
  2493. X    int            multmatch = FALSE;
  2494. X    u_long        len;
  2495. X    char        *filesuf, *setsuf, *nextsetsuf;
  2496. X    int            filesuflen, setsuflen;
  2497. X
  2498. X/*
  2499. X * first handle the case of using an old match
  2500. X */
  2501. X    if (mode >= 1 && mode < 4)
  2502. X    {
  2503. X        if (cmd_numfiles > 0)
  2504. X        {
  2505. X            if (mode == 2)
  2506. X                --findex;
  2507. X            else    /* mode == 1 || mode == 3 */
  2508. X                ++findex;
  2509. X            if (findex < 0)
  2510. X                findex = 0;
  2511. X            if (findex > cmd_numfiles - 1)
  2512. X            {
  2513. X                if (mode == 3)
  2514. X                    findex = 0;
  2515. X                else
  2516. X                    findex = cmd_numfiles - 1;
  2517. X            }
  2518. X            return strsave(cmd_files[findex]);
  2519. X        }
  2520. X        else
  2521. X            return NULL;
  2522. X    }
  2523. X
  2524. X/* free old names */
  2525. X    if (cmd_numfiles != -1 && mode < 4)
  2526. X    {
  2527. X        FreeWild(cmd_numfiles, cmd_files);
  2528. X        cmd_numfiles = -1;
  2529. X    }
  2530. X    findex = 0;
  2531. X
  2532. X    if (mode == -2)        /* only release file name */
  2533. X        return NULL;
  2534. X
  2535. X    if (cmd_numfiles == -1)
  2536. X    {
  2537. X        if (ExpandWildCards(1, (char **)&str, &cmd_numfiles, &cmd_files, FALSE, list_notfound) != 0)
  2538. X            /* error: do nothing */;
  2539. X        else if (cmd_numfiles == 0)
  2540. X            emsg(e_nomatch);
  2541. X        else if (mode < 4)
  2542. X        {
  2543. X            if (cmd_numfiles > 1)        /* more than one match; check suffixes */
  2544. X            {
  2545. X                found = -2;
  2546. X                for (i = 0; i < cmd_numfiles; ++i)
  2547. X                {
  2548. X                    if ((filesuf = strrchr(cmd_files[i], '.')) != NULL)
  2549. X                    {
  2550. X                        filesuflen = strlen(filesuf);
  2551. X                        for (setsuf = p_su; *setsuf; setsuf = nextsetsuf)
  2552. X                        {
  2553. X                            if ((nextsetsuf = strchr(setsuf + 1, '.')) == NULL)
  2554. X                                nextsetsuf = setsuf + strlen(setsuf);
  2555. X                            setsuflen = (int)(nextsetsuf - setsuf);
  2556. X                            if (filesuflen == setsuflen &&
  2557. X                                        strncmp(setsuf, filesuf, (size_t)setsuflen) == 0)
  2558. X                                break;
  2559. X                        }
  2560. X                        if (*setsuf)                /* suffix matched: ignore file */
  2561. X                            continue;
  2562. X                    }
  2563. X                    if (found >= 0)
  2564. X                    {
  2565. X                        multmatch = TRUE;
  2566. X                        break;
  2567. X                    }
  2568. X                    found = i;
  2569. X                }
  2570. X            }
  2571. X            if (multmatch || found < 0)
  2572. X            {
  2573. X                emsg(e_toomany);
  2574. X                found = 0;                /* return first one */
  2575. X                multmatch = TRUE;        /* for found < 0 */
  2576. X            }
  2577. X            if (found >= 0 && !(multmatch && mode == -1))
  2578. X                ss = strsave(cmd_files[found]);
  2579. X        }
  2580. X    }
  2581. X
  2582. X    if (mode == 5 && cmd_numfiles > 0)        /* find longest common part */
  2583. X    {
  2584. X        for (len = 0; cmd_files[0][len]; ++len)
  2585. X        {
  2586. X            for (i = 0; i < cmd_numfiles; ++i)
  2587. X            {
  2588. X#ifdef AMIGA
  2589. X                if (toupper(cmd_files[i][len]) != toupper(cmd_files[0][len]))
  2590. X#else
  2591. X                if (cmd_files[i][len] != cmd_files[0][len])
  2592. X#endif
  2593. X                    break;
  2594. X            }
  2595. X            if (i < cmd_numfiles)
  2596. X                break;
  2597. X        }
  2598. X        ss = alloc((unsigned)len + 1);
  2599. X        if (ss)
  2600. X        {
  2601. X            strncpy(ss, cmd_files[0], (size_t)len);
  2602. X            ss[len] = NUL;
  2603. X        }
  2604. X        multmatch = TRUE;                    /* don't free the names */
  2605. X        findex = -1;                        /* next p_wc gets first one */
  2606. X    }
  2607. X
  2608. X    if (mode == 4 && cmd_numfiles > 0)        /* concatenate all file names */
  2609. X    {
  2610. X        len = 0;
  2611. X        for (i = 0; i < cmd_numfiles; ++i)
  2612. X            len += strlen(cmd_files[i]) + 1;
  2613. X        ss = lalloc(len, TRUE);
  2614. X        if (ss)
  2615. X        {
  2616. X            *ss = NUL;
  2617. X            for (i = 0; i < cmd_numfiles; ++i)
  2618. X            {
  2619. X                strcat(ss, cmd_files[i]);
  2620. X                if (i != cmd_numfiles - 1)
  2621. X                    strcat(ss, " ");
  2622. X            }
  2623. X        }
  2624. X    }
  2625. X
  2626. X    if (!multmatch || mode == -1 || mode == 4)
  2627. X    {
  2628. X        FreeWild(cmd_numfiles, cmd_files);
  2629. X        cmd_numfiles = -1;
  2630. X    }
  2631. X    return ss;
  2632. X}
  2633. X
  2634. X/*
  2635. X * show all filenames that match the string "file" with length "len"
  2636. X */
  2637. X    static void
  2638. Xshowmatches(file, len)
  2639. X    char *file;
  2640. X    int    len;
  2641. X{
  2642. X    char *file_str;
  2643. X    int num_files;
  2644. X    char **files_found;
  2645. X    int i, j, k;
  2646. X    int maxlen;
  2647. X    int lines;
  2648. X    int columns;
  2649. X
  2650. X    file_str = addstar(file, len);        /* add star to file name */
  2651. X    if (file_str != NULL)
  2652. X    {
  2653. X        outchar('\n');
  2654. X        flushbuf();
  2655. X
  2656. X        /* find all files that match the description */
  2657. X        ExpandWildCards(1, &file_str, &num_files, &files_found, FALSE, FALSE);
  2658. X
  2659. X        /* find the maximum length of the file names */
  2660. X        maxlen = 0;
  2661. X        for (i = 0; i < num_files; ++i)
  2662. X        {
  2663. X            j = strlen(files_found[i]);
  2664. X            if (j > maxlen)
  2665. X                maxlen = j;
  2666. X        }
  2667. X
  2668. X        /* compute the number of columns and lines for the listing */
  2669. X        maxlen += 2;    /* two spaces between file names */
  2670. X        columns = ((int)Columns + 2) / maxlen;
  2671. X        if (columns < 1)
  2672. X            columns = 1;
  2673. X        lines = (num_files + columns - 1) / columns;
  2674. X
  2675. X        /* list the files line by line */
  2676. X#ifdef AMIGA
  2677. X        settmode(0);        /* allow output to be halted */
  2678. X#endif
  2679. X        for (i = 0; i < lines; ++i)
  2680. X        {
  2681. X            for (k = i; k < num_files; k += lines)
  2682. X            {
  2683. X                if (k > i)
  2684. X                    for (j = maxlen - strlen(files_found[k - lines]); --j >= 0; )
  2685. X                        outchar(' ');
  2686. X                j = isdir(files_found[k]);    /* highlight directories */
  2687. X                if (j > 0)
  2688. X                {
  2689. X#ifdef AMIGA
  2690. X                    if (term_console)
  2691. X                        outstr("\033[33m");        /* use highlight color */
  2692. X                    else
  2693. X#endif /* AMIGA */
  2694. X                        outstr(T_TI);
  2695. X                }
  2696. X                outstrn(files_found[k]);
  2697. X                if (j > 0)
  2698. X                {
  2699. X#ifdef AMIGA
  2700. X                    if (term_console)
  2701. X                        outstr("\033[0m");        /* use normal color */
  2702. X                    else
  2703. X#endif /* AMIGA */
  2704. X                        outstr(T_TP);
  2705. X                }
  2706. X            }
  2707. X            outchar('\n');
  2708. X            flushbuf();
  2709. X        }
  2710. X        free(file_str);
  2711. X        FreeWild(num_files, files_found);
  2712. X#ifdef AMIGA
  2713. X        settmode(1);
  2714. X#endif
  2715. X
  2716. X        for (i = cmdoffset; --i >= 0; )    /* make room for the command */
  2717. X            outchar('\n');
  2718. X        must_redraw = CLEAR;            /* must redraw later */
  2719. X    }
  2720. X}
  2721. X
  2722. X/*
  2723. X * copy the file name into allocated memory and add a '*' at the end
  2724. X */
  2725. X    static char *
  2726. Xaddstar(fname, len)
  2727. X    char    *fname;
  2728. X    int        len;
  2729. X{
  2730. X    char    *retval;
  2731. X#ifdef MSDOS
  2732. X    int        i;
  2733. X#endif
  2734. X
  2735. X    retval = alloc(len + 4);
  2736. X    if (retval != NULL)
  2737. X    {
  2738. X        strncpy(retval, fname, (size_t)len);
  2739. X#ifdef MSDOS
  2740. X    /*
  2741. X     * if there is no dot in the file name, add "*.*" instead of "*".
  2742. X     */
  2743. X        for (i = len - 1; i >= 0; --i)
  2744. X            if (strchr(".\\/:", retval[i]))
  2745. X                break;
  2746. X        if (i < 0 || retval[i] != '.')
  2747. X        {
  2748. X            retval[len++] = '*';
  2749. X            retval[len++] = '.';
  2750. X        }
  2751. X#endif
  2752. X        retval[len] = '*';
  2753. X        retval[len + 1] = 0;
  2754. X    }
  2755. X    return retval;
  2756. X}
  2757. X
  2758. X/*
  2759. X * dosource: read the file "fname" and execute its lines as EX commands
  2760. X *
  2761. X * This function may be called recursively!
  2762. X */
  2763. X    int
  2764. Xdosource(fname)
  2765. X    register char *fname;
  2766. X{
  2767. X    register FILE    *fp;
  2768. X    register int    len;
  2769. X#ifdef MSDOS
  2770. X    int                error = FALSE;
  2771. X#endif
  2772. X
  2773. X    expand_env(fname, IObuff, IOSIZE);        /* use IObuff for expanded name */
  2774. X    if ((fp = fopen(IObuff, READBIN)) == NULL)
  2775. X        return 1;
  2776. X
  2777. X    len = 0;
  2778. X    while (fgets(IObuff + len, IOSIZE - len, fp) != NULL && !got_int)
  2779. X    {
  2780. X        len = strlen(IObuff) - 1;
  2781. X        if (len >= 0 && IObuff[len] == '\n')    /* remove trailing newline */
  2782. X        {
  2783. X                /* escaped newline, read more */
  2784. X            if (len > 0 && len < IOSIZE && IObuff[len - 1] == Ctrl('V'))
  2785. X            {
  2786. X                IObuff[len - 1] = '\n';        /* remove CTRL-V */
  2787. X                continue;
  2788. X            }
  2789. X#ifdef MSDOS
  2790. X            if (len > 0 && IObuff[len - 1] == '\r') /* trailing CR-LF */
  2791. X                --len;
  2792. X            else
  2793. X            {
  2794. X                if (!error)
  2795. X                    emsg("Warning: Wrong line separator, ^M may be missing");
  2796. X                error = TRUE;        /* lines like ":map xx yy^M" will fail */
  2797. X            }
  2798. X#endif
  2799. X            IObuff[len] = NUL;
  2800. X        }
  2801. X        breakcheck();        /* check for ^C here, so recursive :so will be broken */
  2802. X        docmdline((u_char *)IObuff);
  2803. X        len = 0;
  2804. X    }
  2805. X    fclose(fp);
  2806. X    if (got_int)
  2807. X        emsg(e_interr);
  2808. X    return 0;
  2809. X}
  2810. X
  2811. X/*
  2812. X * get single EX address
  2813. X */
  2814. X    static linenr_t
  2815. Xget_address(ptr)
  2816. X    u_char        **ptr;
  2817. X{
  2818. X    linenr_t    curpos_lnum = Curpos.lnum;
  2819. X    int            c;
  2820. X    int            i;
  2821. X    long        n;
  2822. X    u_char      *cmd;
  2823. X    FPOS        pos;
  2824. X    FPOS        *fp;
  2825. X    linenr_t    lnum;
  2826. X
  2827. X    cmd = *ptr;
  2828. X    skipspace((char **)&cmd);
  2829. X    lnum = INVLNUM;
  2830. X    do
  2831. X    {
  2832. X        switch (*cmd)
  2833. X        {
  2834. X            case '.':                         /* '.' - Cursor position */
  2835. X                        ++cmd;
  2836. X                        lnum = curpos_lnum;
  2837. X                        break;
  2838. X
  2839. X            case '$':                         /* '$' - last line */
  2840. X                        ++cmd;
  2841. X                        lnum = line_count;
  2842. X                        break;
  2843. X
  2844. X            case '\'':                         /* ''' - mark */
  2845. X                        if (*++cmd == NUL || (fp = getmark(*cmd++, FALSE)) == NULL)
  2846. X                        {
  2847. X                            emsg(e_umark);
  2848. X                            goto error;
  2849. X                        }
  2850. X                        lnum = fp->lnum;
  2851. X                        break;
  2852. X
  2853. X            case '/':
  2854. X            case '?':                        /* '/' or '?' - search */
  2855. X                        c = *cmd++;
  2856. X                        pos = Curpos;        /* save Curpos */
  2857. X                        Curpos.col = -1;    /* searchit() will increment the col */
  2858. X                        if (c == '/')
  2859. X                        {
  2860. X                             if (Curpos.lnum == line_count)    /* :/pat on last line */
  2861. X                                Curpos.lnum = 1;
  2862. X                            else
  2863. X                                ++Curpos.lnum;
  2864. X                        }
  2865. X                        searchcmdlen = 0;
  2866. X                        if (dosearch(c, (char *)cmd, FALSE, (long)1, FALSE))
  2867. X                            lnum = Curpos.lnum;
  2868. X                        Curpos = pos;
  2869. X                
  2870. X                        cmd += searchcmdlen;    /* adjust command string pointer */
  2871. X                        break;
  2872. X
  2873. X            default:
  2874. X                        if (isdigit(*cmd))                /* absolute line number */
  2875. X                            lnum = getdigits((char **)&cmd);
  2876. X        }
  2877. X        
  2878. X        while (*cmd == '-' || *cmd == '+')
  2879. X        {
  2880. X            if (lnum == INVLNUM)
  2881. X                lnum = curpos_lnum;
  2882. X            i = *cmd++;
  2883. X            if (!isdigit(*cmd))    /* '+' is '+1', but '+0' is not '+1' */
  2884. X                n = 1;
  2885. X            else 
  2886. X                n = getdigits((char **)&cmd);
  2887. X            if (i == '-')
  2888. X                lnum -= n;
  2889. X            else
  2890. X                lnum += n;
  2891. X        }
  2892. X
  2893. X        curpos_lnum = lnum;
  2894. X    } while (*cmd == '/' || *cmd == '?');
  2895. X
  2896. Xerror:
  2897. X    *ptr = cmd;
  2898. X    return lnum;
  2899. X}
  2900. X
  2901. X/*
  2902. X * align text:
  2903. X * type = -1  left aligned
  2904. X * type = 0   centered
  2905. X * type = 1   right aligned
  2906. X */
  2907. X    static void
  2908. Xdo_align(start, end, width, type)
  2909. X    linenr_t    start;
  2910. X    linenr_t    end;
  2911. X    int            width;
  2912. X    int            type;
  2913. X{
  2914. X    FPOS    pos;
  2915. X    int        len;
  2916. X    int        indent = 0;
  2917. X
  2918. X    pos = Curpos;
  2919. X    if (type == -1)        /* left align: width is used for new indent */
  2920. X    {
  2921. X        if (width >= 0)
  2922. X            indent = width;
  2923. X    }
  2924. X    else
  2925. X    {
  2926. X        if (width <= 0)
  2927. X            width = p_tw;
  2928. X        if (width == 0)
  2929. X            width = 80;
  2930. X    }
  2931. X
  2932. X    if (!u_save((linenr_t)(line1 - 1), (linenr_t)(line2 + 1)))
  2933. X        return;
  2934. X    for (Curpos.lnum = start; Curpos.lnum <= end; ++Curpos.lnum)
  2935. X    {
  2936. X        set_indent(indent, TRUE);                /* remove existing indent */
  2937. X        if (type == -1)                            /* left align */
  2938. X            continue;
  2939. X        len = strsize(nr2ptr(Curpos.lnum));        /* get line lenght */
  2940. X        if (len < width)
  2941. X            switch (type)
  2942. X            {
  2943. X            case 0:        set_indent((width - len) / 2, FALSE);    /* center */
  2944. X                        break;
  2945. X            case 1:        set_indent(width - len, FALSE);            /* right */
  2946. X                        break;
  2947. X            }
  2948. X    }
  2949. X    Curpos = pos;
  2950. X    beginline(TRUE);
  2951. X    updateScreen(NOT_VALID);
  2952. X}
  2953. END_OF_FILE
  2954. if test 60249 -ne `wc -c <'vim/src/cmdline.c'`; then
  2955.     echo shar: \"'vim/src/cmdline.c'\" unpacked with wrong size!
  2956. fi
  2957. chmod +x 'vim/src/cmdline.c'
  2958. # end of 'vim/src/cmdline.c'
  2959. fi
  2960. echo shar: End of archive 25 \(of 25\).
  2961. cp /dev/null ark25isdone
  2962. MISSING=""
  2963. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
  2964.     if test ! -f ark${I}isdone ; then
  2965.     MISSING="${MISSING} ${I}"
  2966.     fi
  2967. done
  2968. if test "${MISSING}" = "" ; then
  2969.     echo You have unpacked all 25 archives.
  2970.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2971. else
  2972.     echo You still need to unpack the following archives:
  2973.     echo "        " ${MISSING}
  2974. fi
  2975. ##  End of shell archive.
  2976. exit 0
  2977.  
  2978. ===============================================================================
  2979. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  2980. Oce Nederland B.V., Research & Development | necessarily represent the position
  2981. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  2982. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  2983. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  2984.  
  2985. exit 0 # Just in case...
  2986.