home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2198 < prev    next >
Internet Message Format  |  1990-12-28  |  67KB

  1. From: kirkenda@eecs.cs.pdx.edu (Steve Kirkendall)
  2. Newsgroups: alt.sources
  3. Subject: Elvis 1.4, part 8 of 8
  4. Message-ID: <832@pdxgate.UUCP>
  5. Date: 3 Dec 90 21:36:52 GMT
  6.  
  7.  
  8. # --------------------------- cut here ----------------------------
  9. # This is a shar archive.  To unpack it, save it to a file, and delete
  10. # anything above the "cut here" line.  Then run sh on the file.
  11. #
  12. # -rw-r--r--  1 kirkenda     7638 Dec  2 17:57 refont.c
  13. # -rw-r--r--  1 kirkenda     2957 Dec  2 17:57 vars.c
  14. # -rw-r--r--  1 kirkenda    13459 Dec  2 17:57 vcmd.c
  15. # -rw-r--r--  1 kirkenda    20322 Dec  2 17:57 vi.c
  16. # -rw-r--r--  1 kirkenda    18110 Dec  2 17:57 vi.h
  17. #
  18.  
  19. if test -f vars.c -a "$1" != -f
  20. then
  21. echo Will not overwrite vars.c
  22. else
  23. echo Extracting vars.c
  24. sed 's/^X//' >vars.c <<\eof
  25. X/* vars.c */
  26. X
  27. X/* Author:
  28. X *    Steve Kirkendall
  29. X *    14407 SW Teal Blvd. #C
  30. X *    Beaverton, OR 97005
  31. X *    kirkenda@cs.pdx.edu
  32. X */
  33. X
  34. X
  35. X/* This file contains variables which weren't happy anyplace else */
  36. X
  37. X#include "config.h"
  38. X#include "vi.h"
  39. X
  40. X/*------------------------------------------------------------------------*/
  41. X
  42. X/* used to remember whether the file has been modified */
  43. Xstruct _viflags    viflags;
  44. X
  45. X/* used to access the tmp file */
  46. Xlong        lnum[MAXBLKS];
  47. Xlong        nlines;
  48. Xint        tmpfd = -1;
  49. X
  50. X/* used to keep track of the current file & alternate file */
  51. Xlong        origtime;
  52. Xchar        origname[256];
  53. Xchar        prevorig[256];
  54. Xlong        prevline = 1;
  55. X
  56. X/* used to track various places in the text */
  57. XMARK        mark[NMARKS];    /* marks 'a through 'z, plus mark '' */
  58. XMARK        cursor;        /* the cursor position within the file */
  59. X
  60. X/* which mode of the editor we're in */
  61. Xint        mode;        /* vi mode? ex mode? quitting? */
  62. X
  63. X/* used to manage the args list */
  64. Xchar        args[BLKSIZE];    /* list of filenames to edit */
  65. Xint        argno;        /* index of current file in args list */
  66. Xint        nargs;        /* number of filenames in args[] */
  67. X
  68. X/* dummy var, never explicitly referenced */
  69. Xint        bavar;        /* used only in BeforeAfter macros */
  70. X
  71. X/* have we made a multi-line change? */
  72. Xint        mustredraw;    /* must we redraw the whole screen? */
  73. X
  74. X/* used to detect changes that invalidate cached text/blocks */
  75. Xlong        changes;    /* incremented when file is changed */
  76. Xint        significant;    /* boolean: was a *REAL* change made? */
  77. X
  78. X/* used to support the pfetch() macro */
  79. Xint        plen;        /* length of the line */
  80. Xlong        pline;        /* line number that len refers to */
  81. Xlong        pchgs;        /* "changes" level that len refers to */
  82. Xchar        *ptext;        /* text of previous line, if valid */
  83. X
  84. X/* misc temporary storage - mostly for strings */
  85. XBLK        tmpblk;        /* a block used to accumulate changes */
  86. X
  87. X/* screen oriented stuff */
  88. Xlong        topline;    /* file line number of top line */
  89. Xint        leftcol;    /* column number of left col */
  90. Xint        physcol;    /* physical column number that cursor is on */
  91. Xint        physrow;    /* physical row number that cursor is on */
  92. X
  93. X/* used to help minimize that "[Hit a key to continue]" message */
  94. Xint        exwrote;    /* Boolean: was the last ex command wordy? */
  95. X
  96. X/* This variable affects the behaviour of certain functions -- most importantly
  97. X * the input function.
  98. X */
  99. Xint        doingdot;    /* boolean: are we doing the "." command? */
  100. X
  101. X/* This variable affects the behaviour of the ":s" command, and it is also
  102. X * used to detect & prohibit nesting of ":g" commands
  103. X */
  104. Xint        doingglobal;    /* boolean: are doing a ":g" command? */
  105. X/* These are used for reporting multi-line changes to the user */
  106. Xlong        rptlines;    /* number of lines affected by a command */
  107. Xchar        *rptlabel;    /* description of how lines were affected */
  108. X
  109. X/* These store info that pertains to the shift-U command */
  110. Xlong    U_line;            /* line# of the undoable line, or 0l for none */
  111. Xchar    U_text[BLKSIZE];    /* contents of the undoable line */
  112. X
  113. X/* Bigger stack req'ed for TOS */
  114. X
  115. X#if TOS
  116. Xlong    _stksize = 16384;
  117. X#endif
  118. eof
  119. if test `wc -c <vars.c` -ne 2957
  120. then
  121. echo vars.c damaged!
  122. fi
  123. fi
  124.  
  125. if test -f vcmd.c -a "$1" != -f
  126. then
  127. echo Will not overwrite vcmd.c
  128. else
  129. echo Extracting vcmd.c
  130. sed 's/^X//' >vcmd.c <<\eof
  131. X/* vcmd.c */
  132. X
  133. X/* Author:
  134. X *    Steve Kirkendall
  135. X *    14407 SW Teal Blvd. #C
  136. X *    Beaverton, OR 97005
  137. X *    kirkenda@cs.pdx.edu
  138. X */
  139. X
  140. X
  141. X/* This file contains the functions that handle VI commands */
  142. X
  143. X
  144. X#include "config.h"
  145. X#include "vi.h"
  146. X#if MSDOS
  147. X#include <process.h>
  148. X#include <string.h>
  149. X#endif
  150. X#if TOS
  151. X#include <osbind.h>
  152. X#include <string.h>
  153. X#endif
  154. X#if OSK
  155. X# include <stdio.h>
  156. X#endif
  157. X
  158. X
  159. X/* This function puts the editor in EX mode */
  160. XMARK v_quit()
  161. X{
  162. X    move(LINES - 1, 0);
  163. X    mode = MODE_EX;
  164. X    return cursor;
  165. X}
  166. X
  167. X/* This function causes the screen to be redrawn */
  168. XMARK v_redraw()
  169. X{
  170. X    redraw(MARK_UNSET, FALSE);
  171. X    return cursor;
  172. X}
  173. X
  174. X/* This function executes a single EX command, and waits for a user keystroke
  175. X * before returning to the VI screen.  If that keystroke is another ':', then
  176. X * another EX command is read and executed.
  177. X */
  178. X/*ARGSUSED*/
  179. XMARK v_1ex(m, text)
  180. X    MARK    m;    /* the current line */
  181. X    char    *text;    /* the first command to execute */
  182. X{
  183. X    /* run the command.  be careful about modes & output */
  184. X    exwrote = (mode == MODE_COLON);
  185. X    doexcmd(text);
  186. X    exrefresh();
  187. X
  188. X    /* if mode is no longer MODE_VI, then we should quit right away! */
  189. X    if (mode != MODE_VI && mode != MODE_COLON)
  190. X        return cursor;
  191. X
  192. X    /* The command did some output.  Wait for a keystoke. */
  193. X    if (exwrote)
  194. X    {
  195. X        mode = MODE_VI;    
  196. X        msg("[Hit <RETURN> to continue]");
  197. X        if (getkey(0) == ':')
  198. X        {    mode = MODE_COLON;
  199. X            addch('\n');
  200. X        }
  201. X        else
  202. X            redraw(MARK_UNSET, FALSE);
  203. X    }
  204. X
  205. X    return cursor;
  206. X}
  207. X
  208. X/* This function undoes the last change */
  209. X/*ARGSUSED*/
  210. XMARK v_undo(m)
  211. X    MARK    m;    /* (ignored) */
  212. X{
  213. X    if (undo())
  214. X    {
  215. X        redraw(MARK_UNSET, FALSE);
  216. X    }
  217. X    return cursor;
  218. X}
  219. X
  220. X/* This function deletes the character(s) that the cursor is on */
  221. XMARK v_xchar(m, cnt, cmd)
  222. X    MARK    m;    /* where to start deletions */
  223. X    long    cnt;    /* number of chars to delete */
  224. X    int    cmd;    /* either 'x' or 'X' */
  225. X{
  226. X    DEFAULT(1);
  227. X
  228. X    /* for 'X', adjust so chars are deleted *BEFORE* cursor */
  229. X    if (cmd == 'X')
  230. X    {
  231. X        if (markidx(m) < cnt)
  232. X            return MARK_UNSET;
  233. X        m -= cnt;
  234. X    }
  235. X
  236. X    /* make sure we don't try to delete more thars than there are */
  237. X    pfetch(markline(m));
  238. X    if (markidx(m + cnt) > plen)
  239. X    {
  240. X        cnt = plen - markidx(m);
  241. X    }
  242. X    if (cnt == 0L)
  243. X    {
  244. X        return MARK_UNSET;
  245. X    }
  246. X
  247. X    /* do it */
  248. X    ChangeText
  249. X    {
  250. X        cut(m, m + cnt);
  251. X        delete(m, m + cnt);
  252. X    }
  253. X    return m;
  254. X}
  255. X
  256. X/* This function defines a mark */
  257. X/*ARGSUSED*/
  258. XMARK v_mark(m, count, key)
  259. X    MARK    m;    /* where the mark will be */
  260. X    long    count;    /* (ignored) */
  261. X    int    key;    /* the ASCII label of the mark */
  262. X{
  263. X    if (key < 'a' || key > 'z')
  264. X    {
  265. X        msg("Marks must be from a to z");
  266. X    }
  267. X    else
  268. X    {
  269. X        mark[key - 'a'] = m;
  270. X    }
  271. X    return m;
  272. X}
  273. X
  274. X/* This function toggles upper & lower case letters */
  275. XMARK v_ulcase(m, cnt)
  276. X    MARK    m;    /* where to make the change */
  277. X    long    cnt;    /* number of chars to flip */
  278. X{
  279. X    REG char     *pos;
  280. X    REG int        i, j;
  281. X    static char    flip[] =
  282. X        "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ[](){}<>";
  283. X
  284. X    DEFAULT(1);
  285. X
  286. X    /* fetch the current version of the line */
  287. X    pfetch(markline(m));
  288. X
  289. X    /* for each position in the line */
  290. X    for (j = 0, i = markidx(m); j < cnt && ptext[i]; j++, i++)
  291. X    {
  292. X        tmpblk.c[j] = 0;
  293. X
  294. X        /* one of the standard chars? */
  295. X        for (pos = flip; *pos && *pos != ptext[i]; pos++)
  296. X        {
  297. X        }
  298. X        if (*pos)
  299. X        {
  300. X            tmpblk.c[j] = flip[(int)(pos - flip) ^ 1];
  301. X        }
  302. X#ifndef NO_DIGRAPH
  303. X        else /* one of the non-standard chars? */
  304. X        {
  305. X            for (pos = o_flipcase; *pos && *pos != ptext[i]; pos++)
  306. X            {
  307. X            }
  308. X            if (*pos)
  309. X            {
  310. X                tmpblk.c[j] = o_flipcase[(int)(pos - o_flipcase) ^ 1];
  311. X            }
  312. X        }
  313. X#endif
  314. X
  315. X        /* if nothing special, then don't change it */
  316. X        if (tmpblk.c[j] == 0)
  317. X        {
  318. X            tmpblk.c[j] = ptext[i];
  319. X        }
  320. X    }
  321. X
  322. X    /* if the new text is different from the old, then change it */
  323. X    if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
  324. X    {
  325. X        ChangeText
  326. X        {
  327. X            tmpblk.c[j] = '\0';
  328. X            change(m, m + j, tmpblk.c);
  329. X        }
  330. X    }
  331. X
  332. X    return m + j;
  333. X}
  334. X
  335. X
  336. XMARK v_replace(m, cnt, key)
  337. X    MARK    m;    /* first char to be replaced */
  338. X    long    cnt;    /* number of chars to replace */
  339. X    int    key;    /* what to replace them with */
  340. X{
  341. X    REG char    *text;
  342. X    REG int        i;
  343. X
  344. X    DEFAULT(1);
  345. X
  346. X    /* map ^M to '\n' */
  347. X    if (key == '\r')
  348. X    {
  349. X        key = '\n';
  350. X    }
  351. X
  352. X    /* make sure the resulting line isn't too long */
  353. X    if (cnt > BLKSIZE - 2 - markidx(m))
  354. X    {
  355. X        cnt = BLKSIZE - 2 - markidx(m);
  356. X    }
  357. X
  358. X    /* build a string of the desired character with the desired length */
  359. X    for (text = tmpblk.c, i = cnt; i > 0; i--)
  360. X    {
  361. X        *text++ = key;
  362. X    }
  363. X    *text = '\0';
  364. X
  365. X    /* make sure cnt doesn't extend past EOL */
  366. X    pfetch(markline(m));
  367. X    key = markidx(m);
  368. X    if (key + cnt > plen)
  369. X    {
  370. X        cnt = plen - key;
  371. X    }
  372. X
  373. X    /* do the replacement */
  374. X    ChangeText
  375. X    {
  376. X        change(m, m + cnt, tmpblk.c);
  377. X    }
  378. X
  379. X    if (*tmpblk.c == '\n')
  380. X    {
  381. X        return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
  382. X    }
  383. X    else
  384. X    {
  385. X        return m + cnt - 1;
  386. X    }
  387. X}
  388. X
  389. XMARK v_overtype(m)
  390. X    MARK        m;    /* where to start overtyping */
  391. X{
  392. X    MARK        end;    /* end of a substitution */
  393. X    static long    width;    /* width of a single-line replace */
  394. X
  395. X    /* the "doingdot" version of replace is really a substitution */
  396. X    if (doingdot)
  397. X    {
  398. X        /* was the last one really repeatable? */
  399. X        if (width < 0)
  400. X        {
  401. X            msg("Can't repeat a multi-line overtype command");
  402. X            return MARK_UNSET;
  403. X        }
  404. X
  405. X        /* replacing nothing by nothing?  Don't bother */
  406. X        if (width == 0)
  407. X        {
  408. X            return m;
  409. X        }
  410. X
  411. X        /* replace some chars by repeated text */
  412. X        return v_subst(m, width);
  413. X    }
  414. X
  415. X    /* Normally, we input starting here, in replace mode */
  416. X    ChangeText
  417. X    {
  418. X        end = input(m, m, WHEN_VIREP);
  419. X    }
  420. X
  421. X    /* if we ended on the same line we started on, then this
  422. X     * overtype is repeatable via the dot key.
  423. X     */
  424. X    if (markline(end) == markline(m) && end >= m - 1L)
  425. X    {
  426. X        width = end - m + 1L;
  427. X    }
  428. X    else /* it isn't repeatable */
  429. X    {
  430. X        width = -1L;
  431. X    }
  432. X
  433. X    return end;
  434. X}
  435. X
  436. X
  437. X/* This function selects which cut buffer to use */
  438. X/*ARGSUSED*/
  439. XMARK v_selcut(m, cnt, key)
  440. X    MARK    m;
  441. X    long    cnt;
  442. X    int    key;
  443. X{
  444. X    cutname(key);
  445. X    return m;
  446. X}
  447. X
  448. X/* This function pastes text from a cut buffer */
  449. X/*ARGSUSED*/
  450. XMARK v_paste(m, cnt, cmd)
  451. X    MARK    m;    /* where to paste the text */
  452. X    long    cnt;    /* (ignored) */
  453. X    int    cmd;    /* either 'p' or 'P' */
  454. X{
  455. X    ChangeText
  456. X    {
  457. X        m = paste(m, cmd == 'p', FALSE);
  458. X    }
  459. X    return m;
  460. X}
  461. X
  462. X/* This function yanks text into a cut buffer */
  463. XMARK v_yank(m, n)
  464. X    MARK    m, n;    /* range of text to yank */
  465. X{
  466. X    cut(m, n);
  467. X    return m;
  468. X}
  469. X
  470. X/* This function deletes a range of text */
  471. XMARK v_delete(m, n)
  472. X    MARK    m, n;    /* range of text to delete */
  473. X{
  474. X    /* illegal to try and delete nothing */
  475. X    if (n <= m)
  476. X    {
  477. X        return MARK_UNSET;
  478. X    }
  479. X
  480. X    /* Do it */
  481. X    ChangeText
  482. X    {
  483. X        cut(m, n);
  484. X        delete(m, n);
  485. X    }
  486. X    return m;
  487. X}
  488. X
  489. X
  490. X/* This starts input mode without deleting anything */
  491. XMARK v_insert(m, cnt, key)
  492. X    MARK    m;    /* where to start (sort of) */
  493. X    long    cnt;    /* repeat how many times? */
  494. X    int    key;    /* what command is this for? {a,A,i,I,o,O} */
  495. X{
  496. X    int    wasdot;
  497. X    long    reps;
  498. X    int    after;    /* are we appending or inserting? */
  499. X
  500. X    DEFAULT(1);
  501. X
  502. X    ChangeText
  503. X    {
  504. X        /* tweak the insertion point, based on command key */
  505. X        switch (key)
  506. X        {
  507. X          case 'i':
  508. X            after = FALSE;
  509. X            break;
  510. X
  511. X          case 'a':
  512. X            pfetch(markline(m));
  513. X            if (plen > 0)
  514. X            {
  515. X                m++;
  516. X            }
  517. X            after = TRUE;
  518. X            break;
  519. X
  520. X          case 'I':
  521. X            m = m_front(m, 1L);
  522. X            after = FALSE;
  523. X            break;
  524. X
  525. X          case 'A':
  526. X            pfetch(markline(m));
  527. X            m = (m & ~(BLKSIZE - 1)) + plen;
  528. X            after = TRUE;
  529. X            break;
  530. X
  531. X          case 'O':
  532. X            m &= ~(BLKSIZE - 1);
  533. X            add(m, "\n");
  534. X            after = FALSE;
  535. X            break;
  536. X
  537. X          case 'o':
  538. X            m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
  539. X            add(m, "\n");
  540. X            after = FALSE;
  541. X            break;
  542. X        }
  543. X
  544. X        /* insert the same text once or more */
  545. X        for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
  546. X        {
  547. X            m = input(m, m, WHEN_VIINP);
  548. X            if (after)
  549. X            {
  550. X                m++;
  551. X            }
  552. X        }
  553. X        if (after)
  554. X        {
  555. X            m--;
  556. X        }
  557. X
  558. X        doingdot = wasdot;
  559. X    }
  560. X
  561. X#ifndef CRUNCH
  562. X# ifndef NO_EXTENSIONS
  563. X    if (key == 'i' && *o_inputmode && mode == MODE_VI)
  564. X    {
  565. X        msg("Now in visual command mode!  To return to input mode, hit <i>.");
  566. X    }
  567. X# endif
  568. X#endif
  569. X
  570. X    return m;
  571. X}
  572. X
  573. X/* This starts input mode with some text deleted */
  574. XMARK v_change(m, n)
  575. X    MARK    m, n;    /* the range of text to change */
  576. X{
  577. X    int    lnmode;    /* is this a line-mode change? */
  578. X
  579. X    /* swap them if they're in reverse order */
  580. X    if (m > n)
  581. X    {
  582. X        MARK    tmp;
  583. X        tmp = m;
  584. X        m = n;
  585. X        n = tmp;
  586. X    }
  587. X
  588. X    /* for line mode, retain the last newline char */
  589. X    lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
  590. X    if (lnmode)
  591. X    {
  592. X        n -= BLKSIZE;
  593. X        pfetch(markline(n));
  594. X        n = (n & ~(BLKSIZE - 1)) + plen;
  595. X    }
  596. X
  597. X    ChangeText
  598. X    {
  599. X        cut(m, n);
  600. X        m = input(m, n, WHEN_VIINP);
  601. X    }
  602. X
  603. X    return m;
  604. X}
  605. X
  606. X/* This function replaces a given number of characters with input */
  607. XMARK v_subst(m, cnt)
  608. X    MARK    m;    /* where substitutions start */
  609. X    long    cnt;    /* number of chars to replace */
  610. X{
  611. X    DEFAULT(1);
  612. X
  613. X    /* make sure we don't try replacing past EOL */
  614. X    pfetch(markline(m));
  615. X    if (markidx(m) + cnt > plen)
  616. X    {
  617. X        cnt = plen - markidx(m);
  618. X    }
  619. X
  620. X    /* Go for it! */
  621. X    ChangeText
  622. X    {
  623. X        cut(m, m + cnt);
  624. X        m = input(m, m + cnt, WHEN_VIINP);
  625. X    }
  626. X    return m;
  627. X}
  628. X
  629. X/* This calls the ex "join" command to join some lines together */
  630. XMARK v_join(m, cnt)
  631. X    MARK    m;    /* the first line to be joined */
  632. X    long    cnt;    /* number of other lines to join */
  633. X{
  634. X    MARK    joint;    /* where the lines were joined */
  635. X
  636. X    DEFAULT(1);
  637. X
  638. X    /* figure out where the joint will be */
  639. X    pfetch(markline(m));
  640. X    joint = (m & ~(BLKSIZE - 1)) + plen;
  641. X
  642. X    /* join the lines */
  643. X    cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
  644. X    mustredraw = TRUE;
  645. X
  646. X    /* the cursor should be left at the joint */
  647. X    return joint;
  648. X}
  649. X
  650. X/* This calls the ex shifter command to shift some lines */
  651. Xstatic MARK shift_help(m, n, excmd)
  652. X    MARK    m, n;    /* range of lines to shift */
  653. X    CMD    excmd;    /* which way do we shift? */
  654. X{
  655. X    /* adjust for inclusive endmarks in ex */
  656. X    n -= BLKSIZE;
  657. X
  658. X    cmd_shift(m, n, excmd, 0, "");
  659. X    return m;
  660. X}
  661. X
  662. X/* This calls the ex "<" command to shift some lines left */
  663. XMARK v_lshift(m, n)
  664. X    MARK    m, n;    /* range of lines to shift */
  665. X{
  666. X    return shift_help(m, n, CMD_SHIFTL);
  667. X}
  668. X
  669. X/* This calls the ex ">" command to shift some lines right */
  670. XMARK v_rshift(m, n)
  671. X    MARK    m, n;    /* range of lines to shift */
  672. X{
  673. X    return shift_help(m, n, CMD_SHIFTR);
  674. X}
  675. X
  676. X/* This runs some lines through a filter program */
  677. XMARK v_filter(m, n)
  678. X    MARK    m, n;    /* range of lines to shift */
  679. X{
  680. X    char    cmdln[100];    /* a shell command line */
  681. X
  682. X    /* adjust for inclusive endmarks in ex */
  683. X    n -= BLKSIZE;
  684. X
  685. X    if (vgets('!', cmdln, sizeof(cmdln)) > 0)
  686. X    {
  687. X        filter(m, n, cmdln);
  688. X    }
  689. X
  690. X    redraw(MARK_UNSET, FALSE);
  691. X    return m;
  692. X}
  693. X
  694. X
  695. X/* This function runs the ex "file" command to show the file's status */
  696. XMARK v_status()
  697. X{
  698. X    cmd_file(cursor, cursor, CMD_FILE, 0, "");
  699. X    return cursor;
  700. X}
  701. X
  702. X
  703. X/* This function runs the ":&" command to repeat the previous :s// */
  704. XMARK v_again(m, n)
  705. X    MARK    m, n;
  706. X{
  707. X    cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
  708. X    return cursor;
  709. X}
  710. X
  711. X
  712. X
  713. X/* This function switches to the previous file, if possible */
  714. XMARK v_switch()
  715. X{
  716. X    if (!*prevorig)
  717. X        msg("No previous file");
  718. X    else
  719. X    {    strcpy(tmpblk.c, prevorig);
  720. X        cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
  721. X    }
  722. X    return cursor;
  723. X}
  724. X
  725. X/* This function does a tag search on a keyword */
  726. X/*ARGSUSED*/
  727. XMARK v_tag(keyword, m, cnt)
  728. X    char    *keyword;
  729. X    MARK    m;
  730. X    long    cnt;
  731. X{
  732. X    /* move the cursor to the start of the tag name, where m is */
  733. X    cursor = m;
  734. X
  735. X    /* perform the tag search */
  736. X    cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
  737. X
  738. X    return cursor;
  739. X}
  740. X
  741. X#ifndef NO_EXTENSIONS
  742. X/* This function looks up a keyword by calling the helpprog program */
  743. X/*ARGSUSED*/
  744. XMARK v_keyword(keyword, m, cnt)
  745. X    char    *keyword;
  746. X    MARK    m;
  747. X    long    cnt;
  748. X{
  749. X    int    waswarn;
  750. X    char    cmdline[130];
  751. X
  752. X    move(LINES - 1, 0);
  753. X    addstr("---------------------------------------------------------\n");
  754. X    clrtoeol();
  755. X    refresh();
  756. X    sprintf(cmdline, "%s %s", o_keywordprg, keyword);
  757. X    waswarn = *o_warn;
  758. X    *o_warn = FALSE;
  759. X    suspend_curses();
  760. X    if (system(cmdline))
  761. X    {
  762. X        addstr("<<< failed >>>\n");
  763. X    }
  764. X    resume_curses(FALSE);
  765. X    mode = MODE_VI;
  766. X    redraw(MARK_UNSET, FALSE);
  767. X    *o_warn = waswarn;
  768. X
  769. X    return m;
  770. X}
  771. X
  772. X
  773. X
  774. XMARK v_increment(keyword, m, cnt)
  775. X    char    *keyword;
  776. X    MARK    m;
  777. X    long    cnt;
  778. X{
  779. X    static    sign;
  780. X    char    newval[12];
  781. X    long    atol();
  782. X
  783. X    DEFAULT(1);
  784. X
  785. X    /* get one more keystroke, unless doingdot */
  786. X    if (!doingdot)
  787. X    {
  788. X        sign = getkey(0);
  789. X    }
  790. X
  791. X    /* adjust the number, based on that second keystroke */
  792. X    switch (sign)
  793. X    {
  794. X      case '+':
  795. X      case '#':
  796. X        cnt = atol(keyword) + cnt;
  797. X        break;
  798. X
  799. X      case '-':
  800. X        cnt = atol(keyword) - cnt;
  801. X        break;
  802. X
  803. X      case '=':
  804. X        break;
  805. X
  806. X      default:
  807. X        return MARK_UNSET;
  808. X    }
  809. X    sprintf(newval, "%ld", cnt);
  810. X
  811. X    ChangeText
  812. X    {
  813. X        change(m, m + strlen(keyword), newval);
  814. X    }
  815. X
  816. X    return m;
  817. X}
  818. X#endif
  819. X
  820. X
  821. X/* This function acts like the EX command "xit" */
  822. X/*ARGSUSED*/
  823. XMARK v_xit(m, cnt, key)
  824. X    MARK    m;    /* ignored */
  825. X    long    cnt;    /* ignored */
  826. X    int    key;    /* must be a second 'Z' */
  827. X{
  828. X    /* if second char wasn't 'Z', fail */
  829. X    if (key != 'Z')
  830. X    {
  831. X        return MARK_UNSET;
  832. X    }
  833. X
  834. X    /* move the cursor to the bottom of the screen */
  835. X    move(LINES - 1, 0);
  836. X    clrtoeol();
  837. X
  838. X    /* do the xit command */
  839. X    cmd_xit(m, m, CMD_XIT, FALSE, "");
  840. X
  841. X    /* return the cursor */
  842. X    return m;
  843. X}
  844. X
  845. X
  846. X/* This function undoes changes to a single line, if possible */
  847. XMARK v_undoline(m)
  848. X    MARK    m;    /* where we hope to undo the change */
  849. X{
  850. X    /* make sure we have the right line in the buffer */
  851. X    if (markline(m) != U_line)
  852. X    {
  853. X        return MARK_UNSET;
  854. X    }
  855. X
  856. X    /* fix it */
  857. X    ChangeText
  858. X    {
  859. X        strcat(U_text, "\n");
  860. X        change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
  861. X    }
  862. X
  863. X    /* nothing in the buffer anymore */
  864. X    U_line = -1L;
  865. X
  866. X    /* return, with the cursor at the front of the line */
  867. X    return m & ~(BLKSIZE - 1);
  868. X}
  869. X
  870. X
  871. X#ifndef NO_ERRLIST
  872. XMARK v_errlist(m)
  873. X    MARK    m;
  874. X{
  875. X    cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
  876. X    return cursor;
  877. X}
  878. X#endif
  879. X
  880. X
  881. X#ifndef NO_AT
  882. X/*ARGSUSED*/
  883. XMARK v_at(m, cnt, key)
  884. X    MARK    m;
  885. X    long    cnt;
  886. X    int    key;
  887. X{
  888. X    if (!fromcutbuf(key))
  889. X    {
  890. X        return MARK_UNSET;
  891. X    }
  892. X    return cursor;
  893. X}
  894. X#endif
  895. eof
  896. if test `wc -c <vcmd.c` -ne 13459
  897. then
  898. echo vcmd.c damaged!
  899. fi
  900. fi
  901.  
  902. if test -f vi.c -a "$1" != -f
  903. then
  904. echo Will not overwrite vi.c
  905. else
  906. echo Extracting vi.c
  907. sed 's/^X//' >vi.c <<\eof
  908. X/* vi.c */
  909. X
  910. X/* Author:
  911. X *    Steve Kirkendall
  912. X *    14407 SW Teal Blvd. #C
  913. X *    Beaverton, OR 97005
  914. X *    kirkenda@cs.pdx.edu
  915. X */
  916. X
  917. X
  918. X#include "config.h"
  919. X#include <ctype.h>
  920. X#include "vi.h"
  921. X
  922. X
  923. X
  924. X/* This array describes what each key does */
  925. X#define NO_FUNC        (MARK (*)())0
  926. X#define NO_ARGS        0
  927. X#define CURSOR_COUNT    1
  928. X#define CURSOR        2
  929. X#define CURSOR_CNT_KEY    3
  930. X#define CURSOR_MOVED    4
  931. X#define CURSOR_EOL    5
  932. X#define ZERO        6
  933. X#define DIGIT        7
  934. X#define CURSOR_TEXT    8
  935. X#define CURSOR_CNT_CMD    9
  936. X#define KEYWORD        10
  937. X#define NO_FLAGS    0x00
  938. X#define    MVMT        0x01    /* this is a movement command */
  939. X#define PTMV        0x02    /* this can be *part* of a movement command */
  940. X#define FRNT        0x04    /* after move, go to front of line */
  941. X#define INCL        0x08    /* include last char when used with c/d/y */
  942. X#define LNMD        0x10    /* use line mode of c/d/y */
  943. X#define NCOL        0x20    /* this command can't change the column# */
  944. X#define NREL        0x40    /* this is "non-relative" -- set the '' mark */
  945. X#define SDOT        0x80    /* set the "dot" variables, for the "." cmd */
  946. Xstatic struct keystru
  947. X{
  948. X    MARK    (*func)();    /* the function to run */
  949. X    uchar    args;        /* description of the args needed */
  950. X    uchar    flags;        /* other stuff */
  951. X}
  952. X    vikeys[] =
  953. X{
  954. X/* NUL not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  955. X/* ^A  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  956. X/* ^B  page backward    */    {m_scroll,    CURSOR_CNT_CMD,    FRNT},
  957. X/* ^C  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  958. X/* ^D  scroll dn 1/2page*/    {m_scroll,    CURSOR_CNT_CMD,    NCOL},
  959. X/* ^E  scroll up    */    {m_scroll,    CURSOR_CNT_CMD,    NCOL},
  960. X/* ^F  page forward    */    {m_scroll,    CURSOR_CNT_CMD,    FRNT},
  961. X/* ^G  show file status    */    {v_status,    NO_ARGS,     NO_FLAGS},
  962. X/* ^H  move left, like h*/    {m_left,    CURSOR_COUNT,    MVMT},
  963. X/* ^I  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  964. X/* ^J  move down    */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|LNMD},
  965. X/* ^K  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  966. X/* ^L  redraw screen    */    {v_redraw,    NO_ARGS,    NO_FLAGS},
  967. X/* ^M  mv front next ln */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|FRNT|LNMD},
  968. X/* ^N  move down    */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|LNMD},
  969. X/* ^O  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  970. X/* ^P  move up        */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|LNMD},
  971. X/* ^Q  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  972. X/* ^R  redraw screen    */    {v_redraw,    NO_ARGS,    NO_FLAGS},
  973. X/* ^S  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  974. X/* ^T  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  975. X/* ^U  scroll up 1/2page*/    {m_scroll,    CURSOR_CNT_CMD,    NCOL},
  976. X/* ^V  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  977. X/* ^W  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  978. X/* ^X  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  979. X/* ^Y  scroll down    */    {m_scroll,    CURSOR_CNT_CMD,    NCOL},
  980. X/* ^Z  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  981. X/* ESC not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  982. X/* ^\  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  983. X/* ^]  keyword is tag    */    {v_tag,        KEYWORD,    NO_FLAGS},
  984. X/* ^^  previous file    */    {v_switch,    CURSOR,        NO_FLAGS},
  985. X/* ^_  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  986. X/* SPC move right,like l*/    {m_right,    CURSOR_COUNT,    MVMT},
  987. X/*  !  run thru filter    */    {v_filter,    CURSOR_MOVED,    FRNT|LNMD|INCL},
  988. X/*  "  select cut buffer*/    {v_selcut,    CURSOR_CNT_KEY,    PTMV},
  989. X#ifndef NO_EXTENSIONS
  990. X/*  #  increment number    */    {v_increment,    KEYWORD,    SDOT},
  991. X#else
  992. X/*  #  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  993. X#endif
  994. X/*  $  move to rear    */    {m_rear,    CURSOR,        MVMT|INCL},
  995. X/*  %  move to match    */    {m_match,    CURSOR,        MVMT|INCL},
  996. X/*  &  repeat subst    */    {v_again,    CURSOR_MOVED,    SDOT|NCOL|LNMD|INCL},
  997. X/*  '  move to a mark    */    {m_tomark,    CURSOR_CNT_KEY,    MVMT|FRNT|NREL|LNMD|INCL},
  998. X#ifndef NO_SENTENCE
  999. X/*  (  mv back sentence    */    {m_bsentence,    CURSOR_COUNT,    MVMT},
  1000. X/*  )  mv fwd sentence    */    {m_fsentence,    CURSOR_COUNT,    MVMT},
  1001. X#else
  1002. X/*  (  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1003. X/*  )  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1004. X#endif
  1005. X#ifndef NO_ERRLIST
  1006. X/*  *  errlist        */    {v_errlist,    CURSOR,        FRNT|NREL},
  1007. X#else
  1008. X/*  *  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1009. X#endif
  1010. X/*  +  mv front next ln */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|FRNT|LNMD},
  1011. X#ifndef NO_CHARSEARCH
  1012. X/*  ,  reverse [fFtT] cmd*/    {m__ch,        CURSOR_CNT_CMD,    MVMT|INCL},
  1013. X#else
  1014. X/*  ,  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1015. X#endif
  1016. X/*  -  mv front prev ln    */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|FRNT|LNMD},
  1017. X/*  .  special...    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1018. X/*  /  forward search    */    {m_fsrch,    CURSOR_TEXT,    MVMT|NREL},
  1019. X/*  0  part of count?    */    {NO_FUNC,    ZERO,        MVMT|PTMV},
  1020. X/*  1  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1021. X/*  2  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1022. X/*  3  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1023. X/*  4  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1024. X/*  5  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1025. X/*  6  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1026. X/*  7  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1027. X/*  8  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1028. X/*  9  part of count    */    {NO_FUNC,    DIGIT,        PTMV},
  1029. X/*  :  run single EX cmd*/    {v_1ex,        CURSOR_TEXT,    NO_FLAGS},
  1030. X#ifndef NO_CHARSEARCH
  1031. X/*  ;  repeat [fFtT] cmd*/    {m__ch,        CURSOR_CNT_CMD,    MVMT|INCL},
  1032. X#else
  1033. X/*  ;  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1034. X#endif
  1035. X/*  <  shift text left    */    {v_lshift,    CURSOR_MOVED,    SDOT|FRNT|LNMD|INCL},
  1036. X/*  =  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1037. X/*  >  shift text right    */    {v_rshift,    CURSOR_MOVED,    SDOT|FRNT|LNMD|INCL},
  1038. X/*  ?  backward search    */    {m_bsrch,    CURSOR_TEXT,    MVMT|NREL},
  1039. X#ifndef NO_AT
  1040. X/*  @  execute a cutbuf */    {v_at,        CURSOR_CNT_KEY,    NO_FLAGS},
  1041. X#else
  1042. X/*  @  undefined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1043. X#endif
  1044. X/*  A  append at EOL    */    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1045. X/*  B  move back Word    */    {m_bword,    CURSOR_CNT_CMD,    MVMT},
  1046. X/*  C  change to EOL    */    {v_change,    CURSOR_EOL,    SDOT},
  1047. X/*  D  delete to EOL    */    {v_delete,    CURSOR_EOL,    SDOT},
  1048. X/*  E  move end of Word    */    {m_eword,    CURSOR_CNT_CMD,    MVMT|INCL},
  1049. X#ifndef NO_CHARSEARCH
  1050. X/*  F  move bk to char    */    {m_Fch,        CURSOR_CNT_KEY,    MVMT|INCL},
  1051. X#else
  1052. X/*  F  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1053. X#endif
  1054. X/*  G  move to line #    */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|NREL|LNMD|FRNT|INCL},
  1055. X/*  H  move to row    */    {m_row,        CURSOR_CNT_CMD,    MVMT|FRNT},
  1056. X/*  I  insert at front    */    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1057. X/*  J  join lines    */    {v_join,    CURSOR_COUNT,    SDOT},
  1058. X#ifndef NO_EXTENSIONS
  1059. X/*  K  look up keyword    */    {v_keyword,    KEYWORD,    NO_FLAGS},
  1060. X#else
  1061. X/*  K  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1062. X#endif
  1063. X/*  L  move to last row    */    {m_row,        CURSOR_CNT_CMD,    MVMT|FRNT},
  1064. X/*  M  move to mid row    */    {m_row,        CURSOR_CNT_CMD,    MVMT|FRNT},
  1065. X/*  N  reverse prev srch*/    {m_Nsrch,    CURSOR,        MVMT},
  1066. X/*  O  insert above line*/    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1067. X/*  P  paste before    */    {v_paste,    CURSOR_CNT_CMD,    NO_FLAGS},
  1068. X/*  Q  quit to EX mode    */    {v_quit,    NO_ARGS,    NO_FLAGS},
  1069. X/*  R  overtype        */    {v_overtype,    CURSOR,        SDOT},
  1070. X/*  S  change line    */    {v_change,    CURSOR_MOVED,    SDOT},
  1071. X#ifndef NO_CHARSEARCH
  1072. X/*  T  move bk to char    */    {m_Tch,        CURSOR_CNT_KEY,    MVMT|INCL},
  1073. X#else
  1074. X/*  T  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1075. X#endif
  1076. X/*  U  undo whole line    */    {v_undoline,    CURSOR,        FRNT},
  1077. X/*  V  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1078. X/*  W  move forward Word*/    {m_fword,    CURSOR_CNT_CMD,    MVMT},
  1079. X/*  X  delete to left    */    {v_xchar,    CURSOR_CNT_CMD,    SDOT},
  1080. X/*  Y  yank text    */    {v_yank,    CURSOR_MOVED,    NCOL},
  1081. X/*  Z  save file & exit    */    {v_xit,        CURSOR_CNT_KEY,    NO_FLAGS},
  1082. X/*  [  move back section*/    {m_bsection,    CURSOR_CNT_KEY,    MVMT|LNMD|NREL},
  1083. X/*  \  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1084. X/*  ]  move fwd section */    {m_fsection,    CURSOR_CNT_KEY,    MVMT|LNMD|NREL},
  1085. X/*  ^  move to front    */    {m_front,    CURSOR,        MVMT},
  1086. X/*  _  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1087. X/*  `  move to mark    */    {m_tomark,    CURSOR_CNT_KEY,    MVMT|NREL},
  1088. X/*  a  append at cursor    */    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1089. X/*  b  move back word    */    {m_bword,    CURSOR_CNT_CMD,    MVMT},
  1090. X/*  c  change text    */    {v_change,    CURSOR_MOVED,    SDOT},
  1091. X/*  d  delete op    */    {v_delete,    CURSOR_MOVED,    SDOT|NCOL},
  1092. X/*  e  move end word    */    {m_eword,    CURSOR_CNT_CMD,    MVMT|INCL},
  1093. X#ifndef NO_CHARSEARCH
  1094. X/*  f  move fwd for char*/    {m_fch,        CURSOR_CNT_KEY,    MVMT|INCL},
  1095. X#else
  1096. X/*  f  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1097. X#endif
  1098. X/*  g  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1099. X/*  h  move left    */    {m_left,    CURSOR_COUNT,    MVMT},
  1100. X/*  i  insert at cursor    */    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1101. X/*  j  move down    */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|NCOL|LNMD},
  1102. X/*  k  move up        */    {m_updnto,    CURSOR_CNT_CMD,    MVMT|NCOL|LNMD},
  1103. X/*  l  move right    */    {m_right,    CURSOR_COUNT,    MVMT},
  1104. X/*  m  define a mark    */    {v_mark,    CURSOR_CNT_KEY,    NO_FLAGS},
  1105. X/*  n  repeat prev srch    */    {m_nsrch,    CURSOR,     MVMT},
  1106. X/*  o  insert below line*/    {v_insert,    CURSOR_CNT_CMD,    SDOT},
  1107. X/*  p  paste after    */    {v_paste,    CURSOR_CNT_CMD,    NO_FLAGS},
  1108. X/*  q  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1109. X/*  r  replace chars    */    {v_replace,    CURSOR_CNT_KEY,    SDOT},
  1110. X/*  s  subst N chars    */    {v_subst,    CURSOR_COUNT,    SDOT},
  1111. X#ifndef NO_CHARSEARCH
  1112. X/*  t  move fwd to char    */    {m_tch,        CURSOR_CNT_KEY,    MVMT|INCL},
  1113. X#else
  1114. X/*  t  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1115. X#endif
  1116. X/*  u  undo        */    {v_undo,    CURSOR,        NO_FLAGS},
  1117. X/*  v  not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS},
  1118. X/*  w  move fwd word    */    {m_fword,    CURSOR_CNT_CMD,    MVMT},
  1119. X/*  x  delete character    */    {v_xchar,    CURSOR_CNT_CMD,    SDOT},
  1120. X/*  y  yank text    */    {v_yank,    CURSOR_MOVED,    NCOL},
  1121. X/*  z  adjust scrn row    */    {m_z,         CURSOR_CNT_KEY,    NCOL},
  1122. X/*  {  back paragraph    */    {m_bparagraph,    CURSOR_COUNT,    MVMT|LNMD},
  1123. X/*  |  move to column    */    {m_tocol,    CURSOR_COUNT,    NREL},
  1124. X/*  }  fwd paragraph    */    {m_fparagraph,    CURSOR_COUNT,    MVMT|LNMD},
  1125. X/*  ~  upper/lowercase    */    {v_ulcase,    CURSOR_COUNT,    SDOT},
  1126. X/* DEL not defined    */    {NO_FUNC,    NO_ARGS,    NO_FLAGS}
  1127. X};
  1128. X
  1129. X
  1130. X
  1131. Xvoid vi()
  1132. X{
  1133. X    REG int            key;    /* keystroke from user */
  1134. X    long            count;    /* numeric argument to some functions */
  1135. X    REG struct keystru    *keyptr;/* pointer to vikeys[] element */
  1136. X    MARK            tcurs;    /* temporary cursor */
  1137. X    int            prevkey;/* previous key, if d/c/y/</>/! */
  1138. X    MARK            range;    /* start of range for d/c/y/</>/! */
  1139. X    char            text[100];
  1140. X    int            dotkey;    /* last "key" of a change */
  1141. X    int            dotpkey;/* last "prevkey" of a change */
  1142. X    int            dotkey2;/* last extra "getkey()" of a change */
  1143. X    int            dotcnt;    /* last "count" of a change */
  1144. X    int            firstkey;
  1145. X    REG int            i;
  1146. X
  1147. X    /* tell the redraw() function to start from scratch */
  1148. X    redraw(MARK_UNSET, FALSE);
  1149. X
  1150. X#ifdef lint
  1151. X    /* lint says that "range" might be used before it is set.  This
  1152. X     * can't really happen due to the way "range" and "prevkey" are used,
  1153. X     * but lint doesn't know that.  This line is here ONLY to keep lint
  1154. X     * happy.
  1155. X     */
  1156. X    range = 0L;
  1157. X#endif
  1158. X
  1159. X    /* safeguard against '.' with no previous command */
  1160. X    dotkey = 0;
  1161. X
  1162. X    /* go immediately into insert mode, if ":set inputmode" */
  1163. X    firstkey = 0;
  1164. X#ifndef NO_EXTENSIONS
  1165. X    if (*o_inputmode)
  1166. X    {
  1167. X        firstkey = 'i';
  1168. X    }
  1169. X#endif
  1170. X
  1171. X    /* Repeatedly handle VI commands */
  1172. X    for (count = 0, prevkey = '\0'; mode == MODE_VI; )
  1173. X    {
  1174. X        /* if we've moved off the undoable line, then we can't undo it at all */
  1175. X        if (markline(cursor) != U_line)
  1176. X        {
  1177. X            U_line = 0L;
  1178. X        }
  1179. X
  1180. X        /* report any changes from the previous command */
  1181. X        if (rptlines >= *o_report)
  1182. X        {
  1183. X            redraw(cursor, FALSE);
  1184. X            msg("%ld lines %s", rptlines, rptlabel);
  1185. X        }
  1186. X        rptlines = 0L;
  1187. X
  1188. X        /* get the next command key.  It must be ASCII */
  1189. X        if (firstkey)
  1190. X        {
  1191. X            key = firstkey;
  1192. X            firstkey = 0;
  1193. X        }
  1194. X        else
  1195. X        {
  1196. X            do
  1197. X            {
  1198. X                key = getkey(WHEN_VICMD);
  1199. X            } while (key < 0 || key > 127);
  1200. X        }
  1201. X
  1202. X        /* change cw and cW commands to ce and cE, respectively */
  1203. X        /* (Why?  because the real vi does it that way!) */
  1204. X        if (prevkey == 'c')
  1205. X        {
  1206. X            if (key == 'w')
  1207. X                key = 'e';
  1208. X            else if (key == 'W')
  1209. X                key = 'E';
  1210. X
  1211. X            /* wouldn't work right at the end of a word unless we
  1212. X             * backspace one character before doing the move.  This
  1213. X             * will fix most cases.  !!! but not all.
  1214. X             */
  1215. X            if (markidx(cursor) > 0 && (key == 'e' || key == 'E'))
  1216. X            {
  1217. X                cursor--;
  1218. X            }
  1219. X        }
  1220. X
  1221. X        /* look up the structure describing this command */
  1222. X        keyptr = &vikeys[key];
  1223. X
  1224. X        /* if we're in the middle of a d/c/y/</>/! command, reject
  1225. X         * anything but movement or a doubled version like "dd".
  1226. X         */
  1227. X        if (prevkey && key != prevkey && !(keyptr->flags & (MVMT|PTMV)))
  1228. X        {
  1229. X            beep();
  1230. X            prevkey = 0;
  1231. X            count = 0;
  1232. X            continue;
  1233. X        }
  1234. X
  1235. X        /* set the "dot" variables, if we're supposed to */
  1236. X        if ((keyptr->flags & SDOT)
  1237. X         || (prevkey && vikeys[prevkey].flags & SDOT))
  1238. X        {
  1239. X            dotkey = key;
  1240. X            dotpkey = prevkey;
  1241. X            dotkey2 = '\0';
  1242. X            dotcnt = count;
  1243. X
  1244. X            /* remember the line before any changes are made */
  1245. X            if (U_line != markline(cursor))
  1246. X            {
  1247. X                U_line = markline(cursor);
  1248. X                strcpy(U_text, fetchline(U_line));
  1249. X            }
  1250. X        }
  1251. X
  1252. X        /* if this is "." then set other vars from the "dot" vars */
  1253. X        if (key == '.')
  1254. X        {
  1255. X            key = dotkey;
  1256. X            keyptr = &vikeys[key];
  1257. X            prevkey = dotpkey;
  1258. X            if (prevkey)
  1259. X            {
  1260. X                range = cursor;
  1261. X            }
  1262. X            if (count == 0)
  1263. X            {
  1264. X                count = dotcnt;
  1265. X            }
  1266. X            doingdot = TRUE;
  1267. X
  1268. X            /* remember the line before any changes are made */
  1269. X            if (U_line != markline(cursor))
  1270. X            {
  1271. X                U_line = markline(cursor);
  1272. X                strcpy(U_text, fetchline(U_line));
  1273. X            }
  1274. X        }
  1275. X        else
  1276. X        {
  1277. X            doingdot = FALSE;
  1278. X        }
  1279. X
  1280. X        /* process the key as a command */
  1281. X        tcurs = cursor;
  1282. X        switch (keyptr->args)
  1283. X        {
  1284. X          case ZERO:
  1285. X            if (count == 0)
  1286. X            {
  1287. X                tcurs = cursor & ~(BLKSIZE - 1);
  1288. X                break;
  1289. X            }
  1290. X            /* else fall through & treat like other digits... */
  1291. X
  1292. X          case DIGIT:
  1293. X            count = count * 10 + key - '0';
  1294. X            break;
  1295. X
  1296. X          case KEYWORD:
  1297. X            /* if not on a keyword, fail */
  1298. X            pfetch(markline(cursor));
  1299. X            key = markidx(cursor);
  1300. X            if (isascii(ptext[key])
  1301. X                && !isalnum(ptext[key]) && ptext[key] != '_')
  1302. X            {
  1303. X                tcurs = MARK_UNSET;
  1304. X                break;
  1305. X            }
  1306. X
  1307. X            /* find the start of the keyword */
  1308. X            while (key > 0 && (!isascii(ptext[key-1]) ||
  1309. X            isalnum(ptext[key - 1]) || ptext[key - 1] == '_'))
  1310. X            {
  1311. X                key--;
  1312. X            }
  1313. X            tcurs = (cursor & ~(BLKSIZE - 1)) + key;
  1314. X
  1315. X            /* copy it into a buffer, and NUL-terminate it */
  1316. X            i = 0;
  1317. X            do
  1318. X            {
  1319. X                text[i++] = ptext[key++];
  1320. X            } while (!isascii(ptext[key]) || isalnum(ptext[key]) || ptext[key] == '_');
  1321. X            text[i] = '\0';
  1322. X
  1323. X            /* call the function */
  1324. X            tcurs = (*keyptr->func)(text, tcurs, count);
  1325. X            count = 0L;
  1326. X            break;
  1327. X
  1328. X          case NO_ARGS:
  1329. X            if (keyptr->func)
  1330. X            {
  1331. X                (*keyptr->func)();
  1332. X            }
  1333. X            else
  1334. X            {
  1335. X                beep();
  1336. X            }
  1337. X            count = 0L;
  1338. X            break;
  1339. X    
  1340. X          case CURSOR_COUNT:
  1341. X            tcurs = (*keyptr->func)(cursor, count);
  1342. X            count = 0L;
  1343. X            break;
  1344. X    
  1345. X          case CURSOR:
  1346. X            tcurs = (*keyptr->func)(cursor);
  1347. X            count = 0L;
  1348. X            break;
  1349. X
  1350. X          case CURSOR_CNT_KEY:
  1351. X            if (doingdot)
  1352. X            {
  1353. X                tcurs = (*keyptr->func)(cursor, count, dotkey2);
  1354. X            }
  1355. X            else
  1356. X            {
  1357. X                /* get a key */
  1358. X                i = getkey(0);
  1359. X                if (i == '\033') /* ESC */
  1360. X                {
  1361. X                    count = 0;
  1362. X                    tcurs = MARK_UNSET;
  1363. X                    break; /* exit from "case CURSOR_CNT_KEY" */
  1364. X                }
  1365. X                else if (i == ('V' & 0x1f))
  1366. X                {
  1367. X                    i = getkey(0);
  1368. X                }
  1369. X
  1370. X                /* if part of an SDOT command, remember it */
  1371. X                 if (keyptr->flags & SDOT
  1372. X                 || (prevkey && vikeys[prevkey].flags & SDOT))
  1373. X                {
  1374. X                    dotkey2 = i;
  1375. X                }
  1376. X
  1377. X                /* do it */
  1378. X                tcurs = (*keyptr->func)(cursor, count, i);
  1379. X            }
  1380. X            count = 0L;
  1381. X            break;
  1382. X    
  1383. X          case CURSOR_MOVED:
  1384. X            /* '&' and uppercase keys always act like doubled */
  1385. X            if (key == '&' || isascii(key) && isupper(key))
  1386. X            {
  1387. X                prevkey = key;
  1388. X            }
  1389. X
  1390. X            if (prevkey)
  1391. X            {
  1392. X                /* doubling up a command */
  1393. X                if (!count) count = 1L;
  1394. X                range = cursor;
  1395. X                tcurs = range + MARK_AT_LINE(count - 1L);
  1396. X                count = 0L;
  1397. X            }
  1398. X            else
  1399. X            {
  1400. X                prevkey = key;
  1401. X                range = cursor;
  1402. X                key = -1; /* so we don't think we doubled yet */
  1403. X            }
  1404. X            break;
  1405. X
  1406. X          case CURSOR_EOL:
  1407. X            prevkey = key;
  1408. X            /* a zero-length line needs special treatment */
  1409. X            pfetch(markline(cursor));
  1410. X            if (plen == 0)
  1411. X            {
  1412. X                /* act on a zero-length section of text */
  1413. X                range = tcurs = cursor;
  1414. X                key = ' ';
  1415. X            }
  1416. X            else
  1417. X            {
  1418. X                /* act like CURSOR_MOVED with '$' movement */
  1419. X                range = cursor;
  1420. X                tcurs = m_rear(cursor, 1L);
  1421. X                key = '$';
  1422. X            }
  1423. X            count = 0L;
  1424. X            keyptr = &vikeys[key];
  1425. X            break;
  1426. X
  1427. X          case CURSOR_TEXT:
  1428. X              do
  1429. X              {    
  1430. X                text[0] = key;
  1431. X                if (vgets(key, text + 1, sizeof text - 1) >= 0)
  1432. X                {
  1433. X                    /* reassure user that <CR> was hit */
  1434. X                    qaddch('\r');
  1435. X                    refresh();
  1436. X
  1437. X                    /* call the function with the text */
  1438. X                    tcurs = (*keyptr->func)(cursor, text);
  1439. X                }
  1440. X                else
  1441. X                {
  1442. X                    if (exwrote || mode == MODE_COLON)
  1443. X                    {
  1444. X                        redraw(MARK_UNSET, FALSE);
  1445. X                    }
  1446. X                    mode = MODE_VI;
  1447. X                }
  1448. X            } while (mode == MODE_COLON);
  1449. X            count = 0L;
  1450. X            break;
  1451. X
  1452. X          case CURSOR_CNT_CMD:
  1453. X            tcurs = (*keyptr->func)(cursor, count, key);
  1454. X            count = 0L;
  1455. X            break;
  1456. X        }
  1457. X
  1458. X        /* if that command took us out of vi mode, then exit the loop
  1459. X         * NOW, without tweaking the cursor or anything.  This is very
  1460. X         * important when mode == MODE_QUIT.
  1461. X         */
  1462. X        if (mode != MODE_VI)
  1463. X        {
  1464. X            break;
  1465. X        }
  1466. X
  1467. X        /* now move the cursor, as appropriate */
  1468. X        if (keyptr->args == CURSOR_MOVED)
  1469. X        {
  1470. X            /* the < and > keys have FRNT,
  1471. X             * but it shouldn't be applied yet
  1472. X             */
  1473. X            tcurs = adjmove(cursor, tcurs, 0);
  1474. X        }
  1475. X        else
  1476. X        {
  1477. X            tcurs = adjmove(cursor, tcurs, (int)keyptr->flags);
  1478. X        }
  1479. X
  1480. X        /* was that the end of a d/c/y/</>/! command? */
  1481. X        if (prevkey && (prevkey == key || (keyptr->flags & MVMT)) && count == 0L)
  1482. X        {
  1483. X            /* if the movement command failed, cancel operation */
  1484. X            if (tcurs == MARK_UNSET)
  1485. X            {
  1486. X                prevkey = 0;
  1487. X                count = 0;
  1488. X                continue;
  1489. X            }
  1490. X
  1491. X            /* make sure range=front and tcurs=rear.  Either way,
  1492. X             * leave cursor=range since that's where we started.
  1493. X             */
  1494. X            cursor = range;
  1495. X            if (tcurs < range)
  1496. X            {
  1497. X                range = tcurs;
  1498. X                tcurs = cursor;
  1499. X            }
  1500. X
  1501. X
  1502. X            /* adjust for line mode & inclusion of last char/line */
  1503. X            i = (keyptr->flags | vikeys[prevkey].flags);
  1504. X            if (key == prevkey)
  1505. X            {
  1506. X                i |= (INCL|LNMD);
  1507. X            }
  1508. X            switch (i & (INCL|LNMD))
  1509. X            {
  1510. X              case INCL:
  1511. X                tcurs++;
  1512. X                break;
  1513. X
  1514. X              case INCL|LNMD:
  1515. X                tcurs += BLKSIZE;
  1516. X                /* fall through... */
  1517. X
  1518. X              case LNMD:
  1519. X                range &= ~(BLKSIZE - 1);
  1520. X                tcurs &= ~(BLKSIZE - 1);
  1521. X                break;
  1522. X            }
  1523. X
  1524. X            /* run the function */
  1525. X            tcurs = (*vikeys[prevkey].func)(range, tcurs);
  1526. X            (void)adjmove(cursor, cursor, 0);
  1527. X            cursor = adjmove(cursor, tcurs, (int)vikeys[prevkey].flags);
  1528. X
  1529. X            /* cleanup */
  1530. X            prevkey = 0;
  1531. X        }
  1532. X        else if (!prevkey)
  1533. X        {
  1534. X            cursor = tcurs;
  1535. X        }
  1536. X    }
  1537. X}
  1538. X
  1539. X/* This function adjusts the MARK value that they return; here we make sure
  1540. X * it isn't past the end of the line, and that the column hasn't been
  1541. X * *accidentally* changed.
  1542. X */
  1543. XMARK adjmove(old, new, flags)
  1544. X    MARK        old;    /* the cursor position before the command */
  1545. X    REG MARK    new;    /* the cursor position after the command */
  1546. X    int        flags;    /* various flags regarding cursor mvmt */
  1547. X{
  1548. X    static int    colno;    /* the column number that we want */
  1549. X    REG char    *text;    /* used to scan through the line's text */
  1550. X    REG int        i;
  1551. X
  1552. X#ifdef DEBUG
  1553. X    watch();
  1554. X#endif
  1555. X
  1556. X    /* if the command failed, bag it! */
  1557. X    if (new == MARK_UNSET)
  1558. X    {
  1559. X        beep();
  1560. X        return old;
  1561. X    }
  1562. X
  1563. X    /* if this is a non-relative movement, set the '' mark */
  1564. X    if (flags & NREL)
  1565. X    {
  1566. X        mark[26] = old;
  1567. X    }
  1568. X
  1569. X    /* make sure it isn't past the end of the file */
  1570. X    if (markline(new) < 1)
  1571. X    {
  1572. X        new = MARK_FIRST;
  1573. X    }
  1574. X    else if (markline(new) > nlines)
  1575. X    {
  1576. X        new = MARK_LAST;
  1577. X    }
  1578. X
  1579. X    /* fetch the new line */
  1580. X    pfetch(markline(new));
  1581. X
  1582. X    /* move to the front, if we're supposed to */
  1583. X    if (flags & FRNT)
  1584. X    {
  1585. X        new = m_front(new, 1L);
  1586. X    }
  1587. X
  1588. X    /* change the column#, or change the mark to suit the column# */
  1589. X    if (!(flags & NCOL))
  1590. X    {
  1591. X        /* change the column# */
  1592. X        i = markidx(new);
  1593. X        if (i == BLKSIZE - 1)
  1594. X        {
  1595. X            new &= ~(BLKSIZE - 1);
  1596. X            if (plen > 0)
  1597. X            {
  1598. X                new += plen - 1;
  1599. X            }
  1600. X            colno = BLKSIZE * 8; /* one heck of a big colno */
  1601. X        }
  1602. X        else if (plen > 0)
  1603. X        {
  1604. X            if (i >= plen)
  1605. X            {
  1606. X                new = (new & ~(BLKSIZE - 1)) + plen - 1;
  1607. X            }
  1608. X            colno = idx2col(new, ptext, FALSE);
  1609. X        }
  1610. X        else
  1611. X        {
  1612. X            new &= ~(BLKSIZE - 1);
  1613. X            colno = 0;
  1614. X        }
  1615. X    }
  1616. X    else
  1617. X    {
  1618. X        /* adjust the mark to get as close as possible to column# */
  1619. X        for (i = 0, text = ptext; i <= colno && *text; text++)
  1620. X        {
  1621. X            if (*text == '\t' && !*o_list)
  1622. X            {
  1623. X                i += *o_tabstop - (i % *o_tabstop);
  1624. X            }
  1625. X            else if (UCHAR(*text) < ' ' || *text == 127)
  1626. X            {
  1627. X                i += 2;
  1628. X            }
  1629. X#ifndef NO_CHARATTR
  1630. X            else if (*o_charattr && text[0] == '\\' && text[1] == 'f' && text[2])
  1631. X            {
  1632. X                text += 2; /* plus one more in "for()" stmt */
  1633. X            }
  1634. X#endif
  1635. X            else
  1636. X            {
  1637. X                i++;
  1638. X            }
  1639. X        }
  1640. X        if (text > ptext)
  1641. X        {
  1642. X            text--;
  1643. X        }
  1644. X        new = (new & ~(BLKSIZE - 1)) + (int)(text - ptext);
  1645. X    }
  1646. X
  1647. X    return new;
  1648. X}
  1649. X
  1650. X
  1651. X#ifdef DEBUG
  1652. Xwatch()
  1653. X{
  1654. X    static wasset;
  1655. X
  1656. X    if (*origname)
  1657. X    {
  1658. X        wasset = TRUE;
  1659. X    }
  1660. X    else if (wasset)
  1661. X    {
  1662. X        msg("origname was clobbered");
  1663. X        endwin();
  1664. X        abort();
  1665. X    }
  1666. X
  1667. X    if (nlines == 0)
  1668. X    {
  1669. X        msg("nlines=0");
  1670. X        endwin();
  1671. X        abort();
  1672. X    }
  1673. X}
  1674. X#endif
  1675. eof
  1676. if test `wc -c <vi.c` -ne 20322
  1677. then
  1678. echo vi.c damaged!
  1679. fi
  1680. fi
  1681.  
  1682. if test -f vi.h -a "$1" != -f
  1683. then
  1684. echo Will not overwrite vi.h
  1685. else
  1686. echo Extracting vi.h
  1687. sed 's/^X//' >vi.h <<\eof
  1688. X/* vi.h */
  1689. X
  1690. X/* Author:
  1691. X *    Steve Kirkendall
  1692. X *    14407 SW Teal Blvd. #C
  1693. X *    Beaverton, OR 97005
  1694. X *    kirkenda@cs.pdx.edu
  1695. X */
  1696. X
  1697. X
  1698. X/* This is the header file for my version of vi. */
  1699. X
  1700. X#define VERSION "ELVIS 1.4, by Steve Kirkendall"
  1701. X#define COPYING    "This version of ELVIS is freely redistributable."
  1702. X
  1703. X#include <errno.h>
  1704. Xextern int errno;
  1705. X#if TOS
  1706. X#define ENOENT (-AEFILNF)
  1707. X#endif
  1708. X
  1709. X#if TOS
  1710. X# include <types.h>
  1711. X# define O_RDONLY    0
  1712. X# define O_WRONLY    1
  1713. X# define O_RDWR        2
  1714. X#else
  1715. X# if OSK
  1716. X#  include <modes.h>
  1717. X#  define O_RDONLY    S_IREAD
  1718. X#  define O_WRONLY    S_IWRITE
  1719. X#  define O_RDWR    (S_IREAD | S_IWRITE)
  1720. X#  define ENOENT    E_PNNF
  1721. X# else
  1722. X#  include <sys/types.h>
  1723. X#  if COHERENT
  1724. X#   include <sys/fcntl.h>
  1725. X#  else
  1726. X#   include <fcntl.h>
  1727. X#  endif
  1728. X# endif
  1729. X#endif
  1730. X
  1731. X#ifndef O_BINARY
  1732. X# define O_BINARY    0
  1733. X#endif
  1734. X
  1735. X#include "curses.h"
  1736. X
  1737. X/*------------------------------------------------------------------------*/
  1738. X/* Miscellaneous constants.                          */
  1739. X
  1740. X#define INFINITY    2000000001L    /* a very large integer */
  1741. X#define LONGKEY        10        /* longest possible raw :map key */
  1742. X#ifndef MAXRCLEN
  1743. X# define MAXRCLEN    1000        /* longest possible .exrc file */
  1744. X#endif
  1745. X
  1746. X/*------------------------------------------------------------------------*/
  1747. X/* These describe how temporary files are divided into blocks             */
  1748. X
  1749. X#define BLKSIZE    1024        /* size of blocks */
  1750. X#define MAXBLKS    (BLKSIZE / sizeof(unsigned short))
  1751. Xtypedef union
  1752. X{
  1753. X    char        c[BLKSIZE];    /* for text blocks */
  1754. X    unsigned short    n[MAXBLKS];    /* for the header block */
  1755. X}
  1756. X    BLK;
  1757. X
  1758. X/*------------------------------------------------------------------------*/
  1759. X/* These are used manipulate BLK buffers.                                 */
  1760. X
  1761. Xextern BLK    hdr;        /* buffer for the header block */
  1762. Xextern BLK    *blkget();    /* given index into hdr.c[], reads block */
  1763. Xextern BLK    *blkadd();    /* inserts a new block into hdr.c[] */
  1764. X
  1765. X/*------------------------------------------------------------------------*/
  1766. X/* These are used to keep track of various flags                          */
  1767. Xextern struct _viflags
  1768. X{
  1769. X    short    file;        /* file flags */
  1770. X}
  1771. X    viflags;
  1772. X
  1773. X/* file flags */
  1774. X#define NEWFILE        0x0001    /* the file was just created */
  1775. X#define READONLY    0x0002    /* the file is read-only */
  1776. X#define HADNUL        0x0004    /* the file contained NUL characters */
  1777. X#define MODIFIED    0x0008    /* the file has been modified */
  1778. X#define NOFILE        0x0010    /* no name is known for the current text */
  1779. X#define ADDEDNL        0x0020    /* newlines were added to the file */
  1780. X
  1781. X/* macros used to set/clear/test flags */
  1782. X#define setflag(x,y)    viflags.x |= y
  1783. X#define clrflag(x,y)    viflags.x &= ~y
  1784. X#define tstflag(x,y)    (viflags.x & y)
  1785. X#define initflags()    viflags.file = 0;
  1786. X
  1787. X/* The options */
  1788. Xextern char    o_autoindent[1];
  1789. Xextern char    o_autoprint[1];
  1790. Xextern char    o_autowrite[1];
  1791. X#ifndef NO_ERRLIST
  1792. Xextern char    o_cc[30];
  1793. X#endif
  1794. X#ifndef NO_CHARATTR
  1795. Xextern char    o_charattr[1];
  1796. X#endif
  1797. Xextern char    o_columns[3];
  1798. Xextern char    o_digraph[1];
  1799. Xextern char    o_directory[30];
  1800. Xextern char    o_edcompatible[1];
  1801. Xextern char    o_errorbells[1];
  1802. Xextern char    o_exrefresh[1];
  1803. X#ifndef NO_DIGRAPH
  1804. Xextern char    o_flipcase[80];
  1805. X#endif
  1806. X#ifndef NO_SENTENCE
  1807. Xextern char    o_hideformat[1];
  1808. X#endif
  1809. Xextern char    o_ignorecase[1];
  1810. X#ifndef NO_EXTENSIONS
  1811. Xextern char    o_inputmode[1];
  1812. X#endif
  1813. Xextern char    o_keytime[3];
  1814. Xextern char    o_keywordprg[80];
  1815. Xextern char    o_lines[3];
  1816. Xextern char    o_list[1];
  1817. X#ifndef NO_MAGIC
  1818. Xextern char    o_magic[1];
  1819. X#endif
  1820. X#ifndef NO_ERRLIST
  1821. Xextern char    o_make[30];
  1822. X#endif
  1823. X#ifndef NO_MODELINE
  1824. Xextern char    o_modeline[1];
  1825. X#endif
  1826. X#ifndef NO_SENTENCE
  1827. Xextern char    o_paragraphs[30];
  1828. X#endif
  1829. X#if MSDOS
  1830. Xextern char    o_pcbios[1];
  1831. X#endif
  1832. Xextern char    o_readonly[1];
  1833. Xextern char    o_report[3];
  1834. Xextern char    o_scroll[3];
  1835. X#ifndef NO_SENTENCE
  1836. Xextern char    o_sections[30];
  1837. X#endif
  1838. Xextern char    o_shell[60];
  1839. X#ifndef NO_SHOWMATCH
  1840. Xextern char    o_showmatch[1];
  1841. X#endif
  1842. X#ifndef NO_SHOWMODE
  1843. Xextern char    o_smd[1];
  1844. X#endif
  1845. Xextern char    o_shiftwidth[3];
  1846. Xextern char    o_sidescroll[3];
  1847. Xextern char    o_sync[1];
  1848. Xextern char    o_tabstop[3];
  1849. Xextern char    o_term[30];
  1850. Xextern char    o_vbell[1];
  1851. Xextern char    o_warn[1];
  1852. Xextern char    o_wrapmargin[3];
  1853. Xextern char    o_wrapscan[1];
  1854. X
  1855. X/*------------------------------------------------------------------------*/
  1856. X/* These help support the single-line multi-change "undo" -- shift-U      */
  1857. X
  1858. Xextern char    U_text[BLKSIZE];
  1859. Xextern long    U_line;
  1860. X
  1861. X/*------------------------------------------------------------------------*/
  1862. X/* These are used to refer to places in the text               */
  1863. X
  1864. Xtypedef long    MARK;
  1865. X#define markline(x)    (long)((x) / BLKSIZE)
  1866. X#define markidx(x)    (int)((x) & (BLKSIZE - 1))
  1867. X#define MARK_UNSET    ((MARK)0)
  1868. X#define MARK_FIRST    ((MARK)BLKSIZE)
  1869. X#define MARK_LAST    ((MARK)(nlines * BLKSIZE))
  1870. X#define MARK_AT_LINE(x)    ((MARK)((x) * BLKSIZE))
  1871. X
  1872. X#define NMARKS    29
  1873. Xextern MARK    mark[NMARKS];    /* marks a-z, plus mark ' and two temps */
  1874. Xextern MARK    cursor;        /* mark where line is */
  1875. X
  1876. X/*------------------------------------------------------------------------*/
  1877. X/* These are used to keep track of the current & previous files.      */
  1878. X
  1879. Xextern long    origtime;    /* modification date&time of the current file */
  1880. Xextern char    origname[256];    /* name of the current file */
  1881. Xextern char    prevorig[256];    /* name of the preceding file */
  1882. Xextern long    prevline;    /* line number from preceding file */
  1883. X
  1884. X/*------------------------------------------------------------------------*/
  1885. X/* misc housekeeping variables & functions                  */
  1886. X
  1887. Xextern int    tmpfd;        /* fd used to access the tmp file */
  1888. Xextern long    lnum[MAXBLKS];    /* last line# of each block */
  1889. Xextern long    nlines;        /* number of lines in the file */
  1890. Xextern char    args[BLKSIZE];    /* file names given on the command line */
  1891. Xextern int    argno;        /* the current element of args[] */
  1892. Xextern int    nargs;        /* number of filenames in args */
  1893. Xextern long    changes;    /* counts changes, to prohibit short-cuts */
  1894. Xextern int    significant;    /* boolean: was a *REAL* change made? */
  1895. Xextern int    mustredraw;    /* boolean: force total redraw of screen? */
  1896. Xextern BLK    tmpblk;        /* a block used to accumulate changes */
  1897. Xextern long    topline;    /* file line number of top line */
  1898. Xextern int    leftcol;    /* column number of left col */
  1899. X#define        botline     (topline + LINES - 2)
  1900. X#define        rightcol (leftcol + COLS - 1)
  1901. Xextern int    physcol;    /* physical column number that cursor is on */
  1902. Xextern int    physrow;    /* physical row number that cursor is on */
  1903. Xextern int    exwrote;    /* used to detect verbose ex commands */
  1904. Xextern int    doingdot;    /* boolean: are we doing the "." command? */
  1905. Xextern int    doingglobal;    /* boolean: are doing a ":g" command? */
  1906. Xextern long    rptlines;    /* number of lines affected by a command */
  1907. Xextern char    *rptlabel;    /* description of how lines were affected */
  1908. Xextern char    *fetchline();    /* read a given line from tmp file */
  1909. Xextern char    *parseptrn();    /* isolate a regexp in a line */
  1910. Xextern MARK    paste();    /* paste from cut buffer to a given point */
  1911. Xextern char    *wildcard();    /* expand wildcards in filenames */
  1912. Xextern MARK    input();    /* inserts characters from keyboard */
  1913. Xextern char    *linespec();    /* finds the end of a /regexp/ string */
  1914. X#define        ctrl(ch) ((ch)&037)
  1915. X#ifndef NO_RECYCLE
  1916. Xextern long    allocate();    /* allocate a free block of the tmp file */
  1917. X#endif
  1918. Xextern int    trapint();    /* trap handler for SIGINT */
  1919. Xextern void    blkdirty();    /* marks a block as being "dirty" */
  1920. Xextern void    blkflush();    /* writes a single dirty block to the disk */
  1921. Xextern void    blksync();    /* forces all "dirty" blocks to disk */
  1922. Xextern void    blkinit();    /* resets the block cache to "empty" state */
  1923. Xextern void    beep();        /* rings the terminal's bell */
  1924. Xextern void    exrefresh();    /* writes text to the screen */
  1925. Xextern void    msg();        /* writes a printf-style message to the screen */
  1926. Xextern void    reset_msg();    /* resets the "manymsgs" flag */
  1927. Xextern void    endmsgs();    /* if "manymsgs" is set, then scroll up 1 line */
  1928. Xextern void    garbage();    /* reclaims any garbage blocks */
  1929. Xextern void    redraw();    /* updates the screen after a change */
  1930. Xextern void    resume_curses();/* puts the terminal in "cbreak" mode */
  1931. Xextern void    beforedo();    /* saves current revision before a new change */
  1932. Xextern void    afterdo();    /* marks end of a beforedo() change */
  1933. Xextern void    abortdo();    /* like "afterdo()" followed by "undo()" */
  1934. Xextern int    undo();        /* restores file to previous undo() */
  1935. Xextern void    dumpkey();    /* lists key mappings to the screen */
  1936. Xextern void    mapkey();    /* defines a new key mapping */
  1937. Xextern void    savekeys();    /* lists key mappings to a file */
  1938. Xextern void    redrawrange();    /* records clues from modify.c */
  1939. Xextern void    cut();        /* saves text in a cut buffer */
  1940. Xextern void    delete();    /* deletes text */
  1941. Xextern void    add();        /* adds text */
  1942. Xextern void    change();    /* deletes text, and then adds other text */
  1943. Xextern void    cutswitch();    /* updates cut buffers when we switch files */
  1944. Xextern void    do_abbr();    /* defines or lists abbreviations */
  1945. Xextern void    do_digraph();    /* defines or lists digraphs */
  1946. Xextern void    exstring();    /* execute a string as EX commands */
  1947. Xextern void    dumpopts();
  1948. Xextern void    setopts();
  1949. Xextern void    saveopts();
  1950. X#ifndef NO_DIGRAPH
  1951. Xextern void    savedigs();
  1952. X#endif
  1953. X#ifndef NO_ABBR
  1954. Xextern void    saveabbr();
  1955. X#endif
  1956. Xextern void    cutname();
  1957. Xextern void    cutname();
  1958. Xextern void    initopts();
  1959. Xextern void    cutend();
  1960. X
  1961. X/*------------------------------------------------------------------------*/
  1962. X/* macros that are used as control structures                             */
  1963. X
  1964. X#define BeforeAfter(before, after) for((before),bavar=1;bavar;(after),bavar=0)
  1965. X#define ChangeText    BeforeAfter(beforedo(FALSE),afterdo())
  1966. X
  1967. Xextern int    bavar;        /* used only in BeforeAfter macros */
  1968. X
  1969. X/*------------------------------------------------------------------------*/
  1970. X/* These are the movement commands.  Each accepts a mark for the starting */
  1971. X/* location & number and returns a mark for the destination.          */
  1972. X
  1973. Xextern MARK    m_updnto();        /* k j G */
  1974. Xextern MARK    m_right();        /* h */
  1975. Xextern MARK    m_left();        /* l */
  1976. Xextern MARK    m_tocol();        /* | */
  1977. Xextern MARK    m_front();        /* ^ */
  1978. Xextern MARK    m_rear();        /* $ */
  1979. Xextern MARK    m_fword();        /* w */
  1980. Xextern MARK    m_bword();        /* b */
  1981. Xextern MARK    m_eword();        /* e */
  1982. Xextern MARK    m_fWord();        /* W */
  1983. Xextern MARK    m_bWord();        /* B */
  1984. Xextern MARK    m_eWord();        /* E */
  1985. Xextern MARK    m_fparagraph();        /* } */
  1986. Xextern MARK    m_bparagraph();        /* { */
  1987. Xextern MARK    m_fsection();        /* ]] */
  1988. Xextern MARK    m_bsection();        /* [[ */
  1989. Xextern MARK    m_match();        /* % */
  1990. X#ifndef NO_SENTENCE
  1991. X extern MARK    m_fsentence();        /* ) */
  1992. X extern MARK    m_bsentence();        /* ( */
  1993. X#endif
  1994. Xextern MARK    m_tomark();        /* 'm */
  1995. Xextern MARK    m_nsrch();        /* n */
  1996. Xextern MARK    m_Nsrch();        /* N */
  1997. Xextern MARK    m_fsrch();        /* /regexp */
  1998. Xextern MARK    m_bsrch();        /* ?regexp */
  1999. X#ifndef NO_CHARSEARCH
  2000. X extern MARK    m__ch();        /* ; , */
  2001. X extern MARK    m_fch();        /* f */
  2002. X extern MARK    m_tch();        /* t */
  2003. X extern MARK    m_Fch();        /* F */
  2004. X extern MARK    m_Tch();        /* T */
  2005. X#endif
  2006. Xextern MARK    m_row();        /* H L M */
  2007. Xextern MARK    m_z();            /* z */
  2008. Xextern MARK    m_scroll();        /* ^B ^F ^E ^Y ^U ^D */
  2009. X
  2010. X/* Some stuff that is used by movement functions... */
  2011. X
  2012. Xextern MARK    adjmove();        /* a helper fn, used by move fns */
  2013. X
  2014. X/* This macro is used to set the default value of cnt */
  2015. X#define DEFAULT(val)    if (cnt < 1) cnt = (val)
  2016. X
  2017. X/* These are used to minimize calls to fetchline() */
  2018. Xextern int    plen;    /* length of the line */
  2019. Xextern long    pline;    /* line number that len refers to */
  2020. Xextern long    pchgs;    /* "changes" level that len refers to */
  2021. Xextern char    *ptext;    /* text of previous line, if valid */
  2022. Xextern void    pfetch();
  2023. Xextern char    digraph();
  2024. X
  2025. X/* This is used to build a MARK that corresponds to a specific point in the
  2026. X * line that was most recently pfetch'ed.
  2027. X */
  2028. X#define buildmark(text)    (MARK)(BLKSIZE * pline + (int)((text) - ptext))
  2029. X
  2030. X
  2031. X/*------------------------------------------------------------------------*/
  2032. X/* These are used to handle EX commands.                  */
  2033. X
  2034. X#define  CMD_NULL    0    /* NOT A VALID COMMAND */
  2035. X#define  CMD_ABBR    1    /* "define an abbreviation" */
  2036. X#define  CMD_ARGS    2    /* "show me the args" */
  2037. X#define  CMD_APPEND    3    /* "insert lines after this line" */
  2038. X#define  CMD_AT        4    /* "execute a cut buffer's contents via EX" */
  2039. X#define  CMD_BANG    5    /* "run a single shell command" */
  2040. X#define  CMD_CC        6    /* "run `cc` and then do CMD_ERRLIST" */
  2041. X#define  CMD_CD        7    /* "change directories" */
  2042. X#define  CMD_CHANGE    8    /* "change some lines" */
  2043. X#define  CMD_COPY    9    /* "copy the selected text to a given place" */
  2044. X#define  CMD_DELETE    10    /* "delete the selected text" */
  2045. X#define  CMD_DIGRAPH    11    /* "add a digraph, or display them all" */
  2046. X#define  CMD_EDIT    12    /* "switch to a different file" */
  2047. X#define  CMD_EQUAL    13    /* "display a line number" */
  2048. X#define  CMD_ERRLIST    14    /* "locate the next error in a list" */
  2049. X#define  CMD_FILE    15    /* "show the file's status" */
  2050. X#define  CMD_GLOBAL    16    /* "globally search & do a command" */
  2051. X#define  CMD_INSERT    17    /* "insert lines before the current line" */
  2052. X#define  CMD_JOIN    18    /* "join the selected line & the one after" */
  2053. X#define  CMD_LIST    19    /* "print lines, making control chars visible" */
  2054. X#define  CMD_MAKE    20    /* "run `make` and then do CMD_ERRLIST" */
  2055. X#define  CMD_MAP    21    /* "adjust the keyboard map" */
  2056. X#define  CMD_MARK    22    /* "mark this line" */
  2057. X#define  CMD_MKEXRC    23    /* "make a .exrc file" */
  2058. X#define  CMD_MOVE    24    /* "move the selected text to a given place" */
  2059. X#define  CMD_NEXT    25    /* "switch to next file in args" */
  2060. X#define  CMD_NUMBER    26    /* "print lines from the file w/ line numbers" */
  2061. X#define  CMD_PRESERVE    27    /* "act as though vi crashed" */
  2062. X#define  CMD_PREVIOUS    28    /* "switch to the previous file in args" */
  2063. X#define  CMD_PRINT    29    /* "print the selected text" */
  2064. X#define  CMD_PUT    30    /* "insert any cut lines before this line" */
  2065. X#define  CMD_QUIT    31    /* "quit without writing the file" */
  2066. X#define  CMD_READ    32    /* "append the given file after this line */
  2067. X#define  CMD_RECOVER    33    /* "recover file after vi crashes" - USE -r FLAG */
  2068. X#define  CMD_REWIND    34    /* "rewind to first file" */
  2069. X#define  CMD_SET    35    /* "set a variable's value" */
  2070. X#define  CMD_SHELL    36    /* "run some lines through a command" */
  2071. X#define  CMD_SHIFTL    37    /* "shift lines left" */
  2072. X#define  CMD_SHIFTR    38    /* "shift lines right" */
  2073. X#define  CMD_SOURCE    39    /* "interpret a file's contents as ex commands" */
  2074. X#define  CMD_STOP    40    /* same as CMD_SUSPEND */
  2075. X#define  CMD_SUBAGAIN    41    /* "repeat the previous substitution" */
  2076. X#define  CMD_SUBSTITUTE    42    /* "substitute text in this line" */
  2077. X#define  CMD_SUSPEND    43    /* "suspend the vi session" */
  2078. X#define  CMD_TR        44    /* "transliterate chars in the selected lines" */
  2079. X#define  CMD_TAG    45    /* "go to a particular tag" */
  2080. X#define  CMD_UNABBR    46    /* "remove an abbreviation definition" */
  2081. X#define  CMD_UNDO    47    /* "undo the previous command" */
  2082. X#define  CMD_UNMAP    48    /* "remove a key sequence map */
  2083. X#define  CMD_VERSION    49    /* "describe which version this is" */
  2084. X#define  CMD_VGLOBAL    50    /* "apply a cmd to lines NOT containing an RE" */
  2085. X#define  CMD_VISUAL    51    /* "go into visual mode" */
  2086. X#define  CMD_WQUIT    52    /* "write this file out (any case) & quit" */
  2087. X#define  CMD_WRITE    53    /* "write the selected(?) text to a given file" */
  2088. X#define  CMD_XIT    54    /* "write this file out (if modified) & quit" */
  2089. X#define  CMD_YANK    55    /* "copy the selected text into the cut buffer" */
  2090. X#ifdef DEBUG
  2091. X# define CMD_DEBUG    56    /* access to internal data structures */
  2092. X# define CMD_VALIDATE    57    /* check for internal consistency */
  2093. X#endif
  2094. Xtypedef int CMD;
  2095. X
  2096. Xextern void    ex();
  2097. Xextern void    vi();
  2098. Xextern void    doexcmd();
  2099. X
  2100. X#ifndef NO_ABBR
  2101. Xextern void    cmd_abbr();
  2102. X#endif
  2103. Xextern void    cmd_append();
  2104. Xextern void    cmd_args();
  2105. X#ifndef NO_AT
  2106. Xextern void    cmd_at();
  2107. X#endif
  2108. Xextern void    cmd_cd();
  2109. Xextern void    cmd_delete();
  2110. X#ifndef NO_DIGRAPH
  2111. Xextern void    cmd_digraph();
  2112. X#endif
  2113. Xextern void    cmd_edit();
  2114. X#ifndef NO_ERRLIST
  2115. Xextern void    cmd_errlist();
  2116. X#endif
  2117. Xextern void    cmd_file();
  2118. Xextern void    cmd_global();
  2119. Xextern void    cmd_join();
  2120. Xextern void    cmd_mark();
  2121. X#ifndef NO_ERRLIST
  2122. Xextern void    cmd_make();
  2123. X#endif
  2124. Xextern void    cmd_map();
  2125. X#ifndef NO_MKEXRC
  2126. Xextern void    cmd_mkexrc();
  2127. X#endif
  2128. Xextern void    cmd_next();
  2129. Xextern void    cmd_print();
  2130. Xextern void    cmd_put();
  2131. Xextern void    cmd_read();
  2132. Xextern void    cmd_set();
  2133. Xextern void    cmd_shell();
  2134. Xextern void    cmd_shift();
  2135. Xextern void    cmd_source();
  2136. Xextern void    cmd_substitute();
  2137. Xextern void    cmd_tag();
  2138. Xextern void    cmd_undo();
  2139. Xextern void    cmd_version();
  2140. Xextern void    cmd_visual();
  2141. Xextern void    cmd_write();
  2142. Xextern void    cmd_xit();
  2143. Xextern void    cmd_move();
  2144. X#ifdef DEBUG
  2145. Xextern void    cmd_debug();
  2146. Xextern void    cmd_validate();
  2147. X#endif
  2148. X
  2149. X/*----------------------------------------------------------------------*/
  2150. X/* These are used to handle VI commands                 */
  2151. X
  2152. Xextern MARK    v_1ex();    /* : */
  2153. Xextern MARK    v_mark();    /* m */
  2154. Xextern MARK    v_quit();    /* Q */
  2155. Xextern MARK    v_redraw();    /* ^L ^R */
  2156. Xextern MARK    v_ulcase();    /* ~ */
  2157. Xextern MARK    v_undo();    /* u */
  2158. Xextern MARK    v_xchar();    /* x */
  2159. Xextern MARK    v_Xchar();    /* X */
  2160. Xextern MARK    v_replace();    /* r */
  2161. Xextern MARK    v_overtype();    /* R */
  2162. Xextern MARK    v_selcut();    /* " */
  2163. Xextern MARK    v_paste();    /* p P */
  2164. Xextern MARK    v_yank();    /* y Y */
  2165. Xextern MARK    v_delete();    /* d D */
  2166. Xextern MARK    v_join();    /* J */
  2167. Xextern MARK    v_insert();    /* a A i I o O */
  2168. Xextern MARK    v_change();    /* c C */
  2169. Xextern MARK    v_subst();    /* s */
  2170. Xextern MARK    v_lshift();    /* < */
  2171. Xextern MARK    v_rshift();    /* > */
  2172. Xextern MARK    v_filter();    /* ! */
  2173. Xextern MARK    v_status();    /* ^G */
  2174. Xextern MARK    v_switch();    /* ^^ */
  2175. Xextern MARK    v_tag();    /* ^] */
  2176. Xextern MARK    v_xit();    /* ZZ */
  2177. Xextern MARK    v_undoline();    /* U */
  2178. Xextern MARK    v_again();    /* & */
  2179. X#ifndef NO_EXTENSIONS
  2180. X extern MARK    v_keyword();    /* ^K */
  2181. X extern MARK    v_increment();    /* * */
  2182. X#endif
  2183. X#ifndef NO_ERRLIST
  2184. X extern MARK    v_errlist();    /* * */
  2185. X#endif
  2186. X#ifndef NO_AT
  2187. X extern MARK    v_at();        /* @ */
  2188. X#endif
  2189. X
  2190. X/*----------------------------------------------------------------------*/
  2191. X/* These describe what mode we're in */
  2192. X
  2193. X#define MODE_EX        1    /* executing ex commands */
  2194. X#define    MODE_VI        2    /* executing vi commands */
  2195. X#define    MODE_COLON    3    /* executing an ex command from vi mode */
  2196. X#define    MODE_QUIT    4
  2197. Xextern int    mode;
  2198. X
  2199. X#define WHEN_VICMD    1    /* getkey: we're reading a VI command */
  2200. X#define WHEN_VIINP    2    /* getkey: we're in VI's INPUT mode */
  2201. X#define WHEN_VIREP    4    /* getkey: we're in VI's REPLACE mode */
  2202. X#define WHEN_EX        8    /* getkey: we're in EX mode */
  2203. X#define WHEN_MSG    16    /* getkey: we're at a "more" prompt */
  2204. X#define WHEN_INMV    256    /* in input mode, interpret the key in VICMD mode */
  2205. eof
  2206. if test `wc -c <vi.h` -ne 18110
  2207. then
  2208. echo vi.h damaged!
  2209. fi
  2210. fi
  2211.  
  2212. if test -f refont.c -a "$1" != -f
  2213. then
  2214. echo Will not overwrite refont.c
  2215. else
  2216. echo Extracting refont.c
  2217. sed 's/^X//' >refont.c <<\eof
  2218. X/* refont.c */
  2219. X
  2220. X/* Author:
  2221. X *    Steve Kirkendall
  2222. X *    14407 SW Teal Blvd. #C
  2223. X *    Beaverton, OR 97005
  2224. X *    kirkenda@cs.pdx.edu
  2225. X */
  2226. X
  2227. X
  2228. X/* This file contains the complete source code for the refont program */
  2229. X
  2230. X/* The refont program converts font designations to the format of your choice.
  2231. X * Known font formats are:
  2232. X *    -b    overtype notation, using backspaces
  2233. X *    -c    overtype notation, using carriage returns
  2234. X *    -d    the "dot" command notation used by nroff (doesn't work well)
  2235. X *    -e    Epson-compatible line printer codes
  2236. X *    -f    the "\f" notation
  2237. X *    -x    none (strip out the font codes)
  2238. X *
  2239. X * Other flags are:
  2240. X *    -I    recognize \f and dot notations in input
  2241. X *    -F    output a formfeed character between files
  2242. X */
  2243. X
  2244. X#include <stdio.h>
  2245. X#include "config.h"
  2246. X
  2247. X/* the program name, for diagnostics */
  2248. Xchar    *progname;
  2249. X
  2250. X/* remembers which output format to use */
  2251. Xint outfmt = 'f';
  2252. X
  2253. X/* do we allow "dot" and "backslash-f" on input? */
  2254. Xint infmt = 0;
  2255. X
  2256. X/* do we insert formfeeds between input files? */
  2257. Xint add_form_feed = 0;
  2258. X
  2259. Xmain(argc, argv)
  2260. X    int    argc;    /* number of command-line args */
  2261. X    char    **argv;    /* values of the command line args */
  2262. X{
  2263. X    FILE    *fp;
  2264. X    int    i, j;
  2265. X    int    retcode;
  2266. X
  2267. X    progname = argv[0];
  2268. X
  2269. X    /* parse the flags */
  2270. X    i = 1;
  2271. X    if (i < argc && argv[i][0] == '-' && argv[i][1])
  2272. X    {
  2273. X        for (j = 1; argv[i][j]; j++)
  2274. X        {
  2275. X            switch (argv[i][j])
  2276. X            {
  2277. X              case 'b':
  2278. X#if !OSK
  2279. X              case 'c':
  2280. X#endif
  2281. X              case 'd':
  2282. X              case 'e':
  2283. X              case 'f':
  2284. X              case 'x':
  2285. X                outfmt = argv[i][j];
  2286. X                break;
  2287. X
  2288. X              case 'I':
  2289. X                infmt = 'I';
  2290. X                break;
  2291. X
  2292. X              case 'F':
  2293. X                add_form_feed = 1;
  2294. X                break;
  2295. X
  2296. X              default:
  2297. X                usage();
  2298. X            }
  2299. X        }
  2300. X        i++;
  2301. X    }
  2302. X
  2303. X    retcode = 0;
  2304. X    if (i == argc)
  2305. X    {
  2306. X        /* probably shouldn't read from keyboard */
  2307. X        if (isatty(fileno(stdin)))
  2308. X        {
  2309. X            usage();
  2310. X        }
  2311. X
  2312. X        /* no files named, so use stdin */
  2313. X        refont(stdin);
  2314. X    }
  2315. X    else
  2316. X    {
  2317. X        for (; i < argc; i++)
  2318. X        {
  2319. X            fp = fopen(argv[i], "r");
  2320. X            if (!fp)
  2321. X            {
  2322. X                perror(argv[i]);
  2323. X                retcode = 1;
  2324. X            }
  2325. X            else
  2326. X            {
  2327. X                refont(fp);
  2328. X                if (i < argc - 1 && add_form_feed)
  2329. X                {
  2330. X                    putchar('\f');
  2331. X                }
  2332. X                fclose(fp);
  2333. X            }
  2334. X        }
  2335. X    }
  2336. X
  2337. X    exit(retcode);
  2338. X}
  2339. X
  2340. Xusage()
  2341. X{
  2342. X    fputs("usage: ", stderr);
  2343. X    fputs(progname, stderr);
  2344. X    fputs(" [-bcdefxFI] [filename]...\n", stderr);
  2345. X    exit(2);
  2346. X}
  2347. X
  2348. X/* This function does the refont thing to a single file */
  2349. X/* I apologize for the length of this function.  It is gross. */
  2350. Xrefont(fp)
  2351. X    FILE    *fp;
  2352. X{
  2353. X    char    textbuf[1025];    /* chars of a line of text */
  2354. X    char    fontbuf[1025];    /* fonts of chars in fontbuf */
  2355. X    int    col;        /* where we are in the line */
  2356. X    int    font;        /* remembered font */
  2357. X    int    more;        /* more characters to be output? */
  2358. X    int    ch;
  2359. X
  2360. X    /* reset some stuff */
  2361. X    for (col = sizeof fontbuf; --col >= 0; )
  2362. X    {
  2363. X        fontbuf[col] = 'R';
  2364. X        textbuf[col] = '\0';
  2365. X    }
  2366. X    col = 0;
  2367. X    font = 'R';
  2368. X
  2369. X    /* get the first char - quit if eof */
  2370. X    while ((ch = getc(fp)) != EOF)
  2371. X    {
  2372. X        /* if "dot" command, read the rest of the command */
  2373. X        if (infmt == 'I' && ch == '.' && col == 0)
  2374. X        {
  2375. X
  2376. X            textbuf[col++] = '.';
  2377. X            textbuf[col++] = getc(fp);
  2378. X            textbuf[col++] = getc(fp);
  2379. X            textbuf[col++] = ch = getc(fp);
  2380. X
  2381. X            /* is it a font line? */
  2382. X            font = 0;
  2383. X            if (textbuf[1] == 'u' && textbuf[2] == 'l')
  2384. X            {
  2385. X                font = 'U';
  2386. X            }
  2387. X            else if (textbuf[1] == 'b' && textbuf[2] == 'o')
  2388. X            {
  2389. X                font = 'B';
  2390. X            }
  2391. X            else if (textbuf[1] == 'i' && textbuf[2] == 't')
  2392. X            {
  2393. X                font = 'I';
  2394. X            }
  2395. X
  2396. X            /* if it is, discard the stuff so far but remember font */
  2397. X            if (font)
  2398. X            {
  2399. X                while (col > 0)
  2400. X                {
  2401. X                    textbuf[--col] = '\0';
  2402. X                }
  2403. X            }
  2404. X            else /* some other format line - write it literally */
  2405. X            {
  2406. X                while (ch != '\n')
  2407. X                {
  2408. X                    textbuf[col++] = ch = getc(fp);
  2409. X                }
  2410. X                fputs(textbuf, fp);
  2411. X                while (col > 0)
  2412. X                {
  2413. X                    textbuf[--col] = '\0';
  2414. X                }
  2415. X            }
  2416. X            continue;
  2417. X        }
  2418. X
  2419. X        /* is it a "\f" formatted font? */
  2420. X        if (infmt == 'I' && ch == '\\')
  2421. X        {
  2422. X            ch = getc(fp);
  2423. X            if (ch == 'f')
  2424. X            {
  2425. X                font = getc(fp);
  2426. X            }
  2427. X            else
  2428. X            {
  2429. X                textbuf[col++] = '\\';
  2430. X                textbuf[col++] = ch;
  2431. X            }
  2432. X            continue;
  2433. X        }
  2434. X
  2435. X        /* is it an Epson font? */
  2436. X        if (ch == '\033')
  2437. X        {
  2438. X            ch = getc(fp);
  2439. X            switch (ch)
  2440. X            {
  2441. X              case '4':
  2442. X                font = 'I';
  2443. X                break;
  2444. X
  2445. X              case 'E':
  2446. X              case 'G':
  2447. X                font = 'B';
  2448. X                break;
  2449. X
  2450. X              case '5':
  2451. X              case 'F':
  2452. X              case 'H':
  2453. X                font = 'R';
  2454. X                break;
  2455. X
  2456. X              case '-':
  2457. X                font = (getc(fp) & 1) ? 'U' : 'R';
  2458. X                break;
  2459. X            }
  2460. X            continue;
  2461. X        }
  2462. X
  2463. X        /* control characters? */
  2464. X        if (ch == '\b')
  2465. X        {
  2466. X            if (col > 0)
  2467. X                col--;
  2468. X            continue;
  2469. X        }
  2470. X        else if (ch == '\t')
  2471. X        {
  2472. X            do
  2473. X            {
  2474. X                if (textbuf[col] == '\0')
  2475. X                {
  2476. X                    textbuf[col] = ' ';
  2477. X                }
  2478. X                col++;
  2479. X            } while (col & 7);
  2480. X            continue;
  2481. X        }
  2482. X#if !OSK
  2483. X        else if (ch == '\r')
  2484. X        {
  2485. X            col = 0;
  2486. X            continue;
  2487. X        }
  2488. X#endif
  2489. X        else if (ch == ' ')
  2490. X        {
  2491. X            if (textbuf[col] == '\0')
  2492. X            {
  2493. X                textbuf[col] = ' ';
  2494. X                fontbuf[col] = font;
  2495. X                col++;
  2496. X            }
  2497. X            continue;
  2498. X        }
  2499. X
  2500. X        /* newline? */
  2501. X        if (ch == '\n')
  2502. X        {
  2503. X            more = 0;
  2504. X            for (col = 0, font = 'R'; textbuf[col]; col++)
  2505. X            {
  2506. X                if (fontbuf[col] != font)
  2507. X                {
  2508. X                    switch (outfmt)
  2509. X                    {
  2510. X                      case 'd':
  2511. X                        putchar('\n');
  2512. X                        switch (fontbuf[col])
  2513. X                        {
  2514. X                          case 'B':
  2515. X                            fputs(".bo\n", stdout);
  2516. X                            break;
  2517. X
  2518. X                          case 'I':
  2519. X                            fputs(".it\n", stdout);
  2520. X                            break;
  2521. X
  2522. X                          case 'U':
  2523. X                            fputs(".ul\n", stdout);
  2524. X                            break;
  2525. X                        }
  2526. X                        while (textbuf[col] == ' ')
  2527. X                        {
  2528. X                            col++;
  2529. X                        }
  2530. X                        break;
  2531. X
  2532. X                      case 'e':
  2533. X                        switch (fontbuf[col])
  2534. X                        {
  2535. X                          case 'B':
  2536. X                            fputs("\033E", stdout);
  2537. X                            break;
  2538. X
  2539. X                          case 'I':
  2540. X                            fputs("\0334", stdout);
  2541. X                            break;
  2542. X
  2543. X                          case 'U':
  2544. X                            fputs("\033-1", stdout);
  2545. X                            break;
  2546. X
  2547. X                          default:
  2548. X                            switch (font)
  2549. X                            {
  2550. X                              case 'B':
  2551. X                                fputs("\033F", stdout);
  2552. X                                break;
  2553. X
  2554. X                              case 'I':
  2555. X                                  fputs("\0335", stdout);
  2556. X                                  break;
  2557. X
  2558. X                              case 'U':
  2559. X                                  fputs("\033-0", stdout);
  2560. X                                  break;
  2561. X                            }
  2562. X                        }
  2563. X                        break;
  2564. X
  2565. X                      case 'f':
  2566. X                          putchar('\\');
  2567. X                          putchar('f');
  2568. X                          putchar(fontbuf[col]);
  2569. X                          break;
  2570. X                    }
  2571. X
  2572. X                    font = fontbuf[col];
  2573. X                }
  2574. X
  2575. X                if (fontbuf[col] != 'R' && textbuf[col] != ' ')
  2576. X                {
  2577. X                    switch (outfmt)
  2578. X                    {
  2579. X                      case 'b':
  2580. X                        if (fontbuf[col] == 'B')
  2581. X                        {
  2582. X                            putchar(textbuf[col]);
  2583. X                        }
  2584. X                        else
  2585. X                        {
  2586. X                            putchar('_');
  2587. X                        }
  2588. X                        putchar('\b');
  2589. X                        break;
  2590. X#if !OSK
  2591. X                      case 'c':
  2592. X                          more = col + 1;
  2593. X                          break;
  2594. X#endif
  2595. X                    }
  2596. X                }
  2597. X
  2598. X                putchar(textbuf[col]);
  2599. X            }
  2600. X
  2601. X#if !OSK
  2602. X            /* another pass? */
  2603. X            if (more > 0)
  2604. X            {
  2605. X                putchar('\r');
  2606. X                for (col = 0; col < more; col++)
  2607. X                {
  2608. X                    switch (fontbuf[col])
  2609. X                    {
  2610. X                      case 'I':
  2611. X                      case 'U':
  2612. X                        putchar('_');
  2613. X                        break;
  2614. X
  2615. X                      case 'B':
  2616. X                        putchar(textbuf[col]);
  2617. X                        break;
  2618. X
  2619. X                      default:
  2620. X                        putchar(' ');
  2621. X                    }
  2622. X                }
  2623. X            }
  2624. X#endif /* not OSK */
  2625. X
  2626. X            /* newline */
  2627. X            if (font != 'R')
  2628. X            {
  2629. X                switch (outfmt)
  2630. X                {
  2631. X                  case 'f':
  2632. X                    putchar('\\');
  2633. X                    putchar('f');
  2634. X                    putchar('R');
  2635. X                    break;
  2636. X
  2637. X                  case 'e':
  2638. X                    switch (font)
  2639. X                    {
  2640. X                      case 'B':
  2641. X                        fputs("\033F", stdout);
  2642. X                        break;
  2643. X
  2644. X                      case 'I':
  2645. X                          fputs("\0335", stdout);
  2646. X                          break;
  2647. X
  2648. X                      case 'U':
  2649. X                          fputs("\033-0", stdout);
  2650. X                          break;
  2651. X                    }
  2652. X                }
  2653. X            }
  2654. X            putchar('\n');
  2655. X
  2656. X            /* reset some stuff */
  2657. X            for (col = sizeof fontbuf; --col >= 0; )
  2658. X            {
  2659. X                fontbuf[col] = 'R';
  2660. X                textbuf[col] = '\0';
  2661. X            }
  2662. X            col = 0;
  2663. X            font = 'R';
  2664. X            continue;
  2665. X        }
  2666. X
  2667. X        /* normal character */
  2668. X        if (font != 'R')
  2669. X        {
  2670. X            textbuf[col] = ch;
  2671. X            fontbuf[col] = font;
  2672. X        }
  2673. X        else if (textbuf[col] == '_')
  2674. X        {
  2675. X            textbuf[col] = ch;
  2676. X            fontbuf[col] = 'U';
  2677. X        }
  2678. X        else if (textbuf[col] && textbuf[col] != ' ' && ch == '_')
  2679. X        {
  2680. X            fontbuf[col] = 'U';
  2681. X        }
  2682. X        else if (textbuf[col] == ch)
  2683. X        {
  2684. X            fontbuf[col] = 'B';
  2685. X        }
  2686. X        else
  2687. X        {
  2688. X            textbuf[col] = ch;
  2689. X        }
  2690. X        col++;
  2691. X    }
  2692. X}
  2693. eof
  2694. if test `wc -c <refont.c` -ne 7638
  2695. then
  2696. echo refont.c damaged!
  2697. fi
  2698. fi
  2699.  
  2700. exit 0
  2701. -------------------------------------------------------------------------------
  2702. Steve Kirkendall     kirkenda@cs.pdx.edu      Grad student at Portland State U.
  2703.