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

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i060:  vim - Vi IMitation editor, v2.0, Part10/25
  4. Message-ID: <1993Dec21.034931.28161@sparky.sterling.com>
  5. X-Md4-Signature: 596994c064b4a2c8e296662aed8f7cf2
  6. Keywords: utility, editor, vi, vim
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: Sterling Software
  9. Date: Tue, 21 Dec 1993 03:49:31 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 60
  14. Archive-name: vim/part10
  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 10 (of 25)."
  25. # Contents:  vim/src/edit.c vim/src/unix.c
  26. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:05 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'vim/src/edit.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'vim/src/edit.c'\"
  30. else
  31. echo shar: Extracting \"'vim/src/edit.c'\" \(22105 characters\)
  32. sed "s/^X//" >'vim/src/edit.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 * edit.c: functions for insert mode
  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 "ops.h"    /* for operator */
  52. X
  53. Xextern u_char *get_inserted();
  54. Xstatic void start_arrow __ARGS((void));
  55. Xstatic void stop_arrow __ARGS((void));
  56. Xstatic void stop_insert __ARGS((void));
  57. Xstatic int echeck_abbr __ARGS((int));
  58. X
  59. Xint arrow_used;                /* Normally FALSE, set to TRUE after hitting
  60. X                             * cursor key in insert mode. Used by vgetorpeek()
  61. X                             * to decide when to call u_sync() */
  62. Xint restart_edit = 0;        /* call edit when next command finished */
  63. Xstatic u_char    *last_insert = NULL;
  64. X                            /* the text of the previous insert */
  65. Xstatic int        last_insert_skip;
  66. X                            /* number of chars in front of the previous insert */
  67. Xstatic int        new_insert_skip;
  68. X                            /* number of chars in front of the current insert */
  69. X
  70. X    void
  71. Xedit(count)
  72. X    long count;
  73. X{
  74. X    u_char         c;
  75. X    u_char         cc;
  76. X    u_char        *ptr;
  77. X    u_char        *saved_line = NULL;        /* saved line for replace mode */
  78. X    linenr_t     saved_lnum = 0;        /* lnum of saved line */
  79. X    int             saved_char = NUL;        /* char replaced by NL */
  80. X    linenr_t     lnum;
  81. X    int          temp = 0;
  82. X    int             mode;
  83. X    int             nextc = 0;
  84. X    int             lastc = 0;
  85. X    colnr_t         mincol;
  86. X
  87. X    if (restart_edit)
  88. X    {
  89. X        arrow_used = TRUE;
  90. X        restart_edit = 0;
  91. X    }
  92. X    else
  93. X        arrow_used = FALSE;
  94. X
  95. X#ifdef DIGRAPHS
  96. X    dodigraph(-1);                    /* clear digraphs */
  97. X#endif
  98. X
  99. X/*
  100. X * Get the current length of the redo buffer, those characters have to be
  101. X * skipped if we want to get to the inserted characters.
  102. X */
  103. X
  104. X    ptr = get_inserted();
  105. X    new_insert_skip = strlen((char *)ptr);
  106. X    free(ptr);
  107. X
  108. X    old_indent = 0;
  109. X
  110. X    for (;;)
  111. X    {
  112. X        if (arrow_used)        /* don't repeat insert when arrow key used */
  113. X            count = 0;
  114. X
  115. X        set_want_col = TRUE;    /* set Curswant in case of K_DARROW or K_UARROW */
  116. X        cursupdate();        /* Figure out where the cursor is based on Curpos. */
  117. X        showruler(0);
  118. X        setcursor();
  119. X        if (nextc)            /* character remaining from CTRL-V */
  120. X        {
  121. X            c = nextc;
  122. X            nextc = 0;
  123. X        }
  124. X        else
  125. X        {
  126. X            c = vgetc();
  127. X            if (c == Ctrl('C') && got_int)
  128. X                got_int = FALSE;
  129. X        }
  130. X        if (c != Ctrl('D'))            /* remember to detect ^^D and 0^D */
  131. X            lastc = c;
  132. X
  133. X/*
  134. X * In replace mode a backspace puts the original text back.
  135. X * We save the current line to be able to do that.
  136. X * If characters are appended to the line, they will be deleted.
  137. X * If we start a new line (with CR) the saved line will be empty, thus
  138. X * the characters will be deleted.
  139. X * If we backspace over the new line, that line will be saved.
  140. X */
  141. X        if (State == REPLACE && saved_lnum != Curpos.lnum)
  142. X        {
  143. X            free(saved_line);
  144. X            saved_line = (u_char *)strsave((char *)nr2ptr(Curpos.lnum));
  145. X            saved_lnum = Curpos.lnum;
  146. X        }
  147. X
  148. X#ifdef DIGRAPHS
  149. X        c = dodigraph(c);
  150. X#endif /* DIGRAPHS */
  151. X
  152. X        if (c == Ctrl('V'))
  153. X        {
  154. X            outchar('^');
  155. X            AppendToRedobuff("\026");    /* CTRL-V */
  156. X            cursupdate();
  157. X            setcursor();
  158. X
  159. X            c = get_literal(&nextc);
  160. X
  161. X        /* erase the '^' */
  162. X            if ((cc = gcharCurpos()) == NUL || (cc == TAB && !p_list))
  163. X                outchar(' ');
  164. X            else
  165. X                outstrn(transchar(cc));
  166. X
  167. X            if (isidchar(c) || !echeck_abbr(c))
  168. X                insertchar(c);
  169. X            continue;
  170. X        }
  171. X        switch (c)        /* handle character in insert mode */
  172. X        {
  173. X              case Ctrl('O'):        /* execute one command */
  174. X                if (echeck_abbr(Ctrl('O') + 0x100))
  175. X                    break;
  176. X                  count = 0;
  177. X                if (State == INSERT)
  178. X                    restart_edit = 'I';
  179. X                else
  180. X                    restart_edit = 'R';
  181. X                goto doESCkey;
  182. X
  183. X              case ESC:             /* an escape ends input mode */
  184. X                if (echeck_abbr(ESC + 0x100))
  185. X                    break;
  186. X                /*FALLTHROUGH*/
  187. X
  188. X              case Ctrl('C'):
  189. XdoESCkey:
  190. X                if (!arrow_used)
  191. X                {
  192. X                    AppendToRedobuff(ESC_STR);
  193. X
  194. X                    if (--count > 0)        /* repeat what was typed */
  195. X                    {
  196. X                            start_redo_ins();
  197. X                            continue;
  198. X                    }
  199. X                    stop_insert();
  200. X                }
  201. X                set_want_col = TRUE;
  202. X
  203. X                /*
  204. X                 * The cursor should end up on the last inserted character.
  205. X                 */
  206. X                if (Curpos.col != 0 && (!restart_edit || gcharCurpos() == NUL) && !p_ri)
  207. X                    decCurpos();
  208. X                if (extraspace)            /* did reverse replace in column 0 */
  209. X                {
  210. X                    delchar(FALSE);
  211. X                    updateline();
  212. X                    extraspace = FALSE;
  213. X                }
  214. X                State = NORMAL;
  215. X                script_winsize_pp();    /* may need to put :winsize in script */
  216. X                    /* inchar() may have deleted the "INSERT" message */
  217. X                if (Recording)
  218. X                    showmode();
  219. X                else if (p_smd)
  220. X                    msg("");
  221. X                free(saved_line);
  222. X                old_indent = 0;
  223. X                return;
  224. X
  225. X                  /*
  226. X                 * Insert the previously inserted text.
  227. X                 * Last_insert actually is a copy of the redo buffer, so we
  228. X                 * first have to remove the command.
  229. X                 * For ^@ the trailing ESC will end the insert.
  230. X                 */
  231. X              case K_ZERO:
  232. X              case Ctrl('A'):
  233. X                stuff_inserted(NUL, 1L, (c == Ctrl('A')));
  234. X                break;
  235. X
  236. X                  /*
  237. X                 * insert the contents of a register
  238. X                 */
  239. X              case Ctrl('R'):
  240. X                  if (!insertbuf(vgetc()))
  241. X                    beep();
  242. X                break;
  243. X
  244. X              case Ctrl('P'):            /* toggle reverse insert mode */
  245. X                  p_ri = !p_ri;
  246. X                showmode();
  247. X                break;
  248. X
  249. X                /*
  250. X                 * If the cursor is on an indent, ^T/^D insert/delete one
  251. X                 * shiftwidth. Otherwise ^T/^D behave like a TAB/backspace.
  252. X                 * This isn't completely compatible with
  253. X                 * vi, but the difference isn't very noticeable and now you can
  254. X                 * mix ^D/backspace and ^T/TAB without thinking about which one
  255. X                 * must be used.
  256. X                 */
  257. X              case Ctrl('T'):        /* make indent one shiftwidth greater */
  258. X              case Ctrl('D'):         /* make indent one shiftwidth smaller */
  259. X                stop_arrow();
  260. X                AppendCharToRedobuff(c);
  261. X                if ((lastc == '0' || lastc == '^') && Curpos.col)
  262. X                {
  263. X                    --Curpos.col;
  264. X                    delchar(FALSE);            /* delete the '^' or '0' */
  265. X                    if (lastc == '^')
  266. X                        old_indent = get_indent();    /* remember current indent */
  267. X
  268. X                        /* determine offset from first non-blank */
  269. X                    temp = Curpos.col;
  270. X                    beginline(TRUE);
  271. X                    temp -= Curpos.col;
  272. X                    set_indent(0, TRUE);    /* remove all indent */
  273. X                }
  274. X                else
  275. X                {
  276. X                        /* determine offset from first non-blank */
  277. X                    temp = Curpos.col;
  278. X                    beginline(TRUE);
  279. X                    temp -= Curpos.col;
  280. X
  281. X                    shift_line(c == Ctrl('D'), TRUE);
  282. X
  283. X                        /* try to put cursor on same character */
  284. X                    temp += Curpos.col;
  285. X                }
  286. X                if (temp <= 0)
  287. X                    Curpos.col = 0;
  288. X                else
  289. X                    Curpos.col = temp;
  290. X                did_ai = FALSE;
  291. X                did_si = FALSE;
  292. X                can_si = FALSE;
  293. X                  goto redraw;
  294. X
  295. X              case BS:
  296. X              case DEL:
  297. Xnextbs:
  298. X                mode = 0;
  299. Xdodel:
  300. X                /* can't delete anything in an empty file */
  301. X                /* can't backup past first character in buffer */
  302. X                /* can't backup past starting point unless 'backspace' > 1 */
  303. X                /* can backup to a previous line if 'backspace' == 0 */
  304. X                if (bufempty() || (!p_ri &&
  305. X                        ((Curpos.lnum == 1 && Curpos.col <= 0) ||
  306. X                        (p_bs < 2 && (arrow_used ||
  307. X                            (Curpos.lnum == Insstart.lnum &&
  308. X                            Curpos.col <= Insstart.col) ||
  309. X                            (Curpos.col <= 0 && p_bs == 0))))))
  310. X                {
  311. X                    beep();
  312. X                    goto redraw;
  313. X                }
  314. X
  315. X                stop_arrow();
  316. X                if (p_ri)
  317. X                    incCurpos();
  318. X                if (Curpos.col <= 0)        /* delete newline! */
  319. X                {
  320. X                    lnum = Insstart.lnum;
  321. X                    if (Curpos.lnum == Insstart.lnum || p_ri)
  322. X                    {
  323. X                        if (!u_save((linenr_t)(Curpos.lnum - 2), (linenr_t)(Curpos.lnum + 1)))
  324. X                            goto redraw;
  325. X                        --Insstart.lnum;
  326. X                        Insstart.col = 0;
  327. X                    }
  328. X                /* in replace mode, in the line we started replacing, we
  329. X                                                        only move the cursor */
  330. X                    if (State != REPLACE || Curpos.lnum > lnum)
  331. X                    {
  332. X                        temp = gcharCurpos();        /* remember current char */
  333. X                        --Curpos.lnum;
  334. X                        dojoin(FALSE, TRUE);
  335. X                        if (temp == NUL && gcharCurpos() != NUL)
  336. X                            ++Curpos.col;
  337. X                        if (saved_char)                /* restore what NL replaced */
  338. X                        {
  339. X                            State = NORMAL;            /* no replace for this char */
  340. X                            inschar(saved_char);    /* but no showmatch */
  341. X                            State = REPLACE;
  342. X                            saved_char = NUL;
  343. X                            if (!p_ri)
  344. X                                decCurpos();
  345. X                        }
  346. X                        else if (p_ri)                /* in reverse mode */
  347. X                            saved_lnum = 0;            /* save this line again */
  348. X                    }
  349. X                    else
  350. X                        decCurpos();
  351. X                    did_ai = FALSE;
  352. X                }
  353. X                else
  354. X                {
  355. X                    if (p_ri && State != REPLACE)
  356. X                        decCurpos();
  357. X                    mincol = 0;
  358. X                    if (mode == 3 && !p_ri && p_ai)    /* keep indent */
  359. X                    {
  360. X                        temp = Curpos.col;
  361. X                        beginline(TRUE);
  362. X                        if (Curpos.col < temp)
  363. X                            mincol = Curpos.col;
  364. X                        Curpos.col = temp;
  365. X                    }
  366. X
  367. X                    /* delete upto starting point, start of line or previous word */
  368. X                    do
  369. X                    {
  370. X                        if (!p_ri)
  371. X                            decCurpos();
  372. X
  373. X                                /* start of word? */
  374. X                        if (mode == 1 && !isspace(gcharCurpos()))
  375. X                        {
  376. X                            mode = 2;
  377. X                            temp = isidchar(gcharCurpos());
  378. X                        }
  379. X                                /* end of word? */
  380. X                        else if (mode == 2 && (isspace(cc = gcharCurpos()) || isidchar(cc) != temp))
  381. X                        {
  382. X                            if (!p_ri)
  383. X                                incCurpos();
  384. X                            else if (State == REPLACE)
  385. X                                decCurpos();
  386. X                            break;
  387. X                        }
  388. X                        if (State == REPLACE)
  389. X                        {
  390. X                            if (saved_line)
  391. X                            {
  392. X                                if (extraspace)
  393. X                                {
  394. X                                    if ((int)strlen(nr2ptr(Curpos.lnum)) - 1 > (int)strlen((char *)saved_line))
  395. X                                        delchar(FALSE);
  396. X                                    else
  397. X                                    {
  398. X                                        decCurpos();
  399. X                                        delchar(FALSE);
  400. X                                        extraspace = FALSE;
  401. X                                        pcharCurpos(*saved_line);
  402. X                                    }
  403. X                                }
  404. X                                else if (Curpos.col < strlen((char *)saved_line))
  405. X                                    pcharCurpos(saved_line[Curpos.col]);
  406. X                                else if (!p_ri)
  407. X                                    delchar(FALSE);
  408. X                            }
  409. X                        }
  410. X                        else  /* State != REPLACE */
  411. X                        {
  412. X                            delchar(FALSE);
  413. X                            if (p_ri && gcharCurpos() == NUL)
  414. X                                break;
  415. X                        }
  416. X                        if (mode == 0)        /* just a single backspace */
  417. X                            break;
  418. X                        if (p_ri && State == REPLACE && incCurpos())
  419. X                            break;
  420. X                    } while (p_ri || (Curpos.col > mincol && (Curpos.lnum != Insstart.lnum ||
  421. X                            Curpos.col != Insstart.col)));
  422. X                    if (extraspace)
  423. X                        decCurpos();
  424. X                }
  425. X                did_si = FALSE;
  426. X                can_si = FALSE;
  427. X                if (Curpos.col <= 1)
  428. X                    did_ai = FALSE;
  429. X                /*
  430. X                 * It's a little strange to put backspaces into the redo
  431. X                 * buffer, but it makes auto-indent a lot easier to deal
  432. X                 * with.
  433. X                 */
  434. X                AppendCharToRedobuff(c);
  435. X                if (vpeekc() == BS)
  436. X                {
  437. X                        c = vgetc();
  438. X                        goto nextbs;    /* speedup multiple backspaces */
  439. X                }
  440. Xredraw:
  441. X                cursupdate();
  442. X                updateline();
  443. X                break;
  444. X
  445. X              case Ctrl('W'):        /* delete word before cursor */
  446. X                  mode = 1;
  447. X                  goto dodel;
  448. X
  449. X              case Ctrl('U'):        /* delete inserted text in current line */
  450. X                mode = 3;
  451. X                  goto dodel;
  452. X
  453. X              case K_LARROW:
  454. X                  if (oneleft())
  455. X                    start_arrow();
  456. X                else
  457. X                    beep();
  458. X                break;
  459. X
  460. X              case K_SLARROW:
  461. X                  if (Curpos.lnum > 1 || Curpos.col > 0)
  462. X                {
  463. X                    bck_word(1L, 0);
  464. X                    start_arrow();
  465. X                }
  466. X                else
  467. X                    beep();
  468. X                break;
  469. X
  470. X              case K_RARROW:
  471. X                if (gcharCurpos() != NUL)
  472. X                {
  473. X                    set_want_col = TRUE;
  474. X                    start_arrow();
  475. X                    ++Curpos.col;
  476. X                }
  477. X                else
  478. X                    beep();
  479. X                break;
  480. X
  481. X              case K_SRARROW:
  482. X                  if (Curpos.lnum < line_count || gcharCurpos() != NUL)
  483. X                {
  484. X                    fwd_word(1L, 0, 0);
  485. X                    start_arrow();
  486. X                }
  487. X                else
  488. X                    beep();
  489. X                break;
  490. X
  491. X              case K_UARROW:
  492. X                  if (oneup(1L))
  493. X                    start_arrow();
  494. X                else
  495. X                    beep();
  496. X                break;
  497. X
  498. X              case K_SUARROW:
  499. X                  if (onepage(BACKWARD, 1L))
  500. X                    start_arrow();
  501. X                else
  502. X                    beep();
  503. X                break;
  504. X
  505. X              case K_DARROW:
  506. X                  if (onedown(1L))
  507. X                    start_arrow();
  508. X                else
  509. X                    beep();
  510. X                break;
  511. X
  512. X              case K_SDARROW:
  513. X                  if (onepage(FORWARD, 1L))
  514. X                    start_arrow();
  515. X                else
  516. X                    beep();
  517. X                break;
  518. X
  519. X              case TAB:
  520. X                if (echeck_abbr(TAB + 0x100))
  521. X                    break;
  522. X                  if (!p_et || (p_ri && State == REPLACE))
  523. X                    goto normalchar;
  524. X                                        /* expand a tab into spaces */
  525. X                stop_arrow();
  526. X                did_ai = FALSE;
  527. X                did_si = FALSE;
  528. X                can_si = FALSE;
  529. X                temp = (int)p_ts - Curpos.col % (int)p_ts;
  530. X                inschar(' ');            /* delete one char in replace mode */
  531. X                while (--temp)
  532. X                    insstr(" ");        /* insstr does not delete chars */
  533. X                AppendToRedobuff("\t");
  534. X                goto redraw;
  535. X
  536. X              case CR:
  537. X              case NL:
  538. X                if (echeck_abbr(c + 0x100))
  539. X                    break;
  540. X                stop_arrow();
  541. X                if (State == REPLACE)
  542. X                {
  543. X                    saved_char = gcharCurpos();
  544. X                    delchar(FALSE);
  545. X                }
  546. X                AppendToRedobuff(NL_STR);
  547. X                if (!Opencmd(FORWARD, TRUE, State == INSERT))
  548. X                    goto doESCkey;        /* out of memory */
  549. X                if (p_ri)
  550. X                {
  551. X                    decCurpos();
  552. X                    if (State == REPLACE && Curpos.col > 0)
  553. X                        decCurpos();
  554. X                }
  555. X                break;
  556. X
  557. X#ifdef DIGRAPHS
  558. X              case Ctrl('K'):
  559. X                outchar('?');
  560. X                AppendToRedobuff("\026");    /* CTRL-V */
  561. X                setcursor();
  562. X                  c = vgetc();
  563. X                outstrn(transchar(c));
  564. X                setcursor();
  565. X                c = getdigraph(c, vgetc());
  566. X                goto normalchar;
  567. X#endif /* DIGRAPHS */
  568. X
  569. X              case Ctrl('Y'):                /* copy from previous line */
  570. X                lnum = Curpos.lnum - 1;
  571. X                goto copychar;
  572. X
  573. X              case Ctrl('E'):                /* copy from next line */
  574. X                lnum = Curpos.lnum + 1;
  575. Xcopychar:
  576. X                if (lnum < 1 || lnum > line_count)
  577. X                {
  578. X                    beep();
  579. X                    break;
  580. X                }
  581. X
  582. X                /* try to advance to the cursor column */
  583. X                temp = 0;
  584. X                ptr = (u_char *)nr2ptr(lnum);
  585. X                while (temp < Cursvcol && *ptr)
  586. X                        temp += chartabsize(*ptr++, temp);
  587. X
  588. X                if (temp > Cursvcol)
  589. X                        --ptr;
  590. X                if ((c = *ptr) == NUL)
  591. X                {
  592. X                    beep();
  593. X                    break;
  594. X                }
  595. X
  596. X                /*FALLTHROUGH*/
  597. X              default:
  598. Xnormalchar:
  599. X                if (Curpos.col > 0 && ((can_si && c == '}') || (did_si && c == '{')))
  600. X                    shift_line(TRUE, TRUE);
  601. X
  602. X                if (isidchar(c) || !echeck_abbr(c))
  603. X                    insertchar(c);
  604. X                break;
  605. X            }
  606. X    }
  607. X}
  608. X
  609. X/*
  610. X * Next character is interpreted literally.
  611. X * A one, two or three digit decimal number is interpreted as its byte value.
  612. X * If one or two digits are entered, *nextc is set to the next character.
  613. X */
  614. X    int
  615. Xget_literal(nextc)
  616. X    int *nextc;
  617. X{
  618. X    u_char         cc;
  619. X    u_char         nc;
  620. X    int             oldstate;
  621. X    int             i;
  622. X
  623. X    oldstate = State;
  624. X    State = NOMAPPING;        /* next characters not mapped */
  625. X
  626. X    if (got_int)
  627. X    {
  628. X        *nextc = NUL;
  629. X        return Ctrl('C');
  630. X    }
  631. X    cc = 0;
  632. X    for (i = 0; i < 3; ++i)
  633. X    {
  634. X        nc = vgetc();
  635. X        if (!isdigit(nc))
  636. X            break;
  637. X        cc = cc * 10 + nc - '0';
  638. X        nc = 0;
  639. X    }
  640. X    if (i == 0)        /* no number entered */
  641. X    {
  642. X        cc = nc;
  643. X        nc = 0;
  644. X        if (cc == K_ZERO)    /* NUL is stored as NL */
  645. X            cc = '\n';
  646. X    }
  647. X    else if (cc == 0)        /* NUL is stored as NL */
  648. X        cc = '\n';
  649. X
  650. X    State = oldstate;
  651. X    *nextc = nc;
  652. X    got_int = FALSE;        /* CTRL-C typed after CTRL-V is not an interrupt */
  653. X    return cc;
  654. X}
  655. X
  656. X/*
  657. X * Special characters in this context are those that need processing other
  658. X * than the simple insertion that can be performed here. This includes ESC
  659. X * which terminates the insert, and CR/NL which need special processing to
  660. X * open up a new line. This routine tries to optimize insertions performed by
  661. X * the "redo", "undo" or "put" commands, so it needs to know when it should
  662. X * stop and defer processing to the "normal" mechanism.
  663. X */
  664. X#define ISSPECIAL(c)    ((c) < ' ' || (c) >= DEL)
  665. X
  666. X    void
  667. Xinsertchar(c)
  668. X    unsigned    c;
  669. X{
  670. X    int        haveto_redraw = FALSE;
  671. X
  672. X    stop_arrow();
  673. X    /*
  674. X     * If the cursor is past 'textwidth' and we are inserting a non-space,
  675. X     * try to break the line in two or more pieces. If c == NUL then we have
  676. X     * been called to do formatting only. If p_tw == 0 it does nothing.
  677. X     */
  678. X    if (c == NUL || !isspace(c))
  679. X    {
  680. X        while (p_tw && Cursvcol >= p_tw)
  681. X        {
  682. X            int        startcol;        /* Cursor column at entry */
  683. X            int        wantcol;        /* column at textwidth border */
  684. X            int        foundcol;        /* column for start of word */
  685. X
  686. X            if ((startcol = Curpos.col) == 0)
  687. X                break;
  688. X            coladvance((int)p_tw);            /* find column of textwidth border */
  689. X            wantcol = Curpos.col;
  690. X
  691. X            Curpos.col = startcol - 1;
  692. X            foundcol = 0;
  693. X            while (Curpos.col > 0)            /* find position to break at */
  694. X            {
  695. X                if (isspace(gcharCurpos()))
  696. X                {
  697. X                    while (Curpos.col > 0 && isspace(gcharCurpos()))
  698. X                        --Curpos.col;
  699. X                    if (Curpos.col == 0)    /* only spaces in front of text */
  700. X                        break;
  701. X                    foundcol = Curpos.col + 1;
  702. X                    if (Curpos.col < wantcol)
  703. X                        break;
  704. X                }
  705. X                --Curpos.col;
  706. X            }
  707. X
  708. X            if (foundcol == 0)            /* no spaces, cannot break line */
  709. X            {
  710. X                Curpos.col = startcol;
  711. X                break;
  712. X            }
  713. X            Curpos.col = foundcol;        /* put cursor after pos. to break line */
  714. X            startcol -= foundcol;
  715. X            Opencmd(FORWARD, FALSE, FALSE);
  716. X            while (isspace(gcharCurpos()) && startcol)        /* delete blanks */
  717. X            {
  718. X                delchar(FALSE);
  719. X                --startcol;                /* adjust cursor pos. */
  720. X            }
  721. X            Curpos.col += startcol;
  722. X            curs_columns(FALSE);        /* update Cursvcol */
  723. X            haveto_redraw = TRUE;
  724. X        }
  725. X        if (c == NUL)                    /* formatting only */
  726. X            return;
  727. X        if (haveto_redraw)
  728. X        {
  729. X            /*
  730. X             * If the cursor ended up just below the screen we scroll up here
  731. X             * to avoid a redraw of the whole screen in the most common cases.
  732. X             */
  733. X             if (Curpos.lnum == Botline && !emptyrows)
  734. X                s_del(0, 1, TRUE);
  735. X            updateScreen(CURSUPD);
  736. X        }
  737. X    }
  738. X
  739. X    did_ai = FALSE;
  740. X    did_si = FALSE;
  741. X    can_si = FALSE;
  742. X
  743. X    /*
  744. X     * If there's any pending input, grab up to MAX_COLUMNS at once.
  745. X     * This speeds up normal text input considerably.
  746. X     */
  747. X    if (vpeekc() != NUL && State != REPLACE && !p_ri)
  748. X    {
  749. X        char            p[MAX_COLUMNS + 1];
  750. X        int             i;
  751. X
  752. X        p[0] = c;
  753. X        i = 1;
  754. X        while ((c = vpeekc()) != NUL && !ISSPECIAL(c) && i < MAX_COLUMNS &&
  755. X                    (!p_tw || (Cursvcol += charsize(p[i - 1])) < p_tw) &&
  756. X                    !(!no_abbr && !isidchar(c) && isidchar(p[i - 1])))
  757. X            p[i++] = vgetc();
  758. X        p[i] = '\0';
  759. X        insstr(p);
  760. X        AppendToRedobuff(p);
  761. X    }
  762. X    else
  763. X    {
  764. X        inschar(c);
  765. X        AppendCharToRedobuff(c);
  766. X    }
  767. X
  768. X    updateline();
  769. X}
  770. X
  771. X
  772. X/*
  773. X * start_arrow() is called when an arrow key is used in insert mode.
  774. X * It resembles hitting the <ESC> key.
  775. X */
  776. X    static void
  777. Xstart_arrow()
  778. X{
  779. X    if (!arrow_used)        /* something has been inserted */
  780. X    {
  781. X        AppendToRedobuff(ESC_STR);
  782. X        arrow_used = TRUE;        /* this means we stopped the current insert */
  783. X        stop_insert();
  784. X    }
  785. X}
  786. X
  787. X/*
  788. X * stop_arrow() is called before a change is made in insert mode.
  789. X * If an arrow key has been used, start a new insertion.
  790. X */
  791. X    static void
  792. Xstop_arrow()
  793. X{
  794. X    if (arrow_used)
  795. X    {
  796. X        u_saveCurpos();            /* errors are ignored! */
  797. X        Insstart = Curpos;        /* new insertion starts here */
  798. X        ResetRedobuff();
  799. X        AppendToRedobuff("1i");    /* pretend we start an insertion */
  800. X        arrow_used = FALSE;
  801. X    }
  802. X}
  803. X
  804. X/*
  805. X * do a few things to stop inserting
  806. X */
  807. X    static void
  808. Xstop_insert()
  809. X{
  810. X    stop_redo_ins();
  811. X
  812. X    /*
  813. X     * save the inserted text for later redo with ^@
  814. X     */
  815. X    free(last_insert);
  816. X    last_insert = get_inserted();
  817. X    last_insert_skip = new_insert_skip;
  818. X
  819. X    /*
  820. X     * If we just did an auto-indent, truncate the line, and put
  821. X     * the cursor back.
  822. X     */
  823. X    if (did_ai && !arrow_used)
  824. X    {
  825. X        *nr2ptr(Curpos.lnum) = NUL;
  826. X        canincrease(0);
  827. X        Curpos.col = 0;
  828. X        if (p_list)            /* the deletion is only seen in list mode */
  829. X            updateline();
  830. X    }
  831. X    did_ai = FALSE;
  832. X    did_si = FALSE;
  833. X    can_si = FALSE;
  834. X}
  835. X
  836. X/*
  837. X * oneright oneleft onedown oneup
  838. X *
  839. X * Move one char {right,left,down,up}.    Return TRUE when sucessful, FALSE when
  840. X * we hit a boundary (of a line, or the file).
  841. X */
  842. X
  843. X    int
  844. Xoneright()
  845. X{
  846. X    char *ptr;
  847. X
  848. X    ptr = Curpos2ptr();
  849. X    set_want_col = TRUE;
  850. X
  851. X    if (*ptr++ == NUL || *ptr == NUL)
  852. X        return FALSE;
  853. X    ++Curpos.col;
  854. X    return TRUE;
  855. X}
  856. X
  857. X    int
  858. Xoneleft()
  859. X{
  860. X    set_want_col = TRUE;
  861. X
  862. X    if (Curpos.col == 0)
  863. X        return FALSE;
  864. X    --Curpos.col;
  865. X    return TRUE;
  866. X}
  867. X
  868. X    void
  869. Xbeginline(flag)
  870. X    int            flag;
  871. X{
  872. X    Curpos.col = 0;
  873. X    if (flag)
  874. X    {
  875. X        register char *ptr;
  876. X
  877. X        for (ptr = nr2ptr(Curpos.lnum); isspace(*ptr); ++ptr)
  878. X            ++Curpos.col;
  879. X    }
  880. X    set_want_col = TRUE;
  881. X}
  882. X
  883. X    int
  884. Xoneup(n)
  885. X    long n;
  886. X{
  887. X    if (n != 0 && Curpos.lnum == 1)
  888. X        return FALSE;
  889. X    if (n >= Curpos.lnum)
  890. X        Curpos.lnum = 1;
  891. X    else
  892. X        Curpos.lnum -= n;
  893. X
  894. X    if (operator == NOP)
  895. X        cursupdate();                /* make sure Topline is valid */
  896. X
  897. X    /* try to advance to the column we want to be at */
  898. X    coladvance(Curswant);
  899. X    return TRUE;
  900. X}
  901. X
  902. X    int
  903. Xonedown(n)
  904. X    long n;
  905. X{
  906. X    if (n != 0 && Curpos.lnum == line_count)
  907. X        return FALSE;
  908. X    Curpos.lnum += n;
  909. X    if (Curpos.lnum > line_count)
  910. X        Curpos.lnum = line_count;
  911. X
  912. X    if (operator == NOP)
  913. X        cursupdate();                /* make sure Topline is valid */
  914. X
  915. X    /* try to advance to the column we want to be at */
  916. X    coladvance(Curswant);
  917. X    return TRUE;
  918. X}
  919. X
  920. X    int
  921. Xonepage(dir, count)
  922. X    int        dir;
  923. X    long    count;
  924. X{
  925. X    linenr_t        lp;
  926. X    long            n;
  927. X
  928. X    if (line_count == 1)    /* nothing to do */
  929. X        return FALSE;
  930. X    for ( ; count > 0; --count)
  931. X    {
  932. X        if (dir == FORWARD ? (Topline >= line_count - 1) : (Topline == 1))
  933. X        {
  934. X            beep();
  935. X            return FALSE;
  936. X        }
  937. X        if (dir == FORWARD)
  938. X        {
  939. X            if (Botline > line_count)                /* at end of file */
  940. X                Topline = line_count;
  941. X            else if (plines(Botline) >= Rows - 3 ||    /* next line is big */
  942. X                    Botline - Topline <= 3)        /* just three lines on screen */
  943. X                Topline = Botline;
  944. X            else
  945. X                Topline = Botline - 2;
  946. X            Curpos.lnum = Topline;
  947. X            if (count != 1)
  948. X                comp_Botline();
  949. X        }
  950. X        else    /* dir == BACKWARDS */
  951. X        {
  952. X            lp = Topline;
  953. X            /*
  954. X             * If the first two lines on the screen are not too big, we keep
  955. X             * them on the screen.
  956. X             */
  957. X            if ((n = plines(lp)) > Rows / 2)
  958. X                --lp;
  959. X            else if (lp < line_count && n + plines(lp + 1) < Rows / 2)
  960. X                ++lp;
  961. X            Curpos.lnum = lp;
  962. X            n = 0;
  963. X            while (n <= Rows - 1 && lp >= 1)
  964. X            {
  965. X                n += plines(lp);
  966. X                --lp;
  967. X            }
  968. X            if (n <= Rows - 1)                /* at begin of file */
  969. X                Topline = 1;
  970. X            else if (lp >= Topline - 2)        /* happens with very long lines */
  971. X            {
  972. X                --Topline;
  973. X                comp_Botline();
  974. X                Curpos.lnum = Botline - 1;
  975. X            }
  976. X            else
  977. X                Topline = lp + 2;
  978. X        }
  979. X    }
  980. X    beginline(TRUE);
  981. X    updateScreen(VALID);
  982. X    return TRUE;
  983. X}
  984. X
  985. X    void
  986. Xstuff_inserted(c, count, no_esc)
  987. X    int        c;
  988. X    long    count;
  989. X    int        no_esc;
  990. X{
  991. X    u_char        *esc_ptr = NULL;
  992. X    u_char        *ptr;
  993. X
  994. X    if (last_insert == NULL)
  995. X    {
  996. X        emsg("No inserted text yet");
  997. X        return;
  998. X    }
  999. X    if (c)
  1000. X        stuffcharReadbuff(c);
  1001. X    if (no_esc && (esc_ptr = (u_char *)strrchr((char *)last_insert, 27)) != NULL)
  1002. X        *esc_ptr = NUL;        /* remove the ESC */
  1003. X
  1004. X            /* skip the command */
  1005. X    ptr = last_insert + last_insert_skip;
  1006. X
  1007. X    do
  1008. X        stuffReadbuff((char *)ptr);
  1009. X    while (--count > 0);
  1010. X
  1011. X    if (no_esc && esc_ptr)
  1012. X        *esc_ptr = 27;        /* put the ESC back */
  1013. X}
  1014. X
  1015. X/*
  1016. X * Check the word in front of the cursor for an abbreviation.
  1017. X * Called when the non-id character "c" has been entered.
  1018. X * When an abbreviation is recognized it is removed from the text and
  1019. X * the replacement string is inserted in typestr, followed by "c".
  1020. X */
  1021. X    static int
  1022. Xecheck_abbr(c)
  1023. X    int c;
  1024. X{
  1025. X    if (p_paste || no_abbr)            /* no abbreviations or in paste mode */
  1026. X        return FALSE;
  1027. X
  1028. X    return check_abbr(c, nr2ptr(Curpos.lnum), Curpos.col,
  1029. X                Curpos.lnum == Insstart.lnum ? Insstart.col : 0);
  1030. X}
  1031. END_OF_FILE
  1032. if test 22105 -ne `wc -c <'vim/src/edit.c'`; then
  1033.     echo shar: \"'vim/src/edit.c'\" unpacked with wrong size!
  1034. fi
  1035. chmod +x 'vim/src/edit.c'
  1036. # end of 'vim/src/edit.c'
  1037. fi
  1038. if test -f 'vim/src/unix.c' -a "${1}" != "-c" ; then 
  1039.   echo shar: Will not clobber existing file \"'vim/src/unix.c'\"
  1040. else
  1041. echo shar: Extracting \"'vim/src/unix.c'\" \(21532 characters\)
  1042. sed "s/^X//" >'vim/src/unix.c' <<'END_OF_FILE'
  1043. X/* vi:ts=4:sw=4
  1044. X *
  1045. X *
  1046. X * VIM - Vi IMproved
  1047. X *
  1048. X * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  1049. X *                            Tim Thompson            twitch!tjt
  1050. X *                            Tony Andrews            onecom!wldrdg!tony 
  1051. X *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  1052. X */
  1053. X/*
  1054. X * unix.c -- BSD and SYSV code
  1055. X *
  1056. X * A lot of this file was written by Juergen Weigert.
  1057. X */
  1058. X
  1059. X#include "vim.h"
  1060. X#include "globals.h"
  1061. X#include "param.h"
  1062. X#include "proto.h"
  1063. X
  1064. X#include <fcntl.h>
  1065. X#if !defined(pyr) && !defined(NOT_BOTH_TIME)
  1066. X# include <time.h>            /* on some systems time.h should not be
  1067. X                               included together with sys/time.h */
  1068. X#endif
  1069. X#include <sys/ioctl.h>
  1070. X#ifndef M_XENIX
  1071. X# include <sys/types.h>
  1072. X#endif
  1073. X#include <signal.h>
  1074. X
  1075. X#ifndef USE_SYSTEM        /* use fork/exec to start the shell */
  1076. X# include <sys/wait.h>
  1077. X# if !defined(SCO) && !defined(SOLARIS)            /* SCO returns pid_t */
  1078. Xextern int fork();
  1079. X# endif
  1080. X# if !defined(linux) && !defined(SOLARIS) && !defined(USL)
  1081. Xextern int execvp __ARGS((const char *, const char **));
  1082. X# endif
  1083. X#endif
  1084. X
  1085. X#ifdef SYSV_UNIX
  1086. X# if defined(__sgi) || defined(UTS2) || defined(UTS4)
  1087. X#  include <sys/time.h>
  1088. X# endif
  1089. X# if defined(M_XENIX) || defined(SCO) || defined(UNICOS)
  1090. X#  ifndef UNICOS
  1091. X#   include <stropts.h>
  1092. X#  endif
  1093. X#  include <sys/select.h>
  1094. X#  define bzero(a, b)    memset((a), 0, (b))
  1095. X# else
  1096. X#  include <poll.h>
  1097. X# endif
  1098. X# if defined(SCO) || defined(ISC)
  1099. X#  include <sys/stream.h>
  1100. X#  include <sys/ptem.h>
  1101. X# endif
  1102. X# if defined(M_UNIX) && !defined(SCO)
  1103. X#  include <sys/time.h>
  1104. X# endif       /* M_UNIX */
  1105. X# ifdef ISC
  1106. X#  include <termios.h>
  1107. X# endif
  1108. X# include <termio.h>
  1109. X#else    /* SYSV_UNIX */
  1110. X# include <sys/time.h>
  1111. X# if defined(hpux) || defined(linux)
  1112. X#  include <termio.h>
  1113. X#  if defined(hpux) && !defined(SIGWINCH)    /* hpux 9.01 has it */
  1114. X#   define SIGWINCH SIGWINDOW
  1115. X#  endif
  1116. X# else
  1117. X#  include <sgtty.h>
  1118. X# endif    /* hpux */
  1119. X#endif    /* !SYSV_UNIX */
  1120. X
  1121. X#if (defined(pyr) || defined(NO_FD_ZERO)) && defined(SYSV_UNIX) && defined(FD_ZERO)
  1122. X# undef FD_ZERO
  1123. X#endif
  1124. X
  1125. X#if defined(ESIX) || defined(M_UNIX)
  1126. X# ifdef SIGWINCH
  1127. X#  undef SIGWINCH
  1128. X# endif
  1129. X# ifdef TIOCGWINSZ
  1130. X#  undef TIOCGWINSZ
  1131. X# endif
  1132. X#endif
  1133. X
  1134. Xstatic int    Read __ARGS((char *, long));
  1135. Xstatic int    WaitForChar __ARGS((int));
  1136. Xstatic int    RealWaitForChar __ARGS((int));
  1137. Xstatic void fill_inbuf __ARGS((void));
  1138. X#ifdef USL
  1139. Xstatic void sig_winch __ARGS((int));
  1140. X#else
  1141. X# if defined(SIGWINCH) && !defined(linux) && !defined(__alpha) && !defined(mips) && !defined(_SEQUENT_) && !defined(SCO) && !defined(SOLARIS) && !defined(ISC)
  1142. Xstatic void sig_winch __ARGS((int, int, struct sigcontext *));
  1143. X# endif
  1144. X#endif
  1145. X
  1146. Xstatic int do_resize = FALSE;
  1147. X
  1148. X/*
  1149. X * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  1150. X */
  1151. X#undef TRUE
  1152. X#define TRUE 1
  1153. X#undef FALSE
  1154. X#define FALSE 0
  1155. X
  1156. X    void
  1157. Xmch_write(s, len)
  1158. X    char    *s;
  1159. X    int        len;
  1160. X{
  1161. X    write(1, s, len);
  1162. X}
  1163. X
  1164. X/*
  1165. X * GetChars(): low level input funcion.
  1166. X * Get a characters from the keyboard.
  1167. X * If time == 0 do not wait for characters.
  1168. X * If time == n wait a short time for characters.
  1169. X * If time == -1 wait forever for characters.
  1170. X */
  1171. X    int
  1172. XGetChars(buf, maxlen, time)
  1173. X    char    *buf;
  1174. X    int        maxlen;
  1175. X    int        time;
  1176. X{
  1177. X    int        len;
  1178. X
  1179. X    if (time >= 0)
  1180. X    {
  1181. X        if (time < 20)        /* don't know if this is necessary */
  1182. X            time = 20;
  1183. X        if (WaitForChar(time) == 0)        /* no character available */
  1184. X            return 0;
  1185. X    }
  1186. X    else        /* time == -1 */
  1187. X    {
  1188. X    /*
  1189. X     * If there is no character available within 2 seconds (default)
  1190. X     * write the autoscript file to disk
  1191. X     */
  1192. X        if (WaitForChar((int)p_ut) == 0)
  1193. X            updatescript(0);
  1194. X    }
  1195. X
  1196. X    for (;;)    /* repeat until we got a character */
  1197. X    {
  1198. X        /* 
  1199. X         * we want to be interrupted by the winch signal
  1200. X         */
  1201. X        WaitForChar(-1);
  1202. X        if (do_resize)
  1203. X        {
  1204. X            debug("do_resize!\n");
  1205. X            set_winsize(0, 0, FALSE);
  1206. X            do_resize = FALSE;
  1207. X            continue;
  1208. X        }
  1209. X        len = Read(buf, (long)maxlen);
  1210. X        if (len > 0)
  1211. X            return len;
  1212. X    }
  1213. X}
  1214. X
  1215. X#if defined(SYSV_UNIX) && !defined(M_XENIX) && !defined(UNICOS)
  1216. X    void
  1217. Xvim_delay()
  1218. X{
  1219. X    poll(0, 0, 500);
  1220. X}
  1221. X#else
  1222. Xextern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
  1223. X
  1224. X    void
  1225. Xvim_delay()
  1226. X{
  1227. X    struct timeval tv;
  1228. X
  1229. X    tv.tv_sec = 25 / 50;
  1230. X    tv.tv_usec = (25 % 50) * (1000000/50);
  1231. X    select(0, 0, 0, 0, &tv);
  1232. X}
  1233. X#endif
  1234. X
  1235. X    static void
  1236. X#if defined(__alpha) || defined(mips)
  1237. Xsig_winch()
  1238. X#else
  1239. X# if defined(_SEQUENT_) || defined(SCO) || defined(ISC)
  1240. Xsig_winch(sig, code)
  1241. X    int        sig;
  1242. X    int        code;
  1243. X# else
  1244. X#  if defined(USL)
  1245. Xsig_winch(sig)
  1246. X    int        sig;
  1247. X#  else
  1248. Xsig_winch(sig, code, scp)
  1249. X    int        sig;
  1250. X    int        code;
  1251. X    struct sigcontext *scp;
  1252. X#  endif
  1253. X# endif
  1254. X#endif
  1255. X{
  1256. X#if defined(SIGWINCH) && (defined(SYSV_UNIX) || defined(linux) || defined(hpux) || defined(USL))
  1257. X    signal(SIGWINCH, (void (*)())sig_winch);
  1258. X#endif
  1259. X    do_resize = TRUE;
  1260. X}
  1261. X
  1262. X/*
  1263. X * If the machine has job control, use it to suspend the program,
  1264. X * otherwise fake it by starting a new shell.
  1265. X */
  1266. X    void
  1267. Xmch_suspend()
  1268. X{
  1269. X#ifdef SIGTSTP
  1270. X    settmode(0);
  1271. X    kill(0, SIGTSTP);        /* send ourselves a STOP signal */
  1272. X    settmode(1);
  1273. X#else
  1274. X    outstr("new shell started\n");
  1275. X    call_shell(NULL, 0, TRUE);
  1276. X#endif
  1277. X}
  1278. X
  1279. X    void
  1280. Xmch_windinit()
  1281. X{
  1282. X    Columns = 80;
  1283. X    Rows = 24;
  1284. X
  1285. X    flushbuf();
  1286. X
  1287. X    mch_get_winsize();
  1288. X#if defined(SIGWINCH)
  1289. X    signal(SIGWINCH, (void (*)())sig_winch);
  1290. X#endif
  1291. X}
  1292. X
  1293. X/*
  1294. X * Check_win checks whether we have an interactive window.
  1295. X * If not, a new window is opened with the newcli command.
  1296. X * If we would open a window ourselves, the :sh and :! commands would not
  1297. X * work properly (Why? probably because we are then running in a background CLI).
  1298. X * This also is the best way to assure proper working in a next Workbench release.
  1299. X *
  1300. X * For the -e option (quickfix mode) we open our own window and disable :sh.
  1301. X * Otherwise we would never know when editing is finished.
  1302. X */
  1303. X#define BUF2SIZE 320        /* lenght of buffer for argument with complete path */
  1304. X
  1305. X    void
  1306. Xcheck_win(argc, argv)
  1307. X    int argc;
  1308. X    char **argv;
  1309. X{
  1310. X    if (!isatty(0) || !isatty(1))
  1311. X    {
  1312. X        fprintf(stderr, "VIM: no controlling terminal\n");
  1313. X        exit(2);
  1314. X    }
  1315. X}
  1316. X
  1317. X/*
  1318. X * fname_case(): Set the case of the filename, if it already exists.
  1319. X *                 This will cause the filename to remain exactly the same.
  1320. X */
  1321. X    void
  1322. Xfname_case(name)
  1323. X    char *name;
  1324. X{
  1325. X}
  1326. X
  1327. X    void
  1328. Xsettitle(str)
  1329. X    char *str;
  1330. X{
  1331. X}
  1332. X
  1333. X    void
  1334. Xresettitle()
  1335. X{
  1336. X}
  1337. X
  1338. X/*
  1339. X * Get name of current directory into buffer 'buf' of length 'len' bytes.
  1340. X * Return non-zero for success.
  1341. X */
  1342. X    int 
  1343. Xdirname(buf, len)
  1344. X    char *buf;
  1345. X    int len;
  1346. X{
  1347. X#if defined(SYSV_UNIX) || defined(hpux) || defined(linux)
  1348. X    extern int        errno;
  1349. X    extern char        *sys_errlist[];
  1350. X
  1351. X    if (getcwd(buf,len) == NULL)
  1352. X    {
  1353. X        strcpy(buf, sys_errlist[errno]);
  1354. X        return 0;
  1355. X    }
  1356. X    return 1;
  1357. X#else
  1358. X    return (getwd(buf) != NULL);
  1359. X#endif
  1360. X}
  1361. X
  1362. X/*
  1363. X * get absolute filename into buffer 'buf' of length 'len' bytes
  1364. X */
  1365. X    int 
  1366. XFullName(fname, buf, len)
  1367. X    char *fname, *buf;
  1368. X    int len;
  1369. X{
  1370. X    int        l;
  1371. X    char    olddir[MAXPATHL];
  1372. X    char    *p;
  1373. X    int        c;
  1374. X    int        retval = 1;
  1375. X
  1376. X    if (fname == NULL)    /* always fail */
  1377. X        return 0;
  1378. X
  1379. X    *buf = 0;
  1380. X    if (*fname != '/')
  1381. X    {
  1382. X        /*
  1383. X         * If the file name has a path, change to that directory for a moment,
  1384. X         * and then do the getwd() (and get back to where we were).
  1385. X         * This will get the correct path name with "../" things.
  1386. X         */
  1387. X        if ((p = strrchr(fname, '/')) != NULL)
  1388. X        {
  1389. X#if defined(SYSV_UNIX) || defined(hpux) || defined(linux)
  1390. X            if (getcwd(olddir, MAXPATHL) == NULL)
  1391. X#else
  1392. X            if (getwd(olddir) == NULL)
  1393. X#endif
  1394. X            {
  1395. X                p = NULL;        /* can't get current dir: don't chdir */
  1396. X                retval = 0;
  1397. X            }
  1398. X            else
  1399. X            {
  1400. X                c = *p;
  1401. X                *p = NUL;
  1402. X                if (chdir(fname))
  1403. X                    retval = 0;
  1404. X                else
  1405. X                    fname = p + 1;
  1406. X                *p = c;
  1407. X            }
  1408. X        }
  1409. X#if defined(SYSV_UNIX) || defined(hpux) || defined(linux)
  1410. X        if (getcwd(buf, len) == NULL)
  1411. X#else
  1412. X        if (getwd(buf) == NULL)
  1413. X#endif
  1414. X        {
  1415. X            retval = 0;
  1416. X            *buf = NUL;
  1417. X        }
  1418. X        l = strlen(buf);
  1419. X        if (l && buf[l - 1] != '/')
  1420. X            strcat(buf, "/");
  1421. X        if (p)
  1422. X            chdir(olddir);
  1423. X    }
  1424. X    strcat(buf, fname);
  1425. X    return retval;
  1426. X}
  1427. X
  1428. X/*
  1429. X * get file permissions for 'name'
  1430. X */
  1431. X    long 
  1432. Xgetperm(name)
  1433. X    char *name;
  1434. X{
  1435. X    struct stat statb;
  1436. X
  1437. X    if (stat(name, &statb))
  1438. X        return -1;
  1439. X    return statb.st_mode;
  1440. X}
  1441. X
  1442. X/*
  1443. X * set file permission for 'name' to 'perm'
  1444. X */
  1445. X    int
  1446. Xsetperm(name, perm)
  1447. X    char *name;
  1448. X    int perm;
  1449. X{
  1450. X#ifdef SCO
  1451. X    return chmod(name, (mode_t)perm);
  1452. X#else
  1453. X    return chmod(name, perm);
  1454. X#endif
  1455. X}
  1456. X
  1457. X/*
  1458. X * check if "name" is a directory
  1459. X */
  1460. X    int 
  1461. Xisdir(name)
  1462. X    char *name;
  1463. X{
  1464. X    struct stat statb;
  1465. X
  1466. X    if (stat(name, &statb))
  1467. X        return -1;
  1468. X#ifdef _POSIX_SOURCE
  1469. X    return S_ISDIR(statb.st_mode);
  1470. X#else
  1471. X    return (statb.st_mode & S_IFMT) == S_IFDIR;
  1472. X#endif
  1473. X}
  1474. X
  1475. X    void
  1476. Xmch_windexit(r)
  1477. X    int r;
  1478. X{
  1479. X    settmode(0);
  1480. X    stoptermcap();
  1481. X    flushbuf();
  1482. X    stopscript();                    /* remove autoscript file */
  1483. X    exit(r);
  1484. X}
  1485. X
  1486. X    void
  1487. Xmch_settmode(raw)
  1488. X    int                raw;
  1489. X{
  1490. X#if defined(ECHOE) && defined(ICANON) && !defined(__NeXT__)
  1491. X    /* for "new" tty systems */
  1492. X# ifdef CONVEX
  1493. X    static struct termios told;
  1494. X           struct termios tnew;
  1495. X# else
  1496. X    static struct termio told;
  1497. X           struct termio tnew;
  1498. X# endif
  1499. X#ifdef TIOCLGET
  1500. X    static unsigned long tty_local;
  1501. X#endif
  1502. X
  1503. X    if (raw)
  1504. X    {
  1505. X#ifdef TIOCLGET
  1506. X        ioctl(0, TIOCLGET, &tty_local);
  1507. X#endif
  1508. X        ioctl(0, TCGETA, &told);
  1509. X        tnew = told;
  1510. X        tnew.c_iflag &= ~(ICRNL | IXON);        /* ICRNL enables typing ^V^M */
  1511. X                                                /* IXON enables typing ^S/^Q */
  1512. X        tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
  1513. X#ifdef IEXTEN
  1514. X                    | IEXTEN        /* IEXTEN enables typing ^V on SOLARIS */
  1515. X#endif
  1516. X                        );
  1517. X        tnew.c_cc[VMIN] = 1;            /* return after 1 char */
  1518. X        tnew.c_cc[VTIME] = 0;            /* don't wait */
  1519. X        ioctl(0, TCSETA, &tnew);
  1520. X    }
  1521. X    else
  1522. X    {
  1523. X        ioctl(0, TCSETA, &told);
  1524. X#ifdef TIOCLGET
  1525. X        ioctl(0, TIOCLSET, &tty_local);
  1526. X#endif
  1527. X    }
  1528. X#else
  1529. X# ifndef TIOCSETN
  1530. X#  define TIOCSETN TIOCSETP        /* for hpux 9.0 */
  1531. X# endif
  1532. X    /* for "old" tty systems */
  1533. X    static struct sgttyb ttybold;
  1534. X           struct sgttyb ttybnew;
  1535. X
  1536. X    if (raw)
  1537. X    {
  1538. X        ioctl(0, TIOCGETP, &ttybold);
  1539. X        ttybnew = ttybold;
  1540. X        ttybnew.sg_flags &= ~(CRMOD | ECHO);
  1541. X        ttybnew.sg_flags |= RAW;
  1542. X        ioctl(0, TIOCSETN, &ttybnew);
  1543. X    }
  1544. X    else
  1545. X        ioctl(0, TIOCSETN, &ttybold);
  1546. X#endif
  1547. X}
  1548. X
  1549. X/*
  1550. X * Try to get the current window size:
  1551. X * 1. with an ioctl(), most accurate method
  1552. X * 2. from the environment variables LINES and COLUMNS
  1553. X * 3. from the termcap
  1554. X * 4. keep using the old values
  1555. X */
  1556. X    int
  1557. Xmch_get_winsize()
  1558. X{
  1559. X    int            old_Rows = Rows;
  1560. X    int            old_Columns = Columns;
  1561. X    char        *p;
  1562. X
  1563. X    Columns = 0;
  1564. X    Rows = 0;
  1565. X
  1566. X/*
  1567. X * 1. try using an ioctl. It is the most accurate method.
  1568. X */
  1569. X# ifdef TIOCGSIZE
  1570. X    {
  1571. X        struct ttysize    ts;
  1572. X
  1573. X        if (ioctl(0, TIOCGSIZE, &ts) == 0)
  1574. X        {
  1575. X            Columns = ts.ts_cols;
  1576. X            Rows = ts.ts_lines;
  1577. X        }
  1578. X    }
  1579. X# else /* TIOCGSIZE */
  1580. X#  ifdef TIOCGWINSZ
  1581. X    {
  1582. X        struct winsize    ws;
  1583. X
  1584. X        if (ioctl(0, TIOCGWINSZ, &ws) == 0)
  1585. X        {
  1586. X            Columns = ws.ws_col;
  1587. X            Rows = ws.ws_row;
  1588. X        }
  1589. X    }
  1590. X#  endif /* TIOCGWINSZ */
  1591. X# endif /* TIOCGSIZE */
  1592. X
  1593. X/*
  1594. X * 2. get size from environment
  1595. X */
  1596. X    if (Columns == 0 || Rows == 0)
  1597. X    {
  1598. X        if ((p = (char *)getenv("LINES")))
  1599. X            Rows = atoi(p);
  1600. X        if ((p = (char *)getenv("COLUMNS")))
  1601. X            Columns = atoi(p);
  1602. X    }
  1603. X
  1604. X#ifdef TERMCAP
  1605. X/*
  1606. X * 3. try reading the termcap
  1607. X */
  1608. X    if (Columns == 0 || Rows == 0)
  1609. X    {
  1610. X        extern void getlinecol();
  1611. X
  1612. X        getlinecol();    /* get "co" and "li" entries from termcap */
  1613. X    }
  1614. X#endif
  1615. X
  1616. X/*
  1617. X * 4. If everything fails, use the old values
  1618. X */
  1619. X    if (Columns <= 0 || Rows <= 0)
  1620. X    {
  1621. X        Columns = old_Columns;
  1622. X        Rows = old_Rows;
  1623. X        return 1;
  1624. X    }
  1625. X    debug2("mch_get_winsize: %dx%d\n", (int)Columns, (int)Rows);
  1626. X
  1627. X    Rows_max = Rows;                /* remember physical max height */
  1628. X
  1629. X    check_winsize();
  1630. X    script_winsize();
  1631. X
  1632. X/* if size changed: screenalloc will allocate new screen buffers */
  1633. X    return (0);
  1634. X}
  1635. X
  1636. X    void
  1637. Xmch_set_winsize()
  1638. X{
  1639. X    /* should try to set the window size to Rows and Columns */
  1640. X}
  1641. X
  1642. X    int 
  1643. Xcall_shell(cmd, dummy, cooked)
  1644. X    char    *cmd;
  1645. X    int        dummy;
  1646. X    int        cooked;
  1647. X{
  1648. X#ifdef USE_SYSTEM        /* use system() to start the shell: simple but slow */
  1649. X
  1650. X    int        x;
  1651. X    char    newcmd[1024];
  1652. X
  1653. X    flushbuf();
  1654. X
  1655. X    if (cooked)
  1656. X        settmode(0);                 /* set to cooked mode */
  1657. X
  1658. X    if (cmd == NULL)
  1659. X        x = system(p_sh);
  1660. X    else
  1661. X    {
  1662. X        sprintf(newcmd, "%s -c \"%s\"", p_sh, cmd);
  1663. X        x = system(newcmd);
  1664. X    }
  1665. X    if (x == 127)
  1666. X    {
  1667. X        emsg("Cannot execute shell sh");
  1668. X        outchar('\n');
  1669. X    }
  1670. X    else if (x)
  1671. X    {
  1672. X        smsg("%d returned", x);
  1673. X        outchar('\n');
  1674. X    }
  1675. X
  1676. X    if (cooked)
  1677. X        settmode(1);                         /* set to raw mode */
  1678. X    return x;
  1679. X
  1680. X#else /* USE_SYSTEM */        /* first attempt at not using system() */
  1681. X
  1682. X    char    newcmd[1024];
  1683. X    int        pid;
  1684. X    int        status = -1;
  1685. X    char    **argv = NULL;
  1686. X    int        argc;
  1687. X    int        i;
  1688. X    char    *p;
  1689. X    int        inquote;
  1690. X
  1691. X    flushbuf();
  1692. X    signal(SIGINT, SIG_IGN);    /* we don't want to be killed here */
  1693. X    if (cooked)
  1694. X        settmode(0);            /* set to cooked mode */
  1695. X
  1696. X    /*
  1697. X     * 1: find number of arguments
  1698. X     * 2: separate them and built argv[]
  1699. X     */
  1700. X    strcpy(newcmd, p_sh);
  1701. X    for (i = 0; i < 2; ++i)    
  1702. X    {
  1703. X        p = newcmd;
  1704. X        inquote = FALSE;
  1705. X        argc = 0;
  1706. X        for (;;)
  1707. X        {
  1708. X            if (i == 1)
  1709. X                argv[argc] = p;
  1710. X            ++argc;
  1711. X            while (*p && (inquote || (*p != ' ' && *p != TAB)))
  1712. X            {
  1713. X                if (*p == '"')
  1714. X                    inquote = !inquote;
  1715. X                ++p;
  1716. X            }
  1717. X            if (*p == NUL)
  1718. X                break;
  1719. X            if (i == 1)
  1720. X                *p++ = NUL;
  1721. X            skipspace(&p);
  1722. X        }
  1723. X        if (i == 0)
  1724. X        {
  1725. X            argv = (char **)alloc((unsigned)((argc + 3) * sizeof(char *)));
  1726. X            if (argv == NULL)        /* out of memory */
  1727. X                goto error;
  1728. X        }
  1729. X    }
  1730. X    if (cmd != NULL)
  1731. X    {
  1732. X        argv[argc++] = "-c";
  1733. X        argv[argc++] = cmd;
  1734. X    }
  1735. X    argv[argc] = NULL;
  1736. X
  1737. X    if ((pid = fork()) == -1)        /* maybe we should use vfork() */
  1738. X        emsg("Cannot fork");
  1739. X    else if (pid == 0)        /* child */
  1740. X    {
  1741. X        signal(SIGINT, SIG_DFL);
  1742. X        execvp(argv[0], argv);
  1743. X        exit(127);            /* exec failed, return failure code */
  1744. X    }
  1745. X    else                    /* parent */
  1746. X    {
  1747. X        wait(&status);
  1748. X        status = (status >> 8) & 255;
  1749. X        if (status)
  1750. X        {
  1751. X            if (status == 127)
  1752. X                emsg2("Cannot execute shell %s", p_sh);
  1753. X            else
  1754. X                smsg("%d returned", status);
  1755. X            outchar('\n');
  1756. X        }
  1757. X    }
  1758. X    free(argv);
  1759. X
  1760. Xerror:
  1761. X    if (cooked)
  1762. X        settmode(1);                         /* set to raw mode */
  1763. X    signal(SIGINT, SIG_DFL);
  1764. X    return status;
  1765. X
  1766. X#endif /* USE_SYSTEM */
  1767. X}
  1768. X
  1769. X/*
  1770. X * The input characters are buffered to be able to check for a CTRL-C.
  1771. X * This should be done with signals, but I don't know how to do that in
  1772. X * a portable way for a tty in RAW mode.
  1773. X */
  1774. X
  1775. X#define INBUFLEN 50
  1776. Xstatic char        inbuf[INBUFLEN];    /* internal typeahead buffer */
  1777. Xstatic int        inbufcount = 0;        /* number of chars in inbuf[] */
  1778. X
  1779. X    static int
  1780. XRead(buf, maxlen)
  1781. X    char    *buf;
  1782. X    long    maxlen;
  1783. X{
  1784. X    if (inbufcount == 0)        /* if the buffer is empty, fill it */
  1785. X        fill_inbuf();
  1786. X    if (maxlen > inbufcount)
  1787. X        maxlen = inbufcount;
  1788. X    memmove(buf, inbuf, maxlen);
  1789. X    inbufcount -= maxlen;
  1790. X    if (inbufcount)
  1791. X        memmove(inbuf, inbuf + maxlen, inbufcount);
  1792. X    return (int)maxlen;
  1793. X}
  1794. X
  1795. X    void
  1796. Xbreakcheck()
  1797. X{
  1798. X/*
  1799. X * check for CTRL-C typed by reading all available characters
  1800. X */
  1801. X    if (RealWaitForChar(0))        /* if characters available */
  1802. X        fill_inbuf();
  1803. X}
  1804. X
  1805. X    static void
  1806. Xfill_inbuf()
  1807. X{
  1808. X    int        len;
  1809. X
  1810. X    if (inbufcount >= INBUFLEN)        /* buffer full */
  1811. X        return;
  1812. X    len = read(0, inbuf + inbufcount, (long)(INBUFLEN - inbufcount));
  1813. X    if (len <= 0)    /* cannot read input??? */
  1814. X    {
  1815. X        fprintf(stderr, "Vim: Error reading input, exiting...\n");
  1816. X        exit(1);
  1817. X    }
  1818. X    while (len-- > 0)
  1819. X    {
  1820. X        /*
  1821. X         * if a CTRL-C was typed, remove it from the buffer and set got_int
  1822. X         */
  1823. X        if (inbuf[inbufcount] == 3)
  1824. X        {
  1825. X            /* remove everything typed before the CTRL-C */
  1826. X            memmove(inbuf, inbuf + inbufcount, len + 1);
  1827. X            inbufcount = 0;
  1828. X            got_int = TRUE;
  1829. X        }
  1830. X        ++inbufcount;
  1831. X    }
  1832. X}
  1833. X
  1834. X/* 
  1835. X * Wait "ticks" until a character is available from the keyboard or from inbuf[]
  1836. X * ticks = -1 will block forever
  1837. X */
  1838. X
  1839. X    static int
  1840. XWaitForChar(ticks)
  1841. X    int ticks;
  1842. X{
  1843. X    if (inbufcount)        /* something in inbuf[] */
  1844. X        return 1;
  1845. X    return RealWaitForChar(ticks);
  1846. X}
  1847. X
  1848. X/* 
  1849. X * Wait "ticks" until a character is available from the keyboard
  1850. X * ticks = -1 will block forever
  1851. X */
  1852. X    static int
  1853. XRealWaitForChar(ticks)
  1854. X    int ticks;
  1855. X{
  1856. X#ifndef FD_ZERO
  1857. X    struct pollfd fds;
  1858. X
  1859. X    fds.fd = 0;
  1860. X    fds.events = POLLIN;
  1861. X    return (poll(&fds, 1, ticks));
  1862. X#else
  1863. X    struct timeval tv;
  1864. X    fd_set fdset;
  1865. X
  1866. X    if (ticks >= 0)
  1867. X    {
  1868. X           tv.tv_sec = ticks / 1000;
  1869. X        tv.tv_usec = (ticks % 1000) * (1000000/1000);
  1870. X    }
  1871. X
  1872. X    FD_ZERO(&fdset);
  1873. X    FD_SET(0, &fdset);
  1874. X    return (select(1, &fdset, NULL, NULL, (ticks >= 0) ? &tv : NULL));
  1875. X#endif
  1876. X}
  1877. X
  1878. X#if !defined(__alpha) && !defined(mips) && !defined(SCO) && !defined(remove) && !defined(CONVEX)
  1879. X    int 
  1880. Xremove(buf)
  1881. X# if defined(linux) || defined(__STDC__) || defined(__NeXT__) || defined(M_UNIX)
  1882. X    const
  1883. X# endif
  1884. X            char *buf;
  1885. X{
  1886. X    return unlink(buf);
  1887. X}
  1888. X#endif
  1889. X
  1890. X/*
  1891. X * ExpandWildCard() - this code does wild-card pattern matching using the shell
  1892. X *
  1893. X * Mool: return 0 for success, 1 for error (you may loose some memory) and
  1894. X *       put an error message in *file.
  1895. X *
  1896. X * num_pat is number of input patterns
  1897. X * pat is array of pointers to input patterns
  1898. X * num_file is pointer to number of matched file names
  1899. X * file is pointer to array of pointers to matched file names
  1900. X * On Unix we do not check for files only yet
  1901. X * list_notfound is ignored
  1902. X */
  1903. X
  1904. Xextern char *mktemp __ARGS((char *));
  1905. X#ifndef SEEK_SET
  1906. X# define SEEK_SET 0
  1907. X#endif
  1908. X#ifndef SEEK_END
  1909. X# define SEEK_END 2
  1910. X#endif
  1911. X
  1912. X    int
  1913. XExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  1914. X    int             num_pat;
  1915. X    char          **pat;
  1916. X    int            *num_file;
  1917. X    char         ***file;
  1918. X    int                files_only;
  1919. X    int                list_notfound;
  1920. X{
  1921. X    char    tmpname[TMPNAMELEN];
  1922. X    char    *command;
  1923. X    int        i;
  1924. X    int        dir;
  1925. X    size_t    len;
  1926. X    FILE    *fd;
  1927. X    char    *buffer;
  1928. X    char    *p;
  1929. X    int        use_glob = FALSE;
  1930. X
  1931. X    *num_file = 0;        /* default: no files found */
  1932. X    *file = (char **)"";
  1933. X
  1934. X    /*
  1935. X     * If there are no wildcards, just copy the names to allocated memory.
  1936. X     * Saves a lot of time, because we don't have to start a new shell.
  1937. X     */
  1938. X    if (!have_wildcard(num_pat, pat))
  1939. X    {
  1940. X        *file = (char **)alloc(num_pat * sizeof(char *));
  1941. X        if (*file == NULL)
  1942. X        {
  1943. X            *file = (char **)"";
  1944. X            return 1;
  1945. X        }
  1946. X        for (i = 0; i < num_pat; i++)
  1947. X            (*file)[i] = strsave(pat[i]);
  1948. X        *num_file = num_pat;
  1949. X        return 0;
  1950. X    }
  1951. X
  1952. X/*
  1953. X * get a name for the temp file
  1954. X */
  1955. X    strcpy(tmpname, TMPNAME2);
  1956. X    if (*mktemp(tmpname) == NUL)
  1957. X    {
  1958. X        emsg(e_notmp);
  1959. X        return 1;
  1960. X    }
  1961. X
  1962. X/*
  1963. X * let the shell expand the patterns and write the result into the temp file
  1964. X * If we use csh, glob will work better than echo.
  1965. X */
  1966. X    if ((len = strlen(p_sh)) >= 3 && strcmp(p_sh + len - 3, "csh") == 0)
  1967. X        use_glob = TRUE;
  1968. X
  1969. X    len = TMPNAMELEN + 10;
  1970. X    for (i = 0; i < num_pat; ++i)        /* count the length of the patterns */
  1971. X        len += strlen(pat[i]) + 3;
  1972. X    command = (char *)alloc(len);
  1973. X    if (command == NULL)
  1974. X        return 1;
  1975. X    if (use_glob)
  1976. X        strcpy(command, "glob >");            /* built the shell command */
  1977. X    else
  1978. X        strcpy(command, "echo >");            /* built the shell command */
  1979. X    strcat(command, tmpname);
  1980. X    for (i = 0; i < num_pat; ++i)
  1981. X    {
  1982. X#ifdef USE_SYSTEM
  1983. X        strcat(command, " \"");                /* need extra quotes because we */
  1984. X        strcat(command, pat[i]);            /*   start the shell twice */
  1985. X        strcat(command, "\"");
  1986. X#else
  1987. X        strcat(command, " ");
  1988. X        strcat(command, pat[i]);
  1989. X#endif
  1990. X    }
  1991. X    i = call_shell(command, 0, FALSE);        /* execute it */
  1992. X    free(command);
  1993. X    if (i)                                    /* call_shell failed */
  1994. X    {
  1995. X        remove(tmpname);
  1996. X        sleep(1);            /* give the user a chance to read error messages */
  1997. X        must_redraw = CLEAR;                /* probably messed up screen */
  1998. X        return 1;
  1999. X    }
  2000. X
  2001. X/*
  2002. X * read the names from the file into memory
  2003. X */
  2004. X     fd = fopen(tmpname, "r");
  2005. X    if (fd == NULL)
  2006. X    {
  2007. X        emsg(e_notopen);
  2008. X        return 1;
  2009. X    }
  2010. X    fseek(fd, 0L, SEEK_END);
  2011. X    len = ftell(fd);                /* get size of temp file */
  2012. X    fseek(fd, 0L, SEEK_SET);
  2013. X    buffer = (char *)alloc(len + 1);
  2014. X    if (buffer == NULL)
  2015. X    {
  2016. X        remove(tmpname);
  2017. X        fclose(fd);
  2018. X        return 1;
  2019. X    }
  2020. X    i = fread(buffer, 1, len, fd);
  2021. X    fclose(fd);
  2022. X    remove(tmpname);
  2023. X    if (i != len)
  2024. X    {
  2025. X        emsg(e_notread);
  2026. X        free(buffer);
  2027. X        return 1;
  2028. X    }
  2029. X
  2030. X    if (use_glob)        /* file names are separated with NUL */
  2031. X    {
  2032. X        buffer[len] = NUL;                    /* make sure the buffers ends in NUL */
  2033. X        i = 0;
  2034. X        for (p = buffer; p < buffer + len; ++p)
  2035. X            if (*p == NUL)                    /* count entry */
  2036. X                ++i;
  2037. X        if (len)
  2038. X            ++i;                            /* count last entry */
  2039. X    }
  2040. X    else                /* file names are separated with SPACE */
  2041. X    {
  2042. X        buffer[len] = '\n';                    /* make sure the buffers ends in NL */
  2043. X        p = buffer;
  2044. X        for (i = 0; *p != '\n'; ++i)        /* count number of entries */
  2045. X        {
  2046. X            while (*p != ' ' && *p != '\n')    /* skip entry */
  2047. X                ++p;
  2048. X            skipspace(&p);                    /* skip to next entry */
  2049. X        }
  2050. X    }
  2051. X    *num_file = i;
  2052. X    *file = (char **)alloc(sizeof(char *) * i);
  2053. X    if (*file == NULL)
  2054. X    {
  2055. X        free(buffer);
  2056. X        *file = (char **)"";
  2057. X        return 1;
  2058. X    }
  2059. X    p = buffer;
  2060. X    for (i = 0; i < *num_file; ++i)
  2061. X    {
  2062. X        (*file)[i] = p;
  2063. X        if (use_glob)
  2064. X        {
  2065. X            while (*p && p < buffer + len)        /* skip entry */
  2066. X                ++p;
  2067. X            ++p;                                /* skip NUL */
  2068. X        }
  2069. X        else
  2070. X        {
  2071. X            while (*p != ' ' && *p != '\n')        /* skip entry */
  2072. X                ++p;
  2073. X            if (*p == '\n')                        /* last entry */
  2074. X                *p = NUL;
  2075. X            else
  2076. X            {
  2077. X                *p++ = NUL;
  2078. X                skipspace(&p);                    /* skip to next entry */
  2079. X            }
  2080. X        }
  2081. X    }
  2082. X    for (i = 0; i < *num_file; ++i)
  2083. X    {
  2084. X        dir = (isdir((*file)[i]) > 0);
  2085. X        if (dir < 0)            /* if file doesn't exist don't add '/' */
  2086. X            dir = 0;
  2087. X        p = alloc((unsigned)(strlen((*file)[i]) + 1 + dir));
  2088. X        if (p)
  2089. X        {
  2090. X            strcpy(p, (*file)[i]);
  2091. X            if (dir)
  2092. X                strcat(p, "/");
  2093. X        }
  2094. X        (*file)[i] = p;
  2095. X    }
  2096. X    free(buffer);
  2097. X    return 0;
  2098. X}
  2099. X
  2100. X    void
  2101. XFreeWild(num, file)
  2102. X    int        num;
  2103. X    char    **file;
  2104. X{
  2105. X    if (file == NULL || num == 0)
  2106. X        return;
  2107. X    while (num--)
  2108. X        free(file[num]);
  2109. X    free(file);
  2110. X}
  2111. X
  2112. X    int
  2113. Xhas_wildcard(p)
  2114. X    char *p;
  2115. X{
  2116. X#ifdef __STDC__
  2117. X    return strpbrk(p, "*?[{`~$") != NULL;
  2118. X#else
  2119. X    for ( ; *p; ++p)
  2120. X        if (strchr("*?[{`~$", *p) != NULL)
  2121. X            return 1;
  2122. X    return 0;
  2123. X#endif
  2124. X}
  2125. X
  2126. X    int
  2127. Xhave_wildcard(num, file)
  2128. X    int        num;
  2129. X    char    **file;
  2130. X{
  2131. X    register int i;
  2132. X
  2133. X    for (i = 0; i < num; i++)
  2134. X        if (has_wildcard(file[i]))
  2135. X            return 1;
  2136. X    return 0;
  2137. X}
  2138. X
  2139. X#if defined(M_XENIX) || defined(UTS2)
  2140. X/*
  2141. X * Scaled-down version of rename, which is missing in Xenix.
  2142. X * This version can only move regular files and will fail if the
  2143. X * destination exists.
  2144. X */
  2145. X    int
  2146. Xrename(src, dest)
  2147. X    char *src, *dest;
  2148. X{
  2149. X    struct stat        st;
  2150. X
  2151. X    if (stat(dest, &st) >= 0)    /* fail if destination exists */
  2152. X        return -1;
  2153. X    if (link(src, dest) != 0)    /* link file to new name */
  2154. X        return -1;
  2155. X    if (unlink(src) == 0)        /* delete link to old name */
  2156. X        return 0;
  2157. X    return -1;
  2158. X}
  2159. X#endif /* M_XENIX || UTS2 */
  2160. END_OF_FILE
  2161. if test 21532 -ne `wc -c <'vim/src/unix.c'`; then
  2162.     echo shar: \"'vim/src/unix.c'\" unpacked with wrong size!
  2163. fi
  2164. chmod +x 'vim/src/unix.c'
  2165. # end of 'vim/src/unix.c'
  2166. fi
  2167. echo shar: End of archive 10 \(of 25\).
  2168. cp /dev/null ark10isdone
  2169. MISSING=""
  2170. 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
  2171.     if test ! -f ark${I}isdone ; then
  2172.     MISSING="${MISSING} ${I}"
  2173.     fi
  2174. done
  2175. if test "${MISSING}" = "" ; then
  2176.     echo You have unpacked all 25 archives.
  2177.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2178. else
  2179.     echo You still need to unpack the following archives:
  2180.     echo "        " ${MISSING}
  2181. fi
  2182. ##  End of shell archive.
  2183. exit 0
  2184.  
  2185. ===============================================================================
  2186. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  2187. Oce Nederland B.V., Research & Development | necessarily represent the position
  2188. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  2189. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  2190. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  2191.  
  2192. exit 0 # Just in case...
  2193.