home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / xvi / part15 < prev    next >
Encoding:
Text File  |  1992-11-01  |  55.4 KB  |  2,500 lines

  1. Newsgroups: comp.sources.misc
  2. From: jmd@cyclone.bt.co.uk (John Downey)
  3. Subject:  v33i024:  xvi - portable multi-window vi-like editor, Part15/18
  4. Message-ID: <1992Oct24.172519.2379@sparky.imd.sterling.com>
  5. X-Md4-Signature: a49b6e529fd93a656d0342c3d5f2c022
  6. Date: Sat, 24 Oct 1992 17:25:19 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jmd@cyclone.bt.co.uk (John Downey)
  10. Posting-number: Volume 33, Issue 24
  11. Archive-name: xvi/part15
  12. Environment: Unix, MS-DOS, OS/2, QNX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  xvi/src/alloc.c xvi/src/defscr.c xvi/src/ex_cmds2.c
  19. #   xvi/src/flexbuf.c xvi/src/msdos_a.asm xvi/src/startup.c
  20. #   xvi/src/sunfront.c
  21. # Wrapped by kent@sparky on Thu Oct 22 09:03:44 1992
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 15 (of 18)."'
  25. if test -f 'xvi/src/alloc.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'xvi/src/alloc.c'\"
  27. else
  28.   echo shar: Extracting \"'xvi/src/alloc.c'\" \(6314 characters\)
  29.   sed "s/^X//" >'xvi/src/alloc.c' <<'END_OF_FILE'
  30. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  31. X#ifndef lint
  32. Xstatic char *sccsid = "@(#)alloc.c    2.1 (Chris & John Downey) 7/29/92";
  33. X#endif
  34. X
  35. X/***
  36. X
  37. X* program name:
  38. X    xvi
  39. X* function:
  40. X    PD version of UNIX "vi" editor, with extensions.
  41. X* module name:
  42. X    alloc.c
  43. X* module function:
  44. X    Various routines dealing with allocation
  45. X    and deallocation of data structures.
  46. X* history:
  47. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  48. X    Originally by Tim Thompson (twitch!tjt)
  49. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  50. X    Heavily modified by Chris & John Downey
  51. X
  52. X***/
  53. X
  54. X#include "xvi.h"
  55. X
  56. X/*
  57. X * We use a special strategy for the allocation & freeing of Change
  58. X * structures to make these operations as fast as possible (since we
  59. X * have to allocate one for each input character in INSERT & REPLACE
  60. X * states).
  61. X *
  62. X * So we have a linked list of reusable Change structures; freeing a
  63. X * Change means just adding it to this list.
  64. X */
  65. Xstatic Change    *chlist = NULL;
  66. X
  67. X/*
  68. X * Free a Change structure. This just means adding it to our list of
  69. X * reusable structures, so a later request for an allocation of a
  70. X * Change can be satisfied very quickly from the front of the list.
  71. X */
  72. Xvoid
  73. Xchfree(ch)
  74. X    Change *ch;
  75. X{
  76. X    ch->c_next = chlist;
  77. X    chlist = ch;
  78. X}
  79. X
  80. XChange *
  81. Xchalloc()
  82. X{
  83. X    if (chlist) {
  84. X    Change    *ch;
  85. X
  86. X    ch = chlist;
  87. X    chlist = chlist->c_next;
  88. X    return ch;
  89. X    }
  90. X    return (Change *) alloc(sizeof (Change));
  91. X}
  92. X
  93. X/*
  94. X * We also use a similar strategy for Line structures.
  95. X */
  96. Xstatic Line    *lnlist = NULL;
  97. X
  98. Xchar *
  99. Xalloc(size)
  100. Xunsigned size;
  101. X{
  102. X    char *p;        /* pointer to new storage space */
  103. X
  104. X    while ((p = malloc(size)) == NULL) {
  105. X    /*
  106. X     * No more memory in the heap, but we may be able to
  107. X     * satisfy the request by recycling entries in one of
  108. X     * our lists of reusable structures.
  109. X     */
  110. X    if (lnlist) {
  111. X        p = (char *) lnlist;
  112. X        lnlist = lnlist->l_next;
  113. X        free(p);
  114. X    } else if (chlist) {
  115. X        p = (char *) chlist;
  116. X        chlist = chlist->c_next;
  117. X        free(p);
  118. X    } else {
  119. X        /*
  120. X         * No: we're out.
  121. X         */
  122. X        show_error(curwin, "Not enough memory!");
  123. X        break;
  124. X    }
  125. X    }
  126. X    return(p);
  127. X}
  128. X
  129. Xchar *
  130. Xstrsave(string)
  131. Xconst char *string;
  132. X{
  133. X    char    *space;
  134. X
  135. X    space = alloc((unsigned) strlen(string) + 1);
  136. X    if (space != NULL)
  137. X    (void) strcpy(space, string);
  138. X    return(space);
  139. X}
  140. X
  141. X/*
  142. X * Allocate and initialize a new line structure with room for
  143. X * 'nchars' characters.
  144. X */
  145. XLine *
  146. Xnewline(nchars)
  147. Xint    nchars;
  148. X{
  149. X    register Line    *l;
  150. X    char        *ltp;
  151. X
  152. X    if (lnlist == NULL) {
  153. X    register unsigned n;
  154. X
  155. X    /*
  156. X     * To avoid memory fragmentation, we try to allocate a
  157. X     * contiguous block of 100 Line structures if we
  158. X     * haven't already got any.
  159. X     *
  160. X     * This means that, for every 100 lines of a file we
  161. X     * read in, there should be a block of Line
  162. X     * structures, which may never be freed, followed by
  163. X     * a large arena for the lines' text and other sundry
  164. X     * dynamically allocated objects, which generally will
  165. X     * be.
  166. X     *
  167. X     * If we can't even get one structure, alloc() should
  168. X     * print an error message. For subsequent ones, we use
  169. X     * malloc() instead because it isn't necessarily a
  170. X     * serious error if we can't get any more space than
  171. X     * we've actually been asked for.
  172. X     */
  173. X    if ((lnlist = (Line *) alloc(sizeof(Line))) == NULL) {
  174. X        return(NULL);
  175. X    }
  176. X    lnlist->l_next = NULL;
  177. X    for (n = 99; n != 0; n--) {
  178. X        if ((l = (Line *) malloc(sizeof(Line))) == NULL) {
  179. X        break;
  180. X        }
  181. X        l->l_next = lnlist;
  182. X        lnlist = l;
  183. X    }
  184. X    }
  185. X
  186. X    /*
  187. X     * Assertion: lnlist != NULL.
  188. X     */
  189. X    l = lnlist;
  190. X    lnlist = l->l_next;
  191. X
  192. X    /*
  193. X     * It is okay for newline() to be called with a 0
  194. X     * parameter - but we must never call malloc(0) as
  195. X     * this will break on many systems.
  196. X     */
  197. X    if (nchars == 0)
  198. X    nchars = 1;
  199. X    ltp = alloc((unsigned) nchars);
  200. X    if (ltp == NULL) {
  201. X    free((char *) l);
  202. X    return(NULL);
  203. X    }
  204. X    ltp[0] = '\0';
  205. X    l->l_text = ltp;
  206. X    l->l_size = nchars;
  207. X    l->l_prev = NULL;
  208. X    l->l_next = NULL;
  209. X
  210. X    return(l);
  211. X}
  212. X
  213. X/*
  214. X * bufempty() - return TRUE if the buffer is empty
  215. X */
  216. Xbool_t
  217. Xbufempty(b)
  218. XBuffer    *b;
  219. X{
  220. X    return(buf1line(b) && b->b_file->l_text[0] == '\0');
  221. X}
  222. X
  223. X/*
  224. X * buf1line() - return TRUE if there is only one line
  225. X */
  226. Xbool_t
  227. Xbuf1line(b)
  228. XBuffer    *b;
  229. X{
  230. X    return(b->b_file->l_next == b->b_lastline);
  231. X}
  232. X
  233. X/*
  234. X * endofline() - return TRUE if the given position is at end of line
  235. X *
  236. X * This routine will probably never be called with a position resting
  237. X * on the zero byte, but handle it correctly in case it happens.
  238. X */
  239. Xbool_t
  240. Xendofline(p)
  241. XPosn    *p;
  242. X{
  243. X    register char    *endtext = p->p_line->l_text + p->p_index;
  244. X
  245. X    return(*endtext == '\0' || *(endtext + 1) == '\0');
  246. X}
  247. X
  248. X/*
  249. X * grow_line(lp, n)
  250. X *    - increase the size of the space allocated for the line by n bytes.
  251. X *
  252. X * This routine returns TRUE immediately if the requested space is available.
  253. X * If not, it attempts to allocate the space and adjust the data structures
  254. X * accordingly, and returns TRUE if this worked.
  255. X * If everything fails it returns FALSE.
  256. X */
  257. Xbool_t
  258. Xgrow_line(lp, n)
  259. XLine    *lp;
  260. Xregister int    n;
  261. X{
  262. X    register int    nsize;
  263. X    register char    *s;        /* pointer to new space */
  264. X
  265. X    nsize = strlen(lp->l_text) + 1 + n;    /* size required */
  266. X
  267. X    if (nsize <= lp->l_size)
  268. X    return(TRUE);
  269. X
  270. X    /*
  271. X     * Need to allocate more space for the string. Allow some extra
  272. X     * space on the assumption that we may need it soon. This avoids
  273. X     * excessive numbers of calls to malloc while entering new text.
  274. X     */
  275. X    s = alloc((unsigned) nsize + SLOP);
  276. X    if (s == NULL) {
  277. X    return(FALSE);
  278. X    }
  279. X
  280. X    lp->l_size = nsize + SLOP;
  281. X    (void) strcpy(s, lp->l_text);
  282. X    free(lp->l_text);
  283. X    lp->l_text = s;
  284. X
  285. X    return(TRUE);
  286. X}
  287. X
  288. X/*
  289. X * Free up space used by the given list of lines.
  290. X *
  291. X * Note that the Line structures themselves are just added to the list
  292. X * of reusable ones.
  293. X */
  294. Xvoid
  295. Xthrow(lineptr)
  296. XLine    *lineptr;
  297. X{
  298. X    if (lineptr != NULL) {
  299. X    Line    *newlist;
  300. X
  301. X    newlist = lineptr;
  302. X    for (;;) {
  303. X        Line    *nextline;
  304. X
  305. X        if (lineptr->l_text != NULL)
  306. X        free(lineptr->l_text);
  307. X        if ((nextline = lineptr->l_next) == NULL) {
  308. X        /*
  309. X         * We've reached the end of this list;
  310. X         * join it on to lnlist ...
  311. X         */
  312. X        lineptr->l_next = lnlist;
  313. X        /*
  314. X         * ... & point lnlist at the beginning
  315. X         * of this list.
  316. X         */
  317. X        lnlist = newlist;
  318. X        return;
  319. X        } else {
  320. X        lineptr = nextline;
  321. X        }
  322. X    }
  323. X    }
  324. X}
  325. END_OF_FILE
  326.   if test 6314 -ne `wc -c <'xvi/src/alloc.c'`; then
  327.     echo shar: \"'xvi/src/alloc.c'\" unpacked with wrong size!
  328.   fi
  329.   # end of 'xvi/src/alloc.c'
  330. fi
  331. if test -f 'xvi/src/defscr.c' -a "${1}" != "-c" ; then 
  332.   echo shar: Will not clobber existing file \"'xvi/src/defscr.c'\"
  333. else
  334.   echo shar: Extracting \"'xvi/src/defscr.c'\" \(5901 characters\)
  335.   sed "s/^X//" >'xvi/src/defscr.c' <<'END_OF_FILE'
  336. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  337. X#ifndef lint
  338. Xstatic char *sccsid = "@(#)defscr.c    2.4 (Chris & John Downey) 9/4/92";
  339. X#endif
  340. X
  341. X/***
  342. X
  343. X* program name:
  344. X    xvi
  345. X* function:
  346. X    PD version of UNIX "vi" editor, with extensions.
  347. X* module name:
  348. X    defscr.c
  349. X* module function:
  350. X    VirtScr interface using old style porting functions.
  351. X    We assume newscr() is only called once; it is an
  352. X    error for it to be called more than once.
  353. X* history:
  354. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  355. X    Originally by Tim Thompson (twitch!tjt)
  356. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  357. X    Heavily modified by Chris & John Downey
  358. X
  359. X***/
  360. X
  361. X#include "xvi.h"
  362. X
  363. Xstatic    VirtScr    *newscr P((VirtScr *));
  364. Xstatic    void    closescr P((VirtScr *));
  365. Xstatic    int    getrows P((VirtScr *));
  366. Xstatic    int    getcols P((VirtScr *));
  367. Xstatic    void    clear_all P((VirtScr *));
  368. Xstatic    void    clear_line P((VirtScr *, int, int));
  369. Xstatic    void    xygoto P((VirtScr *, int, int));
  370. Xstatic    void    xyadvise P((VirtScr *, int, int, int, char *));
  371. Xstatic    void    put_char P((VirtScr *, int, int, int));
  372. Xstatic    void    put_str P((VirtScr *, int, int, char *));
  373. Xstatic    void    ins_str P((VirtScr *, int, int, char *));
  374. Xstatic    void    pset_colour P((VirtScr *, int));
  375. Xstatic    int    colour_cost P((VirtScr *));
  376. Xstatic    int    scroll P((VirtScr *, int, int, int));
  377. Xstatic    void    flushout P((VirtScr *));
  378. Xstatic    void    pbeep P((VirtScr *));
  379. X
  380. XVirtScr    defscr = {
  381. X    NULL,        /* pv_window        */
  382. X    0,            /* pv_rows        */
  383. X    0,            /* pv_cols        */
  384. X
  385. X    newscr,        /* v_new        */
  386. X    closescr,        /* v_close        */
  387. X    getrows,        /* v_rows        */
  388. X    getcols,        /* v_cols        */
  389. X    clear_all,        /* v_clear_all        */
  390. X    clear_line,        /* v_clear_line        */
  391. X    xygoto,        /* v_goto        */
  392. X    xyadvise,        /* v_advise        */
  393. X    put_str,        /* v_write        */
  394. X    put_char,        /* v_putc        */
  395. X    pset_colour,    /* v_set_colour        */
  396. X    colour_cost,    /* v_colour_cost    */
  397. X    flushout,        /* v_flush        */
  398. X    pbeep,        /* v_beep        */
  399. X
  400. X    ins_str,        /* v_insert        */
  401. X    scroll,        /* v_scroll        */
  402. X    NULL,        /* v_flash        */
  403. X    NULL,        /* v_status        */
  404. X    NULL,        /* v_activate        */
  405. X};
  406. X
  407. Xint
  408. Xmain(argc, argv)
  409. Xint    argc;
  410. Xchar    *argv[];
  411. X{
  412. X    xvEvent    event;
  413. X    long    timeout = 0;
  414. X
  415. X    /*
  416. X     * Set up the system and terminal interfaces. This establishes
  417. X     * the window size, changes to raw mode and does whatever else
  418. X     * is needed for the system we're running on.
  419. X     */
  420. X    sys_init();
  421. X
  422. X    if (!can_inschar) {
  423. X    defscr.v_insert = NULL;
  424. X    }
  425. X    if (!can_scroll_area && !can_ins_line && !can_del_line) {
  426. X    defscr.v_scroll = NULL;
  427. X    }
  428. X    defscr.pv_rows = Rows;
  429. X    defscr.pv_cols = Columns;
  430. X
  431. X    defscr.pv_window = (genptr *) xvi_startup(&defscr, argc, argv,
  432. X                            getenv("XVINIT"));
  433. X
  434. X    while (1) {
  435. X    register int    r;
  436. X
  437. X    r = inchar(timeout);
  438. X    if (r == EOF) {
  439. X        event.ev_type = Ev_timeout;
  440. X    } else {
  441. X        event.ev_type = Ev_char;
  442. X        event.ev_inchar = r;
  443. X    }
  444. X    timeout = xvi_handle_event(&event);
  445. X    }
  446. X}
  447. X
  448. X/*ARGSUSED*/
  449. Xstatic VirtScr *
  450. Xnewscr(scr)
  451. XVirtScr    *scr;
  452. X{
  453. X    return(NULL);
  454. X}
  455. X
  456. X/*ARGSUSED*/
  457. Xstatic void
  458. Xclosescr(scr)
  459. XVirtScr    *scr;
  460. X{
  461. X}
  462. X
  463. X/*ARGSUSED*/
  464. Xstatic int
  465. Xgetrows(scr)
  466. XVirtScr    *scr;
  467. X{
  468. X    return(scr->pv_rows);
  469. X}
  470. X
  471. X/*ARGSUSED*/
  472. Xstatic int
  473. Xgetcols(scr)
  474. XVirtScr    *scr;
  475. X{
  476. X    return(scr->pv_cols);
  477. X}
  478. X
  479. X/*ARGSUSED*/
  480. Xstatic void
  481. Xclear_all(scr)
  482. XVirtScr    *scr;
  483. X{
  484. X    erase_display();
  485. X}
  486. X
  487. X/*ARGSUSED*/
  488. Xstatic void
  489. Xclear_line(scr, row, col)
  490. XVirtScr    *scr;
  491. Xint    row;
  492. Xint    col;
  493. X{
  494. X    tty_goto(row, col);
  495. X    erase_line();
  496. X}
  497. X
  498. X/*ARGSUSED*/
  499. Xstatic void
  500. Xxygoto(scr, row, col)
  501. XVirtScr    *scr;
  502. Xint    row;
  503. Xint    col;
  504. X{
  505. X    tty_goto(row, col);
  506. X}
  507. X
  508. X/*ARGSUSED*/
  509. Xstatic void
  510. Xxyadvise(scr, row, col, index, str)
  511. XVirtScr    *scr;
  512. Xint    row;
  513. Xint    col;
  514. Xint    index;
  515. Xchar    *str;
  516. X{
  517. X    if (index > cost_goto) {
  518. X    tty_goto(row, col + index);
  519. X    } else {
  520. X    tty_goto(row, col);
  521. X    while (--index > 0) {
  522. X        outchar(*str++);
  523. X    }
  524. X    }
  525. X}
  526. X
  527. X/*ARGSUSED*/
  528. Xstatic void
  529. Xput_str(scr, row, col, str)
  530. XVirtScr    *scr;
  531. Xint    row;
  532. Xint    col;
  533. Xchar    *str;
  534. X{
  535. X    tty_goto(row, col);
  536. X    outstr(str);
  537. X}
  538. X
  539. X/*ARGSUSED*/
  540. Xstatic void
  541. Xput_char(scr, row, col, c)
  542. XVirtScr    *scr;
  543. Xint    row;
  544. Xint    col;
  545. Xint    c;
  546. X{
  547. X    tty_goto(row, col);
  548. X    outchar(c);
  549. X}
  550. X
  551. X/*ARGSUSED*/
  552. Xstatic void
  553. Xins_str(scr, row, col, str)
  554. XVirtScr    *scr;
  555. Xint    row;
  556. Xint    col;
  557. Xchar    *str;
  558. X{
  559. X    /*
  560. X     * If we are called, can_inschar is TRUE,
  561. X     * so we know it is safe to use inschar().
  562. X     */
  563. X    tty_goto(row, col);
  564. X    for ( ; *str != '\0'; str++) {
  565. X    inschar(*str);
  566. X    }
  567. X}
  568. X
  569. X/*ARGSUSED*/
  570. Xstatic void
  571. Xpset_colour(scr, colour)
  572. XVirtScr    *scr;
  573. Xint    colour;
  574. X{
  575. X    set_colour(colour);
  576. X}
  577. X
  578. X/*ARGSUSED*/
  579. Xstatic int
  580. Xcolour_cost(scr)
  581. XVirtScr    *scr;
  582. X{
  583. X#ifdef    SLINE_GLITCH
  584. X    return(SLINE_GLITCH);
  585. X#else
  586. X    return(0);
  587. X#endif
  588. X}
  589. X
  590. X/*ARGSUSED*/
  591. Xstatic int
  592. Xscroll(scr, start_row, end_row, nlines)
  593. XVirtScr    *scr;
  594. Xint    start_row;
  595. Xint    end_row;
  596. Xint    nlines;
  597. X{
  598. X    if (nlines < 0) {
  599. X    /*
  600. X     * nlines negative means scroll reverse - i.e. move
  601. X     * the text downwards with respect to the terminal.
  602. X     */
  603. X    nlines = -nlines;
  604. X
  605. X    if (can_scroll_area) {
  606. X        scroll_down(start_row, end_row, nlines);
  607. X    } else if (can_ins_line && end_row == Rows - 1) {
  608. X        int    line;
  609. X
  610. X        for (line = 0; line < nlines; line++) {
  611. X        tty_goto(start_row, 0);
  612. X        insert_line();
  613. X        }
  614. X    } else {
  615. X        return(0);
  616. X    }
  617. X    } else if (nlines > 0) {
  618. X    /*
  619. X     * Whereas nlines positive is "normal" scrolling.
  620. X     */
  621. X    if (can_scroll_area) {
  622. X        scroll_up(start_row, end_row, nlines);
  623. X    } else if (end_row == Rows - 1) {
  624. X        int    line;
  625. X
  626. X        if (can_del_line) {
  627. X        for (line = 0; line < nlines; line++) {
  628. X            tty_goto(start_row, 0);
  629. X            delete_line();
  630. X        }
  631. X        } else if (start_row == 0) {
  632. X        tty_goto(start_row, 0);
  633. X        for (line = 0; line < nlines; line++) {
  634. X            delete_line();
  635. X        }
  636. X        } else {
  637. X        return(0);
  638. X        }
  639. X    } else {
  640. X        return(0);
  641. X    }
  642. X    }
  643. X    return(1);
  644. X}
  645. X
  646. X/*ARGSUSED*/
  647. Xstatic void
  648. Xflushout(scr)
  649. XVirtScr    *scr;
  650. X{
  651. X    flush_output();
  652. X}
  653. X
  654. X/*ARGSUSED*/
  655. Xstatic void
  656. Xpbeep(scr)
  657. XVirtScr    *scr;
  658. X{
  659. X    alert();
  660. X    flush_output();
  661. X}
  662. END_OF_FILE
  663.   if test 5901 -ne `wc -c <'xvi/src/defscr.c'`; then
  664.     echo shar: \"'xvi/src/defscr.c'\" unpacked with wrong size!
  665.   fi
  666.   # end of 'xvi/src/defscr.c'
  667. fi
  668. if test -f 'xvi/src/ex_cmds2.c' -a "${1}" != "-c" ; then 
  669.   echo shar: Will not clobber existing file \"'xvi/src/ex_cmds2.c'\"
  670. else
  671.   echo shar: Extracting \"'xvi/src/ex_cmds2.c'\" \(7175 characters\)
  672.   sed "s/^X//" >'xvi/src/ex_cmds2.c' <<'END_OF_FILE'
  673. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  674. X#ifndef lint
  675. Xstatic char *sccsid = "@(#)ex_cmds2.c    2.2 (Chris & John Downey) 8/3/92";
  676. X#endif
  677. X
  678. X/***
  679. X
  680. X* program name:
  681. X    xvi
  682. X* function:
  683. X    PD version of UNIX "vi" editor, with extensions.
  684. X* module name:
  685. X    ex_cmds2.c
  686. X* module function:
  687. X    Command functions for miscellaneous ex (colon) commands.
  688. X    See ex_cmds1.c for file- and buffer-related colon commands.
  689. X* history:
  690. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  691. X    Originally by Tim Thompson (twitch!tjt)
  692. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  693. X    Heavily modified by Chris & John Downey
  694. X
  695. X***/
  696. X
  697. X#include "xvi.h"
  698. X
  699. X#ifdef    MEGAMAX
  700. Xoverlay "ex_cmds2"
  701. X#endif
  702. X
  703. X/*
  704. X * Run shell command.
  705. X *
  706. X * You might think it would be easier to do this as
  707. X *
  708. X *    sys_endv();
  709. X *    system(command);
  710. X *    sys_startv();
  711. X *    prompt("[Hit return to continue] ");
  712. X *    ...
  713. X *
  714. X * but the trouble is that, with some systems, sys_startv() can be
  715. X * used to swap display pages, which would mean that the user would
  716. X * never have time to see the output from the command. (This applies
  717. X * to some terminals, as well as machines with memory-mappped video;
  718. X * cmdtool windows on Sun workstations also do the same thing.)
  719. X *
  720. X * This means we have to display the prompt before calling
  721. X * sys_startv(), so we just use good old fputs(). (We're trying not to
  722. X * use printf()).
  723. X */
  724. X/*ARGSUSED*/
  725. Xvoid
  726. Xdo_shcmd(window, command)
  727. XXviwin    *window;
  728. Xchar    *command;
  729. X{
  730. X    int    c;
  731. X
  732. X    sys_endv();
  733. X
  734. X    (void) fputs(command, stdout);
  735. X    (void) fputs("\r\n", stdout);
  736. X    (void) fflush(stdout);
  737. X    (void) call_system(command);
  738. X    (void) fputs("[Hit return to continue] ", stdout);
  739. X    (void) fflush(stdout);
  740. X    while ((c = getc(stdin)) != '\n' && c != '\r' && c != EOF)
  741. X    ;
  742. X
  743. X    sys_startv();
  744. X    redraw_screen();
  745. X}
  746. X
  747. Xvoid
  748. Xdo_shell(window)
  749. XXviwin    *window;
  750. X{
  751. X    char    *sh = NULL;
  752. X    int    sysret;
  753. X
  754. X    sh = Ps(P_shell);
  755. X    if (sh == NULL) {
  756. X    show_error(window, "SHELL variable not set");
  757. X    return;
  758. X    }
  759. X
  760. X    sys_endv();
  761. X
  762. X    sysret = call_shell(sh);
  763. X
  764. X    sys_startv();
  765. X    redraw_screen();
  766. X
  767. X    if (sysret != 0) {
  768. X#ifdef STRERROR_AVAIL
  769. X    show_error(window, "Can't execute %s [%s]", sh,
  770. X            (errno > 0 ? strerror(errno) : "Unknown Error"));
  771. X#else    /* strerror() not available */
  772. X    show_error(window, "Can't execute %s", sh);
  773. X#endif    /* strerror() not available */
  774. X    }
  775. X}
  776. X
  777. X/*ARGSUSED*/
  778. Xvoid
  779. Xdo_suspend(window)
  780. XXviwin    *window;
  781. X{
  782. X    if (State == NORMAL) {
  783. X#    ifdef    SIGSTOP
  784. X    extern    int    kill P((int, int));
  785. X    extern    int    getpid P((void));
  786. X
  787. X    sys_endv();
  788. X
  789. X    (void) kill(getpid(), SIGSTOP);
  790. X
  791. X    sys_startv();
  792. X    redraw_screen();
  793. X
  794. X#    else /* SIGSTOP */
  795. X
  796. X    /*
  797. X     * Can't suspend unless we're on a BSD UNIX system;
  798. X     * just pretend by invoking a shell instead.
  799. X     */
  800. X    do_shell(window);
  801. X
  802. X#    endif /* SIGSTOP */
  803. X    }
  804. X}
  805. X
  806. Xvoid
  807. Xdo_equals(window, line)
  808. XXviwin    *window;
  809. XLine    *line;
  810. X{
  811. X    if (line == NULL) {
  812. X    /*
  813. X     * Default position is ".".
  814. X     */
  815. X    line = window->w_cursor->p_line;
  816. X    }
  817. X
  818. X    show_message(window, "Line %ld", lineno(window->w_buffer, line));
  819. X}
  820. X
  821. Xvoid
  822. Xdo_help(window)
  823. XXviwin    *window;
  824. X{
  825. X    unsigned    savecho;
  826. X
  827. X    savecho = echo;
  828. X    echo &= ~(e_SCROLL | e_REPORT | e_SHOWINFO);
  829. X    if (Ps(P_helpfile) != NULL && do_buffer(window, Ps(P_helpfile))) {
  830. X    /*
  831. X     * We use "curbuf" here because the new buffer will
  832. X     * have been made the current one by do_buffer().
  833. X     */
  834. X    curbuf->b_flags |= FL_READONLY | FL_NOEDIT;
  835. X    move_window_to_cursor(curwin);
  836. X    show_file_info(curwin);
  837. X    update_window(curwin);
  838. X    }
  839. X    echo = savecho;
  840. X}
  841. X
  842. Xbool_t
  843. Xdo_source(interactive, file)
  844. Xbool_t    interactive;
  845. Xchar    *file;
  846. X{
  847. X    static char        cmdbuf[256];
  848. X    FILE        *fp;
  849. X    register int    c;
  850. X    register char    *bufp;
  851. X    bool_t        literal;
  852. X
  853. X    fp = fopen(file, "r");
  854. X    if (fp == NULL) {
  855. X    if (interactive) {
  856. X        show_error(curwin, "Can't open \"%s\"", file);
  857. X    }
  858. X    return(FALSE);
  859. X    }
  860. X
  861. X    bufp = cmdbuf;
  862. X    literal = FALSE;
  863. X    while ((c = getc(fp)) != EOF) {
  864. X    if (!literal && (c == CTRL('V') || c == '\n')) {
  865. X        switch (c) {
  866. X        case CTRL('V'):
  867. X        literal = TRUE;
  868. X        break;
  869. X
  870. X        case '\n':
  871. X        if (kbdintr) {
  872. X            imessage = TRUE;
  873. X            break;
  874. X        }
  875. X        if (bufp > cmdbuf) {
  876. X            *bufp = '\0';
  877. X            do_colon(cmdbuf, FALSE);
  878. X        }
  879. X        bufp = cmdbuf;
  880. X        break;
  881. X        }
  882. X    } else {
  883. X        literal = FALSE;
  884. X        if (bufp < &cmdbuf[sizeof(cmdbuf) - 1]) {
  885. X        *bufp++ = c;
  886. X        }
  887. X    }
  888. X    }
  889. X    (void) fclose(fp);
  890. X    return(TRUE);
  891. X}
  892. X
  893. X/*
  894. X * Change directory.
  895. X *
  896. X * With a NULL argument, change to the directory given by the HOME
  897. X * environment variable if it is defined; with an argument of "-",
  898. X * change back to the previous directory (like ksh).
  899. X *
  900. X * Return NULL pointer if OK, otherwise error message to say
  901. X * what went wrong.
  902. X */
  903. Xchar *
  904. Xdo_chdir(dir)
  905. X    char    *dir;
  906. X{
  907. X    static char    *homedir = NULL;
  908. X    static char    *prevdir = NULL;
  909. X    char    *ret;
  910. X    char    *curdir;
  911. X
  912. X    if (dir == NULL && homedir == NULL &&
  913. X                    (homedir = getenv("HOME")) == NULL) {
  914. X    return("HOME environment variable not set");
  915. X    }
  916. X
  917. X    if (dir == NULL) {
  918. X    dir = homedir;
  919. X    } else if (*dir == '-' && dir[1] == '\0') {
  920. X    if (prevdir == NULL) {
  921. X        return("No previous directory");
  922. X    } else {
  923. X        dir = prevdir;
  924. X    }
  925. X    }
  926. X
  927. X    curdir = malloc(MAXPATHLEN + 2);
  928. X    if (curdir != NULL && getcwd(curdir, MAXPATHLEN + 2) == NULL) {
  929. X    free(curdir);
  930. X    curdir = NULL;
  931. X    }
  932. X    ret = (chdir(dir) == 0 ? NULL : "Invalid directory");
  933. X    if (prevdir) {
  934. X    free(prevdir);
  935. X    prevdir = NULL;
  936. X    }
  937. X    if (curdir) {
  938. X    prevdir = realloc(curdir, (unsigned) strlen(curdir) + 1);
  939. X    }
  940. X    return(ret);
  941. X}
  942. X
  943. Xvoid
  944. Xdo_cdmy(type, l1, l2, destline)
  945. Xint    type;            /* one of [cdmy] */
  946. XLine    *l1, *l2;        /* start and end (inclusive) of range */
  947. XLine    *destline;        /* destination line for copy/move */
  948. X{
  949. X    Posn    p1, p2;
  950. X    Posn    destpos;
  951. X
  952. X    p1.p_line = (l1 != NULL) ? l1 : curwin->w_cursor->p_line;
  953. X    p2.p_line = (l2 != NULL) ? l2 : p1.p_line;
  954. X    p1.p_index = p2.p_index = 0;
  955. X
  956. X    if (type == 'c' || type == 'm') {
  957. X    if (destline == NULL) {
  958. X        show_error(curwin, "No destination specified");
  959. X        return;
  960. X    }
  961. X    }
  962. X
  963. X    /*
  964. X     * Check that the destination is not inside
  965. X     * the source range for "move" operations.
  966. X     */
  967. X    if (type == 'm') {
  968. X    unsigned long    destlineno;
  969. X
  970. X    destlineno = lineno(curbuf, destline);
  971. X    if (destlineno >= lineno(curbuf, p1.p_line) &&
  972. X                destlineno <= lineno(curbuf, p2.p_line)) {
  973. X        show_error(curwin, "Source conflicts with destination of move");
  974. X        return;
  975. X    }
  976. X    }
  977. X
  978. X    /*
  979. X     * Yank the text to be copied.
  980. X     */
  981. X    if (do_yank(curbuf, &p1, &p2, FALSE, '@') == FALSE) {
  982. X    show_error(curwin, "Not enough memory to yank text");
  983. X    return;
  984. X    }
  985. X
  986. X    if (!start_command(curwin)) {
  987. X    return;
  988. X    }
  989. X
  990. X    switch (type) {
  991. X    case 'd':            /* delete */
  992. X    case 'm':            /* move */
  993. X    move_cursor(curwin, p1.p_line, 0);
  994. X    repllines(curwin, p1.p_line, cntllines(p1.p_line, p2.p_line),
  995. X                        (Line *) NULL);
  996. X    update_buffer(curbuf);
  997. X    cursupdate(curwin);
  998. X    begin_line(curwin, TRUE);
  999. X    }
  1000. X
  1001. X    switch (type) {
  1002. X    case 'c':            /* copy */
  1003. X    case 'm':            /* move */
  1004. X    /*
  1005. X     * And put it back at the destination point.
  1006. X     */
  1007. X    destpos.p_line = destline;
  1008. X    destpos.p_index = 0;
  1009. X    do_put(curwin, &destpos, FORWARD, '@');
  1010. X
  1011. X    update_buffer(curbuf);
  1012. X    cursupdate(curwin);
  1013. X    }
  1014. X
  1015. X    end_command(curwin);
  1016. X}
  1017. END_OF_FILE
  1018.   if test 7175 -ne `wc -c <'xvi/src/ex_cmds2.c'`; then
  1019.     echo shar: \"'xvi/src/ex_cmds2.c'\" unpacked with wrong size!
  1020.   fi
  1021.   # end of 'xvi/src/ex_cmds2.c'
  1022. fi
  1023. if test -f 'xvi/src/flexbuf.c' -a "${1}" != "-c" ; then 
  1024.   echo shar: Will not clobber existing file \"'xvi/src/flexbuf.c'\"
  1025. else
  1026.   echo shar: Extracting \"'xvi/src/flexbuf.c'\" \(7093 characters\)
  1027.   sed "s/^X//" >'xvi/src/flexbuf.c' <<'END_OF_FILE'
  1028. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1029. X#ifndef lint
  1030. Xstatic char *sccsid = "@(#)flexbuf.c    2.2 (Chris & John Downey) 8/27/92";
  1031. X#endif
  1032. X
  1033. X/***
  1034. X
  1035. X* program name:
  1036. X    xvi
  1037. X* function:
  1038. X    PD version of UNIX "vi" editor, with extensions.
  1039. X* module name:
  1040. X    flexbuf.c
  1041. X* module function:
  1042. X    Routines for Flexbufs (variable-length FIFO queues).
  1043. X
  1044. X    Some of the access routines are implemented as macros in xvi.h.
  1045. X* history:
  1046. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1047. X    Originally by Tim Thompson (twitch!tjt)
  1048. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1049. X    Heavily modified by Chris & John Downey
  1050. X
  1051. X***/
  1052. X
  1053. X#include "xvi.h"
  1054. X
  1055. X#define FLEXEXTRA    64
  1056. X
  1057. X/*
  1058. X * Append a single character to a Flexbuf. Return FALSE if we've run
  1059. X * out of space.
  1060. X *
  1061. X * Note that the f->fxb_chars array is not necessarily null-terminated.
  1062. X */
  1063. Xbool_t
  1064. Xflexaddch(f, ch)
  1065. Xregister Flexbuf    *f;
  1066. Xint    ch;
  1067. X{
  1068. X    if (flexempty(f))
  1069. X    f->fxb_rcnt = f->fxb_wcnt = 0;
  1070. X    if (f->fxb_wcnt >= f->fxb_max) {
  1071. X    if (f->fxb_max == 0) {
  1072. X        if ((f->fxb_chars = alloc(FLEXEXTRA)) == NULL) {
  1073. X        return FALSE;
  1074. X        } else {
  1075. X        f->fxb_max = FLEXEXTRA;
  1076. X        }
  1077. X    } else {
  1078. X        unsigned newsize = f->fxb_wcnt + FLEXEXTRA;
  1079. X
  1080. X        if ((f->fxb_chars = realloc(f->fxb_chars, newsize)) == NULL) {
  1081. X        f->fxb_wcnt = f->fxb_max = 0;
  1082. X        return FALSE;
  1083. X        } else {
  1084. X        f->fxb_max = newsize;
  1085. X        }
  1086. X    }
  1087. X    }
  1088. X    f->fxb_chars[f->fxb_wcnt++] = ch;
  1089. X    return TRUE;
  1090. X}
  1091. X
  1092. X/*
  1093. X * Return contents of a Flexbuf as a null-terminated string.
  1094. X */
  1095. Xchar *
  1096. Xflexgetstr(f)
  1097. XFlexbuf    *f;
  1098. X{
  1099. X    if (!flexempty(f) && flexaddch(f, '\0')) {
  1100. X    --f->fxb_wcnt;
  1101. X    return &f->fxb_chars[f->fxb_rcnt];
  1102. X    } else {
  1103. X    return "";
  1104. X    }
  1105. X}
  1106. X
  1107. X/*
  1108. X * Remove the first character from a Flexbuf and return it.
  1109. X */
  1110. Xint
  1111. Xflexpopch(f)
  1112. XFlexbuf    *f;
  1113. X{
  1114. X    return flexempty(f) ?
  1115. X    0 : (unsigned char) f->fxb_chars[f->fxb_rcnt++];
  1116. X}
  1117. X
  1118. X/*
  1119. X * Free storage belonging to a Flexbuf.
  1120. X */
  1121. Xvoid
  1122. Xflexdelete(f)
  1123. XFlexbuf    *f;
  1124. X{
  1125. X    if (f->fxb_max > 0) {
  1126. X    (void) free(f->fxb_chars);
  1127. X    f->fxb_wcnt = f->fxb_max = 0;
  1128. X    }
  1129. X}
  1130. X
  1131. X/*
  1132. X * The following routines provide for appending formatted data to a
  1133. X * Flexbuf using a subset of the format specifiers accepted by
  1134. X * printf(3). The specifiers we understand are currently
  1135. X *
  1136. X *    %c %d %ld %lu %s %u
  1137. X *
  1138. X * Field width, precision & left justification can also be specified
  1139. X * as for printf().
  1140. X *
  1141. X * The main advantage of this is that we don't have to worry about the
  1142. X * end of the destination array being overwritten, as we do with
  1143. X * sprintf(3).
  1144. X */
  1145. X
  1146. Xstatic    unsigned    width;
  1147. Xstatic    unsigned    prec;
  1148. Xstatic    bool_t        ljust;
  1149. X
  1150. X/*
  1151. X * Append a string to a Flexbuf, truncating the string & adding filler
  1152. X * characters as specified by the width, prec & ljust variables.
  1153. X *
  1154. X * The precision specifier gives the maximum field width.
  1155. X */
  1156. Xstatic bool_t
  1157. Xstrformat(f, p)
  1158. XFlexbuf *f;
  1159. Xregister char *p;
  1160. X{
  1161. X    register int c;
  1162. X
  1163. X    if (width != 0 && !ljust) {
  1164. X    register unsigned len;
  1165. X
  1166. X    len = strlen(p);
  1167. X    if (prec != 0 && prec < len)
  1168. X        len = prec;
  1169. X    while (width > len) {
  1170. X        if (!flexaddch(f, ' '))
  1171. X        return FALSE;
  1172. X        --width;
  1173. X    }
  1174. X    }
  1175. X
  1176. X    while ((c = *p++) != '\0') {
  1177. X    if (!flexaddch(f, c))
  1178. X        return FALSE;
  1179. X    if (width != 0)
  1180. X        --width;
  1181. X    if (prec != 0) {
  1182. X        if (--prec == 0) {
  1183. X        break;
  1184. X        }
  1185. X    }
  1186. X    }
  1187. X    while (width != 0) {
  1188. X    if (!flexaddch(f, ' '))
  1189. X        return FALSE;
  1190. X    --width;
  1191. X    }
  1192. X    return TRUE;
  1193. X}
  1194. X
  1195. X/*
  1196. X * Given a binary long integer, convert it to a decimal number &
  1197. X * append it to the end of a Flexbuf.
  1198. X *
  1199. X * The precision specifier gives the minimum number of decimal digits.
  1200. X */
  1201. Xstatic bool_t
  1202. Xnumformat(f, n, uflag)
  1203. XFlexbuf    *f;
  1204. Xlong    n;
  1205. Xbool_t    uflag;
  1206. X{
  1207. X    register char *s;
  1208. X    register unsigned len;
  1209. X
  1210. X    if (n == 0) {
  1211. X    /*
  1212. X     * Special case.
  1213. X     */
  1214. X    s = "0";
  1215. X    len = 1;
  1216. X    } else {
  1217. X    static char dstr[sizeof (long) * 3 + 2];
  1218. X    register unsigned long un;
  1219. X    int neg;
  1220. X
  1221. X    * (s = &dstr[sizeof dstr - 1]) = '\0';
  1222. X
  1223. X    if (!uflag && n < 0) {
  1224. X        neg = 1;
  1225. X        un = -n;
  1226. X    } else {
  1227. X        neg = 0;
  1228. X        un = n;
  1229. X    }
  1230. X
  1231. X    while (un > 0 && s > &dstr[1]) {
  1232. X        *--s = (un % 10) + '0';
  1233. X        un /= 10;
  1234. X    }
  1235. X
  1236. X    if (neg)
  1237. X        *--s = '-';
  1238. X    len = &dstr[sizeof dstr - 1] - s;
  1239. X    }
  1240. X
  1241. X    while (width > len && width > prec) {
  1242. X    if (!flexaddch(f, ' '))
  1243. X        return FALSE;
  1244. X    --width;
  1245. X    }
  1246. X
  1247. X    while (prec > len) {
  1248. X    if (!flexaddch(f, '0'))
  1249. X        return FALSE;
  1250. X    --prec;
  1251. X    if (width > 0)
  1252. X        --width;
  1253. X    }
  1254. X    prec = 0;
  1255. X    return strformat(f, s);
  1256. X}
  1257. X
  1258. X/*
  1259. X * Main formatting routine.
  1260. X */
  1261. Xbool_t
  1262. Xvformat
  1263. X#ifdef __STDC__
  1264. X    (Flexbuf *f, register char *format, register va_list argp)
  1265. X#else
  1266. X    (f, format, argp)
  1267. X    Flexbuf        *f;
  1268. X    register char    *format;
  1269. X    register va_list    argp;
  1270. X#endif
  1271. X{
  1272. X    register int c;
  1273. X
  1274. X    while ((c = *format++) != '\0') {
  1275. X    if (c == '%') {
  1276. X        static char cstr[2];
  1277. X        bool_t lnflag;
  1278. X        bool_t zflag;
  1279. X
  1280. X        lnflag = FALSE;
  1281. X        ljust = FALSE;
  1282. X        width = 0;
  1283. X        prec = 0;
  1284. X        zflag = FALSE;
  1285. X        if ((c = *format++) == '-') {
  1286. X        ljust = TRUE;
  1287. X        c = *format++;
  1288. X        }
  1289. X
  1290. X        /*
  1291. X         * Get width specifier.
  1292. X         */
  1293. X        if (c == '0') {
  1294. X        if (ljust)
  1295. X            /*
  1296. X             * It doesn't make sense to
  1297. X             * have a left-justified
  1298. X             * numeric field with zero
  1299. X             * padding.
  1300. X             */
  1301. X            return FALSE;
  1302. X        zflag = TRUE;
  1303. X        c = *format++;
  1304. X        }
  1305. X
  1306. X        while (c && is_digit(c)) {
  1307. X        if (width != 0)
  1308. X            width *= 10;
  1309. X        width += (c - '0');
  1310. X        c = *format++;
  1311. X        }
  1312. X
  1313. X        if (c == '.') {
  1314. X        /*
  1315. X         * Get precision specifier.
  1316. X         */
  1317. X        while ((c = *format++) != '\0' && is_digit(c)) {
  1318. X            if (prec != 0)
  1319. X            prec *= 10;
  1320. X            prec += (c - '0');
  1321. X        }
  1322. X        }
  1323. X
  1324. X        switch (c) {
  1325. X        case '%':
  1326. X        cstr[0] = c;
  1327. X        if (!strformat(f, cstr))
  1328. X            return FALSE;
  1329. X        continue;
  1330. X
  1331. X        case 'c':
  1332. X        cstr[0] = va_arg(argp, int);
  1333. X        if (!strformat(f, cstr))
  1334. X            return FALSE;
  1335. X        continue;
  1336. X
  1337. X        case 'l':
  1338. X        switch (c = *format++) {
  1339. X        case 'd':
  1340. X        case 'u':
  1341. X            lnflag = TRUE;
  1342. X            break;
  1343. X        default:
  1344. X            /*
  1345. X             * Syntax error.
  1346. X             */
  1347. X            return FALSE;
  1348. X        }
  1349. X        /* fall through ... */
  1350. X
  1351. X        case 'd':
  1352. X        case 'u':
  1353. X        {
  1354. X        long n;
  1355. X
  1356. X        if (lnflag)
  1357. X        {
  1358. X            n = (c == 'u' ?
  1359. X                    (long) va_arg(argp, unsigned long) :
  1360. X                va_arg(argp, long));
  1361. X        } else {
  1362. X            n = (c == 'u' ?
  1363. X                (long) va_arg(argp, unsigned int) :
  1364. X                (long) va_arg(argp, int));
  1365. X        }
  1366. X
  1367. X        /*
  1368. X         * For integers, the precision
  1369. X         * specifier gives the minimum number
  1370. X         * of decimal digits.
  1371. X         */
  1372. X        if (zflag && prec < width) {
  1373. X            prec = width;
  1374. X            width = 0;
  1375. X        }
  1376. X        if (!numformat(f, n, (c == 'u')))
  1377. X            return FALSE;
  1378. X        continue;
  1379. X        }
  1380. X
  1381. X        case 's':
  1382. X        {
  1383. X        char *sp;
  1384. X
  1385. X        if ((sp = va_arg(argp, char *)) == NULL ||
  1386. X                        !strformat(f, sp)) {
  1387. X            return FALSE;
  1388. X        }
  1389. X        continue;
  1390. X        }
  1391. X
  1392. X        default:
  1393. X        /*
  1394. X         * Syntax error.
  1395. X         */
  1396. X        return FALSE;
  1397. X        }
  1398. X    } else if (!flexaddch(f, c)) {
  1399. X        return FALSE;
  1400. X    }
  1401. X    }
  1402. X    return TRUE;
  1403. X}
  1404. X
  1405. X/*
  1406. X * Front end callable with a variable number of arguments.
  1407. X */
  1408. X/*VARARGS2*/
  1409. Xbool_t
  1410. Xlformat
  1411. X#ifdef __STDC__
  1412. X    (Flexbuf *f, char *format, ...)
  1413. X#else
  1414. X    (f, format, va_alist)
  1415. X    Flexbuf    *f;
  1416. X    char    *format;
  1417. X    va_dcl
  1418. X#endif
  1419. X{
  1420. X    va_list argp;
  1421. X    bool_t retval;
  1422. X
  1423. X    VA_START(argp, format);
  1424. X    retval = vformat(f, format, argp);
  1425. X    va_end(argp);
  1426. X    return retval;
  1427. X}
  1428. END_OF_FILE
  1429.   if test 7093 -ne `wc -c <'xvi/src/flexbuf.c'`; then
  1430.     echo shar: \"'xvi/src/flexbuf.c'\" unpacked with wrong size!
  1431.   fi
  1432.   # end of 'xvi/src/flexbuf.c'
  1433. fi
  1434. if test -f 'xvi/src/msdos_a.asm' -a "${1}" != "-c" ; then 
  1435.   echo shar: Will not clobber existing file \"'xvi/src/msdos_a.asm'\"
  1436. else
  1437.   echo shar: Extracting \"'xvi/src/msdos_a.asm'\" \(6169 characters\)
  1438.   sed "s/^X//" >'xvi/src/msdos_a.asm' <<'END_OF_FILE'
  1439. X; Copyright (c) 1990,1991,1992 Chris and John Downey
  1440. X_TEXT    segment word public 'CODE'
  1441. X    db    "@(#)msdos_a.asm    2.1 (Chris & John Downey) 7/29/92"
  1442. X    db    0
  1443. X_TEXT    ends
  1444. X
  1445. X;***
  1446. X;
  1447. X; program name:
  1448. X;    xvi
  1449. X; function:
  1450. X;    PD version of UNIX "vi" editor, with extensions.
  1451. X; module name:
  1452. X;    msdos_a.asm
  1453. X; module function:
  1454. X;    Assembly language part of system interface module for MS-DOS.
  1455. X;
  1456. X;    This code has been assembled with Microsoft's Macro Assembler
  1457. X;    (MASM) version 5.1, & is compatible with code generated by
  1458. X;    MS-DOS C compilers using the normal large memory model calling
  1459. X;    conventions. This includes the Microsoft & Zortech compilers.
  1460. X;
  1461. X;    The ignore_signals() routine installs handlers for keyboard &
  1462. X;    critical error interrupts. Critical error interrupts are
  1463. X;    generated for events like trying to access a diskette when
  1464. X;    there isn't one in the drive, or it isn't formatted, etc. The
  1465. X;    system's default interrupt handler just displays a message
  1466. X;    followed by "Abort, Retry, Fail?", which destroys our editing
  1467. X;    screen, & if the user presses 'a', the current process gets
  1468. X;    killed without further warning. We don't want this to happen
  1469. X;    to xvi, so we install our own handler, which just pretends the
  1470. X;    user chose the "Ignore" option (or "Fail" on MS-DOS 3.0 or
  1471. X;    later) by returning 0 (for "Ignore") or 3 (for "Fail") in the
  1472. X;    AL register.
  1473. X;
  1474. X;    Note that most MS-DOS system calls, if issued from within a
  1475. X;    critical error handler, will cause the system to crash
  1476. X;    (because the system itself isn't re-entrant). 
  1477. X; history:
  1478. X;
  1479. X;    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1480. X;    Originally by Tim Thompson (twitch!tjt)
  1481. X;    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1482. X;    Heavily modified by Chris & John Downey
  1483. X;***
  1484. X
  1485. Xinclude 8086mm.inc
  1486. X
  1487. X        public    _msdsignal
  1488. X        public    _catch_signals
  1489. X        public    _getchnw
  1490. X        public    _dup
  1491. X        public    _dup2
  1492. X
  1493. X_TEXT        segment word public 'CODE'
  1494. X        even
  1495. X;
  1496. X; Address of interrupt flag.
  1497. X;
  1498. Xiflagaddr    label    dword
  1499. Xiflagoff    dw    ?
  1500. Xiflagseg    dw    ?
  1501. X
  1502. X;
  1503. X; Major MS-DOS version number.
  1504. X;
  1505. Xsysversion    db    ?
  1506. X
  1507. X        assume    nothing
  1508. X        assume    cs:_TEXT
  1509. X_msdsignal:
  1510. X        ;
  1511. X        ; void msdsignal(unsigned char *flagp);
  1512. X        ;
  1513. X        ; Install interrupt handlers.
  1514. X        ;
  1515. X        ; This routine is called by ignore_signals() with the
  1516. X        ; address of the interrupt flag in flagp.
  1517. X        ;
  1518. X        mov    bx, sp
  1519. X        push    ds
  1520. X        ;
  1521. X        ; Store address of interrupt flag.
  1522. X        ;
  1523. X    if DPTRSIZE eq 4
  1524. X        lds    ax, ss:[bx + CPTRSIZE]
  1525. X    else
  1526. X        mov    ax, [bx + CPTRSIZE]
  1527. X    endif
  1528. X        mov    dx, ds
  1529. X        mov    cx, cs
  1530. X        mov    ds, cx
  1531. X        assume    ds: _TEXT
  1532. X        mov    iflagoff, ax
  1533. X        mov    iflagseg, dx
  1534. X        ;
  1535. X        ; Get MS-DOS major version number.
  1536. X        ;
  1537. X        mov    ah, 30h
  1538. X        int    21h
  1539. X        mov    sysversion, al
  1540. X        ;
  1541. X        ; Install keyboard interrupt handler.
  1542. X        ;
  1543. X        mov    dx, offset kbd
  1544. X        mov    ax, 2523h    ; Keyboard interrupt is 23h.
  1545. X        int    21h
  1546. X        ;
  1547. X        ; Install critical error handler.
  1548. X        ;
  1549. X        mov    dx, offset criterr
  1550. X        mov    ax, 2524h    ; Critical error interrupt is 24h.
  1551. X        int    21h
  1552. X        pop    ds
  1553. X        assume    ds: nothing
  1554. X        C_ret
  1555. X
  1556. X_catch_signals:
  1557. X        ;
  1558. X        ; void catch_signals(void);
  1559. X        ;
  1560. X        ; Set console break flag so that we can be interrupted
  1561. X        ; even when we're not waiting for console input.
  1562. X        ;
  1563. X        mov    ax, 3301h
  1564. X        mov    dl, 1
  1565. X        int    21h
  1566. X        C_ret
  1567. X
  1568. X        assume    nothing
  1569. X        assume    cs: _TEXT
  1570. X
  1571. Xcriterr:            ; Entry point for critical error interrupts.
  1572. X        pushf
  1573. X        sti
  1574. X        clear    al
  1575. X        cmp    sysversion, 3
  1576. X        jb    ignore
  1577. X        mov    al, 3
  1578. Xignore:
  1579. X        popf
  1580. X        iret
  1581. Xkbd:                ; Entry point for keyboard interrupts.
  1582. X        push    ds
  1583. X        push    bx
  1584. X        ;
  1585. X        ; Increment interrupt flag.
  1586. X        ;
  1587. X        lds    bx, iflagaddr
  1588. X        mov    byte ptr [bx], 1
  1589. X        pop    bx
  1590. X        pop    ds
  1591. X        iret
  1592. X
  1593. X        assume    nothing
  1594. X        assume    cs: _TEXT
  1595. X_getchnw:
  1596. X        ;
  1597. X        ; int getchnw();
  1598. X        ;
  1599. X        ; Return a character from standard input if one is
  1600. X        ; immediately available, otherwise -1.
  1601. X        ;
  1602. X        mov    dl, 0ffh
  1603. X        mov    ah, 6
  1604. X        int    21h
  1605. X        jz    notavail
  1606. X        clear    ah
  1607. X        C_ret
  1608. Xnotavail:
  1609. X        mov    ax, -1
  1610. X        C_ret
  1611. X
  1612. X_dup:
  1613. X        ;
  1614. X        ; int dup(int fd);
  1615. X        ;
  1616. X        ; Duplicate file descriptor.
  1617. X        ;
  1618. X        push    bp
  1619. X        mov    bp, sp
  1620. X        mov    bx, [bp + CPTRSIZE + 2]
  1621. X        mov    ah, 45h
  1622. X        int    21h
  1623. X        ;
  1624. X        ; Return -1 if CF is set, otherwise new descriptor.
  1625. X        ;
  1626. X        sbb    bx, bx
  1627. X        or    ax, bx    ; New descriptor is in AX.
  1628. X        pop    bp
  1629. X        C_ret
  1630. X
  1631. X_dup2:
  1632. X        ;
  1633. X        ; int dup2(int fd1, int fd2);
  1634. X        ;
  1635. X        ; Duplicate file descriptor with specified new value.
  1636. X        ;
  1637. X        push    bp
  1638. X        mov    bp, sp
  1639. X        mov    bx, [bp + CPTRSIZE + 2] ; Existing descriptor.
  1640. X        mov    cx, [bp + CPTRSIZE + 4] ; New descriptor.
  1641. X        mov    ah, 46h
  1642. X        int    21h
  1643. X        ;
  1644. X        ; Return -1 if CF is set, otherwise 0.
  1645. X        ;
  1646. X        sbb    ax, ax
  1647. X        pop    bp
  1648. X        C_ret
  1649. X
  1650. X;
  1651. X; The following code is untested because neither of us has access to
  1652. X; an MS-DOS development system at the moment.
  1653. X;
  1654. X;            assume    nothing
  1655. X;            assume    cs: _TEXT
  1656. X;
  1657. X;    setdta        proc    near
  1658. X;            ;
  1659. X;            ; Set DOS's Disk Transfer Address to the address
  1660. X;            ; pointed to by ss:bx. This is either a near or far
  1661. X;            ; pointer, depending on what C memory model we're
  1662. X;            ; using.
  1663. X;            ;
  1664. X;            mov    ah, 1ah
  1665. X;        if DPTRSIZE eq 2        ; Small or medium memory model.
  1666. X;            mov    dx, [bx]
  1667. X;            int    21h
  1668. X;        else
  1669. X;            push    ds
  1670. X;            lds    dx, ss:[bx]
  1671. X;            int    21h
  1672. X;            pop    ds
  1673. X;        endif
  1674. X;            ret
  1675. X;    setdta        endp
  1676. X;
  1677. X;    _statfirst:
  1678. X;            ;
  1679. X;            ; int statfirst(char * name, struct dstat * info,
  1680. X;            ;        int attribute);
  1681. X;            ;
  1682. X;            ; Return information on a named file or the first file
  1683. X;            ; matching a given specification.
  1684. X;            ;
  1685. X;            ; This is like stat(2) on Unix except that it does
  1686. X;            ; pattern matching with '*' & '?' (in the base name
  1687. X;            ; only, not in any directory names). If there are
  1688. X;            ; multiple matches, statfirst() only returns
  1689. X;            ; information on the first one & statnext() can be
  1690. X;            ; called successively for subsequent ones.
  1691. X;            ;
  1692. X;            ; The base name is returned, in capital letters, in
  1693. X;            ; the dstat structure, together with some other
  1694. X;            ; information.
  1695. X;            ;
  1696. X;            mov    bx, sp
  1697. X;            add    bx, CPTRSIZE + DPTRSIZE
  1698. X;            ;
  1699. X;            ; ss:bx now points to our struct dstat pointer.
  1700. X;            ;
  1701. X;            call    setdta
  1702. X;        if DPTRSIZE eq 2
  1703. X;            mov    dx, [bx - DPTRSIZE]
  1704. X;            mov    cx, [bx + DPTRSIZE]
  1705. X;        else
  1706. X;            lds    dx, ss:[bx - DPTRSIZE]
  1707. X;            mov    cx, ss:[bx + DPTRSIZE]
  1708. X;        endif
  1709. X;            mov    ah, 4eh
  1710. X;            int    21h
  1711. X;            sbb    ax, ax
  1712. X;            C_ret
  1713. X;
  1714. X;    _statnext:
  1715. X;            ;
  1716. X;            ; int statnext(struct dstat *info);
  1717. X;            ;
  1718. X;            ; See above.
  1719. X;            ;
  1720. X;            mov    bx, sp
  1721. X;            add    bx, CPTRSIZE
  1722. X;            ;
  1723. X;            ; ss:bx now points to our struct dstat pointer.
  1724. X;            ;
  1725. X;            call    setdta
  1726. X;            mov    ah, 4fh
  1727. X;            int    21h
  1728. X;            sbb    ax, ax
  1729. X;            C_ret
  1730. X_TEXT        ends
  1731. X        end
  1732. END_OF_FILE
  1733.   if test 6169 -ne `wc -c <'xvi/src/msdos_a.asm'`; then
  1734.     echo shar: \"'xvi/src/msdos_a.asm'\" unpacked with wrong size!
  1735.   fi
  1736.   # end of 'xvi/src/msdos_a.asm'
  1737. fi
  1738. if test -f 'xvi/src/startup.c' -a "${1}" != "-c" ; then 
  1739.   echo shar: Will not clobber existing file \"'xvi/src/startup.c'\"
  1740. else
  1741.   echo shar: Extracting \"'xvi/src/startup.c'\" \(9907 characters\)
  1742.   sed "s/^X//" >'xvi/src/startup.c' <<'END_OF_FILE'
  1743. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1744. X#ifndef lint
  1745. Xstatic char *sccsid = "@(#)startup.c    2.3 (Chris & John Downey) 9/4/92";
  1746. X#endif
  1747. X
  1748. X/***
  1749. X
  1750. X* program name:
  1751. X    xvi
  1752. X* function:
  1753. X    PD version of UNIX "vi" editor, with extensions.
  1754. X* module name:
  1755. X    main.c
  1756. X* module function:
  1757. X    Entry point for xvi; setup, argument parsing and signal handling.
  1758. X* history:
  1759. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1760. X    Originally by Tim Thompson (twitch!tjt)
  1761. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1762. X    Heavily modified by Chris & John Downey
  1763. X
  1764. X***/
  1765. X
  1766. X#include "xvi.h"
  1767. X
  1768. X/*
  1769. X * References to the current cursor position, and the window
  1770. X * and buffer into which it references. These make the code a
  1771. X * lot simpler, but we have to be a bit careful to update them
  1772. X * whenever necessary.
  1773. X */
  1774. XBuffer    *curbuf;
  1775. XXviwin    *curwin;
  1776. X
  1777. X/*
  1778. X * Global variables.
  1779. X */
  1780. Xstate_t        State = NORMAL;    /* This is the current state of the command */
  1781. X                /* interpreter. */
  1782. X
  1783. Xunsigned    echo;        /*
  1784. X                 * bitmap controlling the verbosity of
  1785. X                 * screen output (see xvi.h for details).
  1786. X                 */
  1787. X
  1788. Xint        indentchars;    /* number of chars indented on current line */
  1789. X
  1790. Xvolatile unsigned char
  1791. X        kbdintr;    /*
  1792. X                 * global flag set when a keyboard interrupt
  1793. X                 * is received
  1794. X                 */
  1795. X
  1796. Xbool_t        imessage;    /*
  1797. X                 * global flag to indicate whether we should
  1798. X                 * display the "Interrupted" message
  1799. X                 */
  1800. X
  1801. X/*
  1802. X * Internal routines.
  1803. X */
  1804. Xstatic    void    usage P((void));
  1805. X
  1806. XXviwin *
  1807. Xxvi_startup(vs, argc, argv, envp)
  1808. XVirtScr    *vs;
  1809. Xint    argc;
  1810. Xchar    *argv[];
  1811. Xchar    *envp;                /* init string from the environment */
  1812. X{
  1813. X    char    *tag = NULL;        /* tag from command line */
  1814. X    char    *pat = NULL;        /* pattern from command line */
  1815. X    long    line = -1;        /* line number from command line */
  1816. X    char    **files;
  1817. X    int        numfiles = 0;
  1818. X    int        count;
  1819. X    char    *env;
  1820. X
  1821. X    ignore_signals();
  1822. X
  1823. X    /*
  1824. X     * Initialise parameter module.
  1825. X     */
  1826. X    init_params();
  1827. X
  1828. X    /*
  1829. X     * Initialise yank/put module.
  1830. X     */
  1831. X    init_yankput();
  1832. X
  1833. X    /*
  1834. X     * The critical path this code has to follow is quite tricky.
  1835. X     * We can't really run the "env" string until after we've set
  1836. X     * up the first screen window because we don't know what the
  1837. X     * commands in "env" might do: they might, for all we know,
  1838. X     * want to display something. And we can't set up the first
  1839. X     * screen window until we've set up the terminal interface.
  1840. X     *
  1841. X     * Also, we can't read the command line arguments until after
  1842. X     * we've run the "env" string because a "-s param=value" argument
  1843. X     * should override any setting of that parameter in the environment.
  1844. X     *
  1845. X     * All this means that the usage() function, which tells the
  1846. X     * user that the command line syntax was wrong, can only be
  1847. X     * called after the display interface has already been set up,
  1848. X     * which means we must be in visual mode. So usage() has to
  1849. X     * switch back to system mode (otherwise, on systems where
  1850. X     * sys_startv() & sys_endv() switch display pages,
  1851. X     * the user will never see the output of usage()). So ...
  1852. X     */
  1853. X
  1854. X    /*
  1855. X     * Set up the first buffer and screen window.
  1856. X     * Must call sys_init first.
  1857. X     */
  1858. X    curbuf = new_buffer();
  1859. X    if (curbuf == NULL) {
  1860. X    sys_endv();
  1861. X    (void) fputs("Can't allocate buffer memory.\n", stderr);
  1862. X    sys_exit(2);
  1863. X    }
  1864. X    curwin = init_window(vs);
  1865. X    if (curwin == NULL) {
  1866. X    sys_endv();
  1867. X    (void) fputs("Can't allocate buffer memory.\n", stderr);
  1868. X    sys_exit(2);
  1869. X    }
  1870. X
  1871. X    /*
  1872. X     * Connect the two together.
  1873. X     */
  1874. X    map_window_onto_buffer(curwin, curbuf);
  1875. X
  1876. X    init_sline(curwin);
  1877. X
  1878. X    /*
  1879. X     * Save a copy of the passed environment string in case it was
  1880. X     * obtained from getenv(), so that the subsequent call we make
  1881. X     * to get the SHELL parameter value does not overwrite it.
  1882. X     */
  1883. X    if (envp != NULL) {
  1884. X    env = strsave(envp);
  1885. X    } else {
  1886. X        env = NULL;
  1887. X    }
  1888. X
  1889. X    /*
  1890. X     * Try to obtain a value for the "shell" parameter from the
  1891. X     * environment variable SHELL. If this is NULL, do not override
  1892. X     * any existing value. The system interface code (sys_init()) is
  1893. X     * free to set up a default value, and the initialisation string
  1894. X     * in the next part of the startup is free to override both that
  1895. X     * value and the one from the environment.
  1896. X     */
  1897. X    {
  1898. X    char    *sh;
  1899. X
  1900. X    sh = getenv("SHELL");
  1901. X    if (sh != NULL) {
  1902. X        set_param(P_shell, sh);
  1903. X    }
  1904. X    }
  1905. X
  1906. X    /*
  1907. X     * Run any initialisation string passed to us.
  1908. X     *
  1909. X     * We can't really do this until we have set up the terminal
  1910. X     * because we don't know what the initialisation string might do.
  1911. X     */
  1912. X    if (env != NULL) {
  1913. X    register char    *ep;
  1914. X    register bool_t    escaped = FALSE;
  1915. X
  1916. X    /*
  1917. X     * Commands in the initialization string can be
  1918. X     * separated by '|' (or '\n'), but a literal '|' or
  1919. X     * '\n' can be escaped by a preceding '\\', so we have
  1920. X     * to process the string, looking for all three
  1921. X     * characters.
  1922. X     */
  1923. X    for (ep = env; *ep;) {
  1924. X        switch (*ep++) {
  1925. X        case '\\':
  1926. X        escaped = TRUE;
  1927. X        continue;
  1928. X        case '|':
  1929. X        case '\n':
  1930. X        if (escaped) {
  1931. X            register char *s, *d;
  1932. X
  1933. X            for (d = (s = --ep) - 1; (*d++ = *s++) != '\0'; )
  1934. X            ;
  1935. X        } else {
  1936. X            ep[-1] = '\0';
  1937. X            do_colon(env, FALSE);
  1938. X            env = ep;
  1939. X        }
  1940. X        /* fall through ... */
  1941. X        default:
  1942. X        escaped = FALSE;
  1943. X        }
  1944. X    }
  1945. X    if (ep > env) {
  1946. X        do_colon(env, FALSE);
  1947. X    }
  1948. X    }
  1949. X
  1950. X    /*
  1951. X     * Process the command line arguments.
  1952. X     *
  1953. X     * We can't really do this until we have run the "env" string,
  1954. X     * because "-s param=value" on the command line should override
  1955. X     * parameter setting in the environment.
  1956. X     *
  1957. X     * This is a bit awkward because it means usage() is called
  1958. X     * when we're already in vi mode (which means, among other
  1959. X     * things, that display pages may have been swapped).
  1960. X     */
  1961. X    for (count = 1;
  1962. X     count < argc && (argv[count][0] == '-' || argv[count][0] == '+');
  1963. X                                count++) {
  1964. X
  1965. X    if (argv[count][0] == '-') {
  1966. X        switch (argv[count][1]) {
  1967. X        case 't':
  1968. X        /*
  1969. X         * -t tag or -ttag
  1970. X         */
  1971. X        if (numfiles != 0)
  1972. X            usage();
  1973. X        if (argv[count][2] != '\0') {
  1974. X            tag = &(argv[count][2]);
  1975. X        } else if (count < (argc - 1)) {
  1976. X            count += 1;
  1977. X            tag = argv[count];
  1978. X        } else {
  1979. X            usage();
  1980. X        }
  1981. X        break;
  1982. X
  1983. X        case 's':
  1984. X        /*
  1985. X         * -s param=value or
  1986. X         * -sparam=value
  1987. X         */
  1988. X        if (argv[count][2] != '\0') {
  1989. X            argv[count] += 2;
  1990. X        } else if (count < (argc - 1)) {
  1991. X            count += 1;
  1992. X        } else {
  1993. X            usage();
  1994. X        }
  1995. X        do_set(curwin, 1, &argv[count], FALSE);
  1996. X        break;
  1997. X
  1998. X        default:
  1999. X        usage();
  2000. X        }
  2001. X
  2002. X    } else /* argv[count][0] == '+' */ {
  2003. X        char    nc;
  2004. X
  2005. X        /*
  2006. X         * "+n file" or "+/pat file"
  2007. X         */
  2008. X        if (count >= (argc - 1))
  2009. X        usage();
  2010. X
  2011. X        nc = argv[count][1];
  2012. X        if (nc == '/') {
  2013. X        pat = &(argv[count][2]);
  2014. X        } else if (is_digit(nc)) {
  2015. X        line = atol(&(argv[count][1]));
  2016. X        } else if (nc == '\0') {
  2017. X        line = 0;
  2018. X        } else {
  2019. X        usage();
  2020. X        }
  2021. X        count += 1;
  2022. X        files = &argv[count];
  2023. X        numfiles = 1;
  2024. X    }
  2025. X    }
  2026. X    if (numfiles != 0 || tag != NULL) {
  2027. X    /*
  2028. X     * If we found "-t tag", "+n file" or "+/pat file" on
  2029. X     * the command line, we don't want to see any more
  2030. X     * file names.
  2031. X     */
  2032. X    if (count < argc)
  2033. X        usage();
  2034. X    } else {
  2035. X    /*
  2036. X     * Otherwise, file names are valid.
  2037. X     */
  2038. X    numfiles = argc - count;
  2039. X    if (numfiles > 0) {
  2040. X        files = &(argv[count]);
  2041. X    }
  2042. X    }
  2043. X
  2044. X    /*
  2045. X     * Initialise the cursor and top of screen pointers
  2046. X     * to the start of the first buffer. Note that the
  2047. X     * bottom of screen pointer is also set up, as some
  2048. X     * code (e.g. move_window_to_cursor) depends on it.
  2049. X     */
  2050. X    curwin->w_topline = curbuf->b_file;
  2051. X    curwin->w_botline = curbuf->b_file->l_next;
  2052. X    move_cursor(curwin, curbuf->b_file, 0);
  2053. X    curwin->w_col = 0;
  2054. X    curwin->w_row = 0;
  2055. X
  2056. X    /*
  2057. X     * Clear the window.
  2058. X     *
  2059. X     * It doesn't make sense to do this until we have a value for
  2060. X     * Pn(P_colour).
  2061. X     */
  2062. X    clear(curwin);
  2063. X
  2064. X    if (numfiles != 0) {
  2065. X    if (line < 0 && pat == NULL)
  2066. X        echo = e_CHARUPDATE | e_SHOWINFO;
  2067. X
  2068. X    do_next(curwin, numfiles, files, FALSE);
  2069. X
  2070. X    if (pat != NULL) {
  2071. X        echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  2072. X        (void) dosearch(curwin, pat, '/');
  2073. X    } else if (line >= 0) {
  2074. X        echo = e_CHARUPDATE | e_SHOWINFO;
  2075. X        do_goto((line > 0) ? line : MAX_LINENO);
  2076. X    }
  2077. X
  2078. X    } else if (tag != NULL) {
  2079. X    echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  2080. X    if (do_tag(curwin, tag, FALSE, TRUE, FALSE) == FALSE) {
  2081. X        /*
  2082. X         * Failed to find tag - wait for a while
  2083. X         * to allow user to read tags error and then
  2084. X         * display the "no file" message.
  2085. X         */
  2086. X        sleep(2);
  2087. X        show_file_info(curwin);
  2088. X    }
  2089. X    } else {
  2090. X    echo = e_CHARUPDATE | e_SHOWINFO;
  2091. X    show_file_info(curwin);
  2092. X    }
  2093. X
  2094. X    setpcmark(curwin);
  2095. X
  2096. X    echo = e_CHARUPDATE;
  2097. X
  2098. X    /*
  2099. X     * Ensure we are at the right screen position.
  2100. X     */
  2101. X    move_window_to_cursor(curwin);
  2102. X
  2103. X    /*
  2104. X     * Draw the screen.
  2105. X     */
  2106. X    update_all();
  2107. X
  2108. X    /*
  2109. X     * Update the cursor position on the screen, and go there.
  2110. X     */
  2111. X    cursupdate(curwin);
  2112. X    wind_goto(curwin);
  2113. X
  2114. X    /*
  2115. X     * Allow everything.
  2116. X     */
  2117. X    echo = e_ANY;
  2118. X
  2119. X    catch_signals();
  2120. X
  2121. X    if (env != NULL) {
  2122. X    free(env);
  2123. X    }
  2124. X
  2125. X    return(curwin);
  2126. X}
  2127. X
  2128. X/*
  2129. X * Print usage message and die.
  2130. X *
  2131. X * This function is only called after we have set the terminal to vi
  2132. X * mode.
  2133. X *
  2134. X * The system interface functions have to ensure that it's safe to
  2135. X * call sys_exit() when sys_endv() has already been called (& there
  2136. X * hasn't necessarily been any intervening sys_startv()).
  2137. X */
  2138. Xstatic void
  2139. Xusage()
  2140. X{
  2141. X    sys_endv();
  2142. X    (void) fputs("Usage: xvi { options } [ file ... ]\n", stderr);
  2143. X    (void) fputs("       xvi { options } -t tag\n", stderr);
  2144. X    (void) fputs("       xvi { options } +[num] file\n", stderr);
  2145. X    (void) fputs("       xvi { options } +/pat  file\n", stderr);
  2146. X    (void) fputs("\nOptions are:\n", stderr);
  2147. X    (void) fputs("       -s [no]boolean-parameter\n", stderr);
  2148. X    (void) fputs("       -s parameter=value\n", stderr);
  2149. X    sys_exit(1);
  2150. X}
  2151. END_OF_FILE
  2152.   if test 9907 -ne `wc -c <'xvi/src/startup.c'`; then
  2153.     echo shar: \"'xvi/src/startup.c'\" unpacked with wrong size!
  2154.   fi
  2155.   # end of 'xvi/src/startup.c'
  2156. fi
  2157. if test -f 'xvi/src/sunfront.c' -a "${1}" != "-c" ; then 
  2158.   echo shar: Will not clobber existing file \"'xvi/src/sunfront.c'\"
  2159. else
  2160.   echo shar: Extracting \"'xvi/src/sunfront.c'\" \(7353 characters\)
  2161.   sed "s/^X//" >'xvi/src/sunfront.c' <<'END_OF_FILE'
  2162. X#ifndef lint
  2163. Xstatic char *sccsid = "@(#)sunfront.c    2.1 (Chris & John Downey) 7/29/92";
  2164. X#endif
  2165. X
  2166. X/***
  2167. X
  2168. X* program name:
  2169. X    xvi
  2170. X* function:
  2171. X    PD version of UNIX "vi" editor, with extensions.
  2172. X* module name:
  2173. X    sunfront.c
  2174. X* module function:
  2175. X    Terminal interface module for SunView: front end program.
  2176. X* history:
  2177. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  2178. X    Originally by Tim Thompson (twitch!tjt)
  2179. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  2180. X    Heavily modified by Chris & John Downey
  2181. X***/
  2182. X
  2183. X#include "xvi.h"
  2184. X
  2185. X#include <suntool/sunview.h>
  2186. X#include <suntool/panel.h>
  2187. X#include <suntool/icon.h>
  2188. X#include <suntool/canvas.h>
  2189. X#include <suntool/tty.h>
  2190. X#include <sys/filio.h>
  2191. X#include <sys/types.h>
  2192. X#include <sys/socket.h>
  2193. X#include <vfork.h>
  2194. X
  2195. Xstatic short icon_image[] =
  2196. X{
  2197. X#   include "xvi.icn"
  2198. X};
  2199. X
  2200. Xmpr_static(iconpr, 64, 64, 1, icon_image);
  2201. X
  2202. Xstatic Frame frame;
  2203. Xstatic Tty xviwin;
  2204. X
  2205. X/*
  2206. X * Handle keyboard or mouse input.
  2207. X */
  2208. Xstatic Notify_value
  2209. Xttyproc(win, event, na, type)
  2210. XTty            win;
  2211. XEvent            *event;
  2212. XNotify_arg        na;
  2213. XNotify_event_type    type;
  2214. X{
  2215. X    static Pixfont    *deffont = (Pixfont *) 0; /* default font */
  2216. X    register int    evtcode;
  2217. X    static char        seqbuf[(sizeof (unsigned int) * 12) + 7] =
  2218. X                        { PREFIXCHAR };
  2219. X    int            nchars;
  2220. X    bool_t        done;
  2221. X    static unsigned    buttonstate, prevx, prevy;
  2222. X    unsigned        mx, my;
  2223. X
  2224. X#define    BUTTONMASK(e)        (1 << ((e) - BUT(1)))
  2225. X
  2226. X    if (deffont == NULL) {
  2227. X    /*
  2228. X     * Get default font.
  2229. X     */
  2230. X    deffont = pf_default();
  2231. X    }
  2232. X
  2233. X    evtcode = event_action(event);
  2234. X    mx = event_x(event) / deffont->pf_defaultsize.x;
  2235. X    my = event_y(event) / deffont->pf_defaultsize.y;
  2236. X    nchars = 0;
  2237. X    done = FALSE;
  2238. X    if (evtcode == LOC_DRAG && buttonstate == BUTTONMASK(MS_MIDDLE)) {
  2239. X    if (mx != prevx || my != prevy) {
  2240. X        /*
  2241. X         * Mouse drag event. Send a PREFIXCHAR,
  2242. X         * followed by 'm', followed by the starting
  2243. X         * row, finishing row, starting column &
  2244. X         * finishing column, in that order.
  2245. X         */
  2246. X        sprintf(&seqbuf[1], "m%x;%x;%x;%x;", prevy, my, prevx, mx);
  2247. X        nchars = strlen(seqbuf);
  2248. X        done = TRUE;
  2249. X        prevx = mx;
  2250. X        prevy = my;
  2251. X    }
  2252. X    } else if (event_is_down(event)) {
  2253. X    if (event_is_button(event)) {
  2254. X        switch (evtcode) {
  2255. X        case MS_MIDDLE:
  2256. X        prevx = mx;
  2257. X        prevy = my;
  2258. X        break;
  2259. X        case MS_RIGHT:
  2260. X        /*
  2261. X         * Right button pressed. We have to
  2262. X         * send a PREFIXCHAR, followed by 'p',
  2263. X         * followed by the position of the
  2264. X         * mouse cursor in character
  2265. X         * co-ordinates: y first, then x.
  2266. X         */
  2267. X        sprintf(&seqbuf[1], "p%x;%x;", my, mx);
  2268. X        nchars = strlen(seqbuf);
  2269. X        done = TRUE;
  2270. X        }
  2271. X        buttonstate |= BUTTONMASK(evtcode);
  2272. X    } else {
  2273. X        /*
  2274. X         * nchars is the number of characters we have
  2275. X         * to send to xvi.main. In most of the cases
  2276. X         * we have to deal with here, this will be 2.
  2277. X         */
  2278. X        nchars = 2;
  2279. X        done = TRUE;
  2280. X        switch (evtcode) {
  2281. X        case PREFIXCHAR:
  2282. X        seqbuf[1] = PREFIXCHAR;
  2283. X        break;
  2284. X        case KEY_RIGHT(7):
  2285. X        seqbuf[1] = 'H';
  2286. X        break;
  2287. X        case KEY_RIGHT(8):
  2288. X        seqbuf[1] = 'k';
  2289. X        break;
  2290. X        case KEY_RIGHT(9):
  2291. X        seqbuf[1] = CTRL('B');
  2292. X        break;
  2293. X        case KEY_RIGHT(10):
  2294. X        seqbuf[1] = '\b';
  2295. X        break;
  2296. X        case KEY_RIGHT(12):
  2297. X        seqbuf[1] = ' ';
  2298. X        break;
  2299. X        case KEY_RIGHT(13):
  2300. X        seqbuf[1] = 'L';
  2301. X        break;
  2302. X        case KEY_RIGHT(14):
  2303. X        seqbuf[1] = 'j';
  2304. X        break;
  2305. X        case KEY_RIGHT(15):
  2306. X        seqbuf[1] = CTRL('F');
  2307. X        break;
  2308. X        default:
  2309. X        nchars = 0;
  2310. X        done = FALSE;
  2311. X        }
  2312. X    }
  2313. X    } else if (event_is_up(event) && event_is_button(event)) {
  2314. X    if (evtcode == MS_RIGHT)
  2315. X        done = TRUE;
  2316. X    buttonstate &= ~BUTTONMASK(evtcode);
  2317. X    }
  2318. X    if (nchars > 0) {
  2319. X    ttysw_input(xviwin, seqbuf, nchars);
  2320. X    }
  2321. X    return done ?
  2322. X       NOTIFY_DONE :
  2323. X       notify_next_event_func(win, event, na, type);
  2324. X}
  2325. X
  2326. X/*
  2327. X * Read messages coming from back-end process.
  2328. X */
  2329. Xstatic Notify_value
  2330. Xreadsocket(client, fd)
  2331. XNotify_client    client;
  2332. Xint        fd;
  2333. X{
  2334. X    char c;
  2335. X
  2336. X    while (read(fd, &c, 1) == 1) {
  2337. X    if (c == 'q') {
  2338. X        (void) notify_set_input_func(client, NOTIFY_FUNC_NULL, fd);
  2339. X        window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
  2340. X        window_destroy(frame);
  2341. X        return NOTIFY_DONE;
  2342. X    }
  2343. X
  2344. X    }
  2345. X    return NOTIFY_DONE;
  2346. X}
  2347. X
  2348. Xstatic Notify_value
  2349. Xsigign(client, signum, when)
  2350. XNotify_client        client;
  2351. Xint            signum;
  2352. XNotify_signal_mode    when;
  2353. X{
  2354. X    return NOTIFY_IGNORED;
  2355. X}
  2356. X
  2357. X/*
  2358. X * Start up our back-end process and connect its standard input,
  2359. X * output & error files to the tty subwindow we've created for it.
  2360. X *
  2361. X * We use a pair of connected stream sockets to communicate with it:
  2362. X * it can reference its socket as file descriptor 3. Currently, this
  2363. X * is only used by the back-end process to tell us when to exit (by
  2364. X * sending the single character 'q').
  2365. X */
  2366. Xstatic void
  2367. Xforkmain(argv)
  2368. Xchar    **argv;
  2369. X{
  2370. X    int        winfd;
  2371. X    int        commsock[2];
  2372. X    int        savefd[4];
  2373. X    int        nbflag;
  2374. X    int        i;
  2375. X    char    *progname;
  2376. X
  2377. X
  2378. X    for (i = 0; i <= 3; i++) {
  2379. X    while ((savefd[i] = dup(i)) <= 3) {
  2380. X        ;
  2381. X    }
  2382. X    }
  2383. X    if (socketpair(AF_UNIX, SOCK_STREAM, 0, commsock) != 0) {
  2384. X    fprintf(stderr, "%s: can't create socket\n", argv[0]);
  2385. X    exit(1);
  2386. X    }
  2387. X    winfd = (int) window_get(xviwin, TTY_TTY_FD);
  2388. X    if ((progname = strdup(argv[0])) == NULL) {
  2389. X    progname = "xvi.sunview";
  2390. X    }
  2391. X    argv[0] = XVI_MAINPROG;
  2392. X    switch (vfork()) {
  2393. X    case 0:        /* This is the child process. */
  2394. X    for (i = 0; i <= 2; i++) {
  2395. X        dup2(winfd, i);
  2396. X    }
  2397. X    dup2(commsock[1], 3);
  2398. X    ioctl(winfd, FIOCLEX, 0);
  2399. X    ioctl(commsock[0], FIOCLEX, 0);
  2400. X    ioctl(commsock[1], FIOCLEX, 0);
  2401. X    for (i = 0; i <= 3; i++) {
  2402. X        ioctl(savefd[i], FIOCLEX, 0);
  2403. X    }
  2404. X    execvp(argv[0], argv);
  2405. X    fprintf(stderr, "%s: can't execute %s\n", progname, argv[0]);
  2406. X    fflush(stderr);
  2407. X    _exit(1);
  2408. X
  2409. X    case -1:
  2410. X    fprintf(stderr, "%s: vfork() failed\n", progname);
  2411. X    fflush(stderr);
  2412. X    _exit(1);
  2413. X
  2414. X    default:    /* This is the parent process. */
  2415. X    /*
  2416. X     * We should only reach this point after the
  2417. X     * child has called execvp() (or died).
  2418. X     */
  2419. X    for (i = 0; i <= 3; i++) {
  2420. X        dup2(savefd[i], i);
  2421. X        close(savefd[i]);
  2422. X    }
  2423. X    close(commsock[1]);
  2424. X    /*
  2425. X     * commsock[0] is our end of the socketpair.
  2426. X     * We have to make it non-blocking & register
  2427. X     * an input handler for it.
  2428. X     */
  2429. X    nbflag = 1;
  2430. X    ioctl(commsock[0], FIONBIO, &nbflag);
  2431. X    (void) notify_set_input_func((Notify_client) xviwin,
  2432. X                    readsocket, commsock[0]);
  2433. X    }
  2434. X}
  2435. X
  2436. Xmain(argc, argv)
  2437. Xint    argc;
  2438. Xchar    **argv;
  2439. X{
  2440. X    Icon    xvicon;
  2441. X    char    *label;
  2442. X
  2443. X    if ((label = strrchr(argv[0], '/')) == NULL) {
  2444. X    label = argv[0];
  2445. X    } else {
  2446. X    label++;
  2447. X    }
  2448. X    xvicon = icon_create(ICON_IMAGE, &iconpr, 0);
  2449. X    frame = window_create(NULL,                FRAME,
  2450. X                FRAME_LABEL,        label,
  2451. X                FRAME_ICON,            xvicon,
  2452. X                FRAME_ARGC_PTR_ARGV,    &argc, argv,
  2453. X                WIN_ERROR_MSG,        "Can't create window",
  2454. X                FRAME_NO_CONFIRM,        TRUE,
  2455. X                FRAME_SUBWINDOWS_ADJUSTABLE,
  2456. X                FALSE,
  2457. X                0);
  2458. X    xviwin = window_create(frame,            TTY,
  2459. X                TTY_ARGV,            TTY_ARGV_DO_NOT_FORK,
  2460. X                WIN_CONSUME_KBD_EVENTS,    WIN_RIGHT_KEYS,
  2461. X                0,
  2462. X                WIN_CONSUME_PICK_EVENTS,    WIN_MOUSE_BUTTONS,
  2463. X                WIN_UP_EVENTS,
  2464. X                LOC_DRAG,
  2465. X                0,
  2466. X                0);
  2467. X    (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  2468. X              SIGHUP, NOTIFY_ASYNC);
  2469. X    (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  2470. X              SIGINT, NOTIFY_ASYNC);
  2471. X    (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  2472. X              SIGQUIT, NOTIFY_ASYNC);
  2473. X    forkmain(argv);
  2474. X    notify_interpose_event_func(xviwin, ttyproc, NOTIFY_SAFE);
  2475. X    window_main_loop(frame);
  2476. X}
  2477. END_OF_FILE
  2478.   if test 7353 -ne `wc -c <'xvi/src/sunfront.c'`; then
  2479.     echo shar: \"'xvi/src/sunfront.c'\" unpacked with wrong size!
  2480.   fi
  2481.   # end of 'xvi/src/sunfront.c'
  2482. fi
  2483. echo shar: End of archive 15 \(of 18\).
  2484. cp /dev/null ark15isdone
  2485. MISSING=""
  2486. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  2487.     if test ! -f ark${I}isdone ; then
  2488.     MISSING="${MISSING} ${I}"
  2489.     fi
  2490. done
  2491. if test "${MISSING}" = "" ; then
  2492.     echo You have unpacked all 18 archives.
  2493.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2494. else
  2495.     echo You still must unpack the following archives:
  2496.     echo "        " ${MISSING}
  2497. fi
  2498. exit 0
  2499. exit 0 # Just in case...
  2500.