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

  1. Newsgroups: comp.sources.misc
  2. From: jmd@cyclone.bt.co.uk (John Downey)
  3. Subject:  v33i022:  xvi - portable multi-window vi-like editor, Part13/18
  4. Message-ID: <1992Oct24.172432.2229@sparky.imd.sterling.com>
  5. X-Md4-Signature: acfc7434ac3367299701e94351de32e1
  6. Date: Sat, 24 Oct 1992 17:24:32 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 22
  11. Archive-name: xvi/part13
  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/find.c xvi/src/movement.c xvi/src/qnx.c
  19. #   xvi/src/regmagic.h xvi/src/yankput.c
  20. # Wrapped by kent@sparky on Thu Oct 22 09:03:43 1992
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 13 (of 18)."'
  24. if test -f 'xvi/src/find.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'xvi/src/find.c'\"
  26. else
  27.   echo shar: Extracting \"'xvi/src/find.c'\" \(12296 characters\)
  28.   sed "s/^X//" >'xvi/src/find.c' <<'END_OF_FILE'
  29. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  30. X#ifndef lint
  31. Xstatic char *sccsid = "@(#)find.c    2.2 (Chris & John Downey) 7/29/92";
  32. X#endif
  33. X
  34. X/***
  35. X
  36. X* program name:
  37. X    xvi
  38. X* function:
  39. X    PD version of UNIX "vi" editor, with extensions.
  40. X* module name:
  41. X    find.c
  42. X* module function:
  43. X    Character and function searching.
  44. X* history:
  45. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  46. X    Originally by Tim Thompson (twitch!tjt)
  47. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  48. X    Heavily modified by Chris & John Downey
  49. X
  50. X***/
  51. X
  52. X#include "xvi.h"
  53. X#include "regexp.h"    /* Henry Spencer's regular expression routines */
  54. X
  55. X#ifdef    MEGAMAX
  56. Xoverlay "find"
  57. X#endif
  58. X
  59. X/*
  60. X * Character Searches
  61. X */
  62. X
  63. Xstatic char lastc;        /* last character searched for */
  64. Xstatic int  lastcdir;        /* last direction of character search */
  65. Xstatic int  lastctype;        /* last type of search ("find" or "to") */
  66. X
  67. X/*
  68. X * searchc(c, dir, type, num)
  69. X *
  70. X * Search for character 'c', in direction 'dir'. If type is 0, move to
  71. X * the position of the character, otherwise move to just before the char.
  72. X * 'num' is the number of times to do it (the prefix number).
  73. X */
  74. XPosn *
  75. Xsearchc(ch, dir, type, num)
  76. Xint    ch;
  77. Xint    dir;
  78. Xint    type;
  79. Xint    num;
  80. X{
  81. X    static Posn        pos;            /* saved cursor posn */
  82. X    enum mvtype        (*mvfunc) P((Posn *));
  83. X    enum mvtype        (*backfunc) P((Posn *));
  84. X    unsigned char    c;            /* as ch but uchar */
  85. X    register int    i;            /* loop counter */
  86. X
  87. X    /*
  88. X     * Remember details in case we want to repeat the search.
  89. X     */
  90. X    lastc = ch;
  91. X    lastcdir = dir;
  92. X    lastctype = type;
  93. X
  94. X    pos = *(curwin->w_cursor);    /* save position in case we fail */
  95. X    c = ch;
  96. X    if (dir == FORWARD) {
  97. X    mvfunc = inc;
  98. X    backfunc = dec;
  99. X    } else {
  100. X    mvfunc = dec;
  101. X    backfunc = inc;
  102. X    }
  103. X
  104. X    /*
  105. X     * On 'to' searches, skip one to start with so we can repeat
  106. X     * searches in the same direction and have it work right.
  107. X     */
  108. X    if (type) {
  109. X    if ((*mvfunc)(&pos) != mv_SAMELINE) {
  110. X        return(NULL);
  111. X    }
  112. X    }
  113. X
  114. X    for (i = 0; i < num; i++) {
  115. X    bool_t    found;
  116. X
  117. X    found = FALSE;
  118. X    while ((*mvfunc)(&pos) == mv_SAMELINE) {
  119. X        if ((unsigned char) gchar(&pos) == c) {
  120. X        found = TRUE;
  121. X        break;
  122. X        }
  123. X    }
  124. X    if (!found) {
  125. X        return(NULL);
  126. X    }
  127. X    }
  128. X    if (type) {
  129. X    (void) (*backfunc)(&pos);
  130. X    }
  131. X    return(&pos);
  132. X}
  133. X
  134. X/*ARGSUSED*/
  135. XPosn *
  136. Xcrepsearch(buffer, flag, num)
  137. XBuffer    *buffer;
  138. Xint    flag;
  139. Xint    num;
  140. X{
  141. X    Posn    *newpos;
  142. X    int    dir;
  143. X    int    savedir;
  144. X
  145. X    if (lastc == '\0') {
  146. X    return(NULL);
  147. X    }
  148. X
  149. X    savedir = lastcdir;
  150. X    if (flag) {
  151. X    dir = (lastcdir == FORWARD) ? BACKWARD : FORWARD;
  152. X    } else {
  153. X    dir = lastcdir;
  154. X    }
  155. X
  156. X    newpos = searchc(lastc, dir, lastctype, num);
  157. X
  158. X    lastcdir = savedir;        /* put direction of search back how it was */
  159. X
  160. X    return(newpos);
  161. X}
  162. X
  163. X/*
  164. X * "Other" Searches
  165. X */
  166. X
  167. X/*
  168. X * showmatch - move the cursor to the matching paren or brace
  169. X */
  170. XPosn *
  171. Xshowmatch()
  172. X{
  173. X    register char    initc;            /* initial char */
  174. X    register enum mvtype
  175. X                (*move) P((Posn *));    /* function to move cursor */
  176. X    register char    findc;            /* terminating char */
  177. X    static Posn        pos;            /* current position */
  178. X    char        c;
  179. X    int            count = 0;
  180. X    bool_t        found = FALSE;
  181. X
  182. X    pos = *curwin->w_cursor;
  183. X
  184. X    /*
  185. X     * Move forward to the first bracket character after the cursor.
  186. X     * If we get to EOF before a bracket, return NULL.
  187. X     */
  188. X    for (found = FALSE; !found; ) {
  189. X    initc = gchar(&pos);
  190. X    switch (initc) {
  191. X    case '(':
  192. X        findc = ')';
  193. X        move = inc;
  194. X        found = TRUE;
  195. X        break;
  196. X    case ')':
  197. X        findc = '(';
  198. X        move = dec;
  199. X        found = TRUE;
  200. X        break;
  201. X    case '{':
  202. X        findc = '}';
  203. X        move = inc;
  204. X        found = TRUE;
  205. X        break;
  206. X    case '}':
  207. X        findc = '{';
  208. X        move = dec;
  209. X        found = TRUE;
  210. X        break;
  211. X    case '[':
  212. X        findc = ']';
  213. X        move = inc;
  214. X        found = TRUE;
  215. X        break;
  216. X    case ']':
  217. X        findc = '[';
  218. X        move = dec;
  219. X        found = TRUE;
  220. X        break;
  221. X    default:
  222. X        if (inc(&pos) == mv_NOMOVE) {
  223. X        return(NULL);
  224. X        }
  225. X    }
  226. X    }
  227. X
  228. X    /*
  229. X     * Move in the appropriate direction until we find a matching
  230. X     * bracket or reach end of file.
  231. X     */
  232. X    while ((*move)(&pos) != mv_NOMOVE) {
  233. X    c = gchar(&pos);
  234. X    if (c == initc) {
  235. X        count++;
  236. X    } else if (c == findc) {
  237. X        if (count == 0)
  238. X        return(&pos);
  239. X        count--;
  240. X    }
  241. X    }
  242. X    return(NULL);            /* never found it */
  243. X}
  244. X
  245. X/*
  246. X * Find the nth next occurrence of str in the specified direction.
  247. X */
  248. XPosn *
  249. Xfind_pattern(str, dir, num)
  250. Xchar    *str;
  251. Xint    dir;
  252. Xint    num;
  253. X{
  254. X    Posn    *p;
  255. X    Posn    *lastp;
  256. X
  257. X    p = curwin->w_cursor;
  258. X    lastp = NULL;
  259. X    while (num-- > 0) {
  260. X    p = nsearch(curwin, p->p_line, p->p_index, dir, str);
  261. X    if (p != NULL) {
  262. X        lastp = p;
  263. X    } else {
  264. X        break;
  265. X    }
  266. X    }
  267. X
  268. X    return(lastp);
  269. X}
  270. X
  271. X/*
  272. X * The following routines do the word searches performed by the
  273. X * 'w', 'W', 'b', 'B', 'e', and 'E' commands.
  274. X */
  275. X
  276. X/*
  277. X * To perform these searches, characters are placed into one of three
  278. X * classes, and transitions between classes determine word boundaries.
  279. X *
  280. X * The classes are:
  281. X *
  282. X * cl_white - white space
  283. X * cl_text  - letters, digits, and underscore
  284. X * cl_punc  - everything else
  285. X */
  286. X
  287. Xtypedef enum {
  288. X    cl_white,
  289. X    cl_text,
  290. X    cl_punc
  291. X} cclass;
  292. X
  293. Xstatic    int    stype;        /* type of the word motion being performed */
  294. X
  295. X#define is_white(c)    (((c) == ' ') || ((c) == '\t') || ((c) == '\0'))
  296. X#define is_text(c)    (is_alnum(c) || ((c) == '_'))
  297. X
  298. X/*
  299. X * cls(c) - returns the class of character 'c'
  300. X *
  301. X * The 'type' of the current search modifies the classes of characters
  302. X * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from
  303. X * class "cl_punc" are reported as class "cl_text" since only white space
  304. X * boundaries are of interest.
  305. X */
  306. Xstatic cclass
  307. Xcls(c)
  308. Xchar    c;
  309. X{
  310. X    if (is_white(c))
  311. X    return(cl_white);
  312. X
  313. X    if (is_text(c))
  314. X    return(cl_text);
  315. X
  316. X    /*
  317. X     * If stype is non-zero, report these as class 1.
  318. X     */
  319. X    return((stype == 0) ? cl_punc : cl_text);
  320. X}
  321. X
  322. X
  323. X/*
  324. X * fwd_word(pos, type, skip_white) - move forward one word
  325. X *
  326. X * Returns the resulting position, or NULL if EOF was reached.
  327. X *
  328. X * The extra argument "skip_white" (which is only used in fwd_word,
  329. X * but also included in bck_word and end_word for compatibility) is
  330. X * used to indicate whether to skip over white space to get to the
  331. X * start of the next word. If it is FALSE, the position returned will
  332. X * be the first white-space character (or punctuation) encountered.
  333. X * This is used by one command only: "cw".
  334. X */
  335. XPosn *
  336. Xfwd_word(p, type, skip_white)
  337. XPosn    *p;
  338. Xint    type;
  339. Xbool_t    skip_white;
  340. X{
  341. X    static    Posn    pos;
  342. X    cclass        sclass;        /* starting class */
  343. X
  344. X    stype = type;
  345. X    sclass = cls(gchar(p));
  346. X
  347. X    pos = *p;
  348. X
  349. X    /*
  350. X     * We always move at least one character.
  351. X     */
  352. X    if (inc(&pos) == mv_NOMOVE)
  353. X    return(NULL);
  354. X
  355. X    if (sclass != cl_white) {
  356. X    /*
  357. X     * We were in the middle of a word to start with.
  358. X     * Move right until we change character class.
  359. X     */
  360. X    while (cls(gchar(&pos)) == sclass) {
  361. X        if (inc(&pos) == mv_NOMOVE) {
  362. X        /*
  363. X         * Got to EOF. Return current position.
  364. X         */
  365. X        return(&pos);
  366. X        }
  367. X    }
  368. X
  369. X    /*
  370. X     * If we went from punctuation -> text
  371. X     * or text -> punctuation, return here.
  372. X     *
  373. X     * If we went text/punctuation -> whitespace,
  374. X     * we want to continue to the start of the
  375. X     * next word, if there is one.
  376. X     */
  377. X    if (cls(gchar(&pos)) != cl_white)
  378. X        return(&pos);
  379. X    }
  380. X
  381. X    /*
  382. X     * We're in white space; go to next non-white.
  383. X     */
  384. X    if (skip_white) {
  385. X    while (cls(gchar(&pos)) == cl_white) {
  386. X        /*
  387. X         * We'll stop if we land on a blank line
  388. X         */
  389. X        if (pos.p_index == 0 && pos.p_line->l_text[0] == '\0')
  390. X        break;
  391. X
  392. X        if (inc(&pos) == mv_NOMOVE) {
  393. X        /*
  394. X         * We have reached end of file; if we are at
  395. X         * the beginning of a line, just return that
  396. X         * position, otherwise try to back up so that
  397. X         * we are still within the line.
  398. X         */
  399. X        if (pos.p_index != 0) {
  400. X            (void) dec(&pos);
  401. X        }
  402. X        break;
  403. X        }
  404. X    }
  405. X
  406. X    /*
  407. X     * If we didn't move, return NULL.
  408. X     */
  409. X    if (pos.p_line == p->p_line && pos.p_index == p->p_index) {
  410. X        return(NULL);
  411. X    }
  412. X    }
  413. X
  414. X    return(&pos);
  415. X}
  416. X
  417. X/*
  418. X * bck_word(pos, type, skip_white) - move backward one word
  419. X *
  420. X * Returns the resulting position, or NULL if EOF was reached.
  421. X */
  422. X/*ARGSUSED*/
  423. XPosn *
  424. Xbck_word(p, type, skip_white)
  425. XPosn    *p;
  426. Xint    type;
  427. Xbool_t    skip_white;
  428. X{
  429. X    static    Posn    pos;
  430. X    cclass        sclass;        /* starting class */
  431. X
  432. X    stype = type;
  433. X    sclass = cls(gchar(p));
  434. X
  435. X    pos = *p;
  436. X
  437. X    if (dec(&pos) == mv_NOMOVE)
  438. X    return(NULL);
  439. X
  440. X    /*
  441. X     * If we're in the middle of a word, we just have to
  442. X     * back up to the start of it.
  443. X     */
  444. X    if (cls(gchar(&pos)) == sclass && sclass != cl_white) {
  445. X    /*
  446. X     * Move backward to start of the current word
  447. X     */
  448. X    while (cls(gchar(&pos)) == sclass) {
  449. X        if (dec(&pos) == mv_NOMOVE)
  450. X        return(&pos);
  451. X    }
  452. X    (void) inc(&pos);    /* overshot - forward one */
  453. X    return(&pos);
  454. X    }
  455. X
  456. X    /*
  457. X     * We were at the start of a word. Go back to the start
  458. X     * of the prior word.
  459. X     */
  460. X
  461. X    while (cls(gchar(&pos)) == cl_white) {    /* skip any white space */
  462. X    /*
  463. X     * We'll stop if we land on a blank line
  464. X     */
  465. X    if (pos.p_index == 0 && pos.p_line->l_text[0] == '\0')
  466. X        return(&pos);
  467. X
  468. X    if (dec(&pos) == mv_NOMOVE)
  469. X        return(&pos);
  470. X    }
  471. X
  472. X    sclass = cls(gchar(&pos));
  473. X
  474. X    /*
  475. X     * Move backward to start of this word.
  476. X     */
  477. X    while (cls(gchar(&pos)) == sclass) {
  478. X    if (dec(&pos) == mv_NOMOVE)
  479. X        return(&pos);
  480. X    }
  481. X    (void) inc(&pos);        /* overshot - forward one */
  482. X
  483. X    return(&pos);
  484. X}
  485. X
  486. X/*
  487. X * end_word(pos, type, skip_white) - move to the next end-of-word after
  488. X *                     the current cursor position
  489. X *
  490. X * There is an apparent bug in the 'e' motion of the real vi. At least
  491. X * on the System V Release 3 version for the 80386. Unlike 'b' and 'w',
  492. X * the 'e' motion crosses blank lines. When the real vi crosses a blank
  493. X * line in an 'e' motion, the cursor is placed on the FIRST character
  494. X * of the next non-blank line. The 'E' command, however, works correctly.
  495. X * Since this appears to be a bug, I have not duplicated it here.
  496. X *
  497. X * Returns the resulting position, or NULL if EOF was reached.
  498. X */
  499. X/*ARGSUSED*/
  500. XPosn *
  501. Xend_word(p, type, skip_white)
  502. XPosn    *p;
  503. Xint    type;
  504. Xbool_t    skip_white;
  505. X{
  506. X    static    Posn    pos;
  507. X    cclass        sclass;
  508. X
  509. X    stype = type;
  510. X    sclass = cls(gchar(p));
  511. X
  512. X    pos = *p;
  513. X
  514. X    if (inc(&pos) == mv_NOMOVE)
  515. X    return(NULL);
  516. X
  517. X    /*
  518. X     * If we're in the middle of a word, we just have to
  519. X     * move to the end of it.
  520. X     */
  521. X    if (cls(gchar(&pos)) == sclass && sclass != cl_white) {
  522. X    /*
  523. X     * Move forward to end of the current word
  524. X     */
  525. X    while (cls(gchar(&pos)) == sclass) {
  526. X        if (inc(&pos) == mv_NOMOVE) {
  527. X        return(&pos);
  528. X        }
  529. X    }
  530. X    (void) dec(&pos);        /* overshot - forward one */
  531. X    return(&pos);
  532. X    }
  533. X
  534. X    /*
  535. X     * We were at the end of a word. Go to the end
  536. X     * of the next word.
  537. X     */
  538. X
  539. X    while (cls(gchar(&pos)) == cl_white) {    /* skip any white space */
  540. X    if (inc(&pos) == mv_NOMOVE) {
  541. X        return(&pos);
  542. X    }
  543. X    }
  544. X
  545. X    sclass = cls(gchar(&pos));
  546. X
  547. X    /*
  548. X     * Move forward to end of this word.
  549. X     */
  550. X    while (cls(gchar(&pos)) == sclass) {
  551. X    if (inc(&pos) == mv_NOMOVE) {
  552. X        return(&pos);
  553. X    }
  554. X    }
  555. X    (void) dec(&pos);            /* overshot - forward one */
  556. X
  557. X    return(&pos);
  558. X}
  559. X
  560. X/*
  561. X * Search for the given pattern in the given buffer,
  562. X * in the direction specified.
  563. X */
  564. Xbool_t
  565. Xdosearch(window, str, cmd_char)
  566. XXviwin        *window;
  567. Xchar        *str;
  568. Xint        cmd_char;
  569. X{
  570. X    Posn    *p;
  571. X    unsigned    savecho;
  572. X    bool_t    retval;
  573. X    int        dir;
  574. X    static int    lastdir = FORWARD;
  575. X
  576. X    /*
  577. X     * Place the cursor at bottom left of the window,
  578. X     * so the user knows what we are doing.
  579. X     */
  580. X    gotocmd(window, FALSE);
  581. X
  582. X    switch (cmd_char) {
  583. X    case '/':
  584. X    lastdir = dir = FORWARD;
  585. X    break;
  586. X    case '?':
  587. X    lastdir = dir = BACKWARD;
  588. X    break;
  589. X    case 'n':
  590. X    dir = lastdir;
  591. X    break;
  592. X    case 'N':
  593. X    dir = (lastdir == FORWARD) ? BACKWARD : FORWARD;
  594. X    break;
  595. X    }
  596. X
  597. X    /*
  598. X     * It is safe not to put the cursor back, because
  599. X     * we are going to produce some more output anyway.
  600. X     */
  601. X
  602. X    savecho = echo;
  603. X
  604. X    p = search(window, window->w_cursor->p_line,
  605. X            window->w_cursor->p_index, dir, &str);
  606. X    if (p == NULL) {
  607. X    regerror("Pattern not found");
  608. X    retval = FALSE;
  609. X    } else if (*str != '\0') {
  610. X    regerror("Usage: /pattern or ?pattern");
  611. X    retval = FALSE;
  612. X    } else {
  613. X    setpcmark(window);
  614. X    move_cursor(window, p->p_line, p->p_index);
  615. X    window->w_set_want_col = TRUE;
  616. X    retval = TRUE;
  617. X    }
  618. X
  619. X    echo = savecho;
  620. X    return retval;
  621. X}
  622. END_OF_FILE
  623.   if test 12296 -ne `wc -c <'xvi/src/find.c'`; then
  624.     echo shar: \"'xvi/src/find.c'\" unpacked with wrong size!
  625.   fi
  626.   # end of 'xvi/src/find.c'
  627. fi
  628. if test -f 'xvi/src/movement.c' -a "${1}" != "-c" ; then 
  629.   echo shar: Will not clobber existing file \"'xvi/src/movement.c'\"
  630. else
  631.   echo shar: Extracting \"'xvi/src/movement.c'\" \(12825 characters\)
  632.   sed "s/^X//" >'xvi/src/movement.c' <<'END_OF_FILE'
  633. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  634. X#ifndef lint
  635. Xstatic char *sccsid = "@(#)movement.c    2.2 (Chris & John Downey) 9/1/92";
  636. X#endif
  637. X
  638. X/***
  639. X
  640. X* program name:
  641. X    xvi
  642. X* function:
  643. X    PD version of UNIX "vi" editor, with extensions.
  644. X* module name:
  645. X    movement.c
  646. X* module function:
  647. X    Movement of the cursor and the window into the buffer.
  648. X* history:
  649. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  650. X    Originally by Tim Thompson (twitch!tjt)
  651. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  652. X    Heavily modified by Chris & John Downey
  653. X
  654. X***/
  655. X
  656. X#include "xvi.h"
  657. X
  658. X/*
  659. X * Shift a buffer's contents down relative to its window,
  660. X * but don't change the display.
  661. X *
  662. X * Return number of physical lines shifted.
  663. X */
  664. Xint
  665. Xshiftdown(win, nlines)
  666. Xregister Xviwin    *win;
  667. Xunsigned    nlines;
  668. X{
  669. X    register unsigned    k;        /* loop counter */
  670. X    int            done = 0;    /* # of physical lines done */
  671. X
  672. X    for (k = 0; k < nlines; k++) {
  673. X    register Line    *p;
  674. X    register long    physlines;
  675. X
  676. X    /*
  677. X     * Set the top screen line to the previous one.
  678. X     */
  679. X    p = win->w_topline->l_prev;
  680. X    if (p == win->w_buffer->b_line0)
  681. X        break;
  682. X
  683. X    physlines = plines(win, p);
  684. X    done += LONG2INT(physlines);
  685. X
  686. X    win->w_topline = p;
  687. X    }
  688. X
  689. X    win->w_curs_new = TRUE;
  690. X
  691. X    return(done);
  692. X}
  693. X
  694. X/*
  695. X * Shift a buffer's contents up relative to its window,
  696. X * but don't change the display.
  697. X *
  698. X * Return number of physical lines shifted.
  699. X */
  700. Xint
  701. Xshiftup(win, nlines)
  702. Xregister Xviwin    *win;
  703. Xunsigned    nlines;
  704. X{
  705. X    register unsigned    k;        /* loop counter */
  706. X    int            done = 0;    /* # of physical lines done */
  707. X
  708. X    for (k = 0; k < nlines; k++) {
  709. X    register Line    *p;
  710. X    register long    physlines;
  711. X
  712. X    /*
  713. X     * Set the top screen line to the next one.
  714. X     */
  715. X    p = win->w_topline->l_next;
  716. X    if (p == win->w_buffer->b_lastline)
  717. X        break;
  718. X
  719. X    physlines = plines(win, win->w_topline);
  720. X    done += LONG2INT(physlines);
  721. X
  722. X    win->w_topline = p;
  723. X    }
  724. X
  725. X    win->w_curs_new = TRUE;
  726. X
  727. X    return(done);
  728. X}
  729. X
  730. X/*
  731. X * Scroll the screen down 'nlines' lines.
  732. X */
  733. Xvoid
  734. Xscrolldown(win, nlines)
  735. Xregister Xviwin    *win;
  736. Xunsigned    nlines;
  737. X{
  738. X    s_ins(win, 0, shiftdown(win, nlines));
  739. X}
  740. X
  741. X/*
  742. X * Scroll the screen up 'nlines' lines.
  743. X */
  744. Xvoid
  745. Xscrollup(win, nlines)
  746. Xregister Xviwin    *win;
  747. Xunsigned    nlines;
  748. X{
  749. X    s_del(win, 0, shiftup(win, nlines));
  750. X}
  751. X
  752. X/*
  753. X * oneup
  754. X * onedown
  755. X * one_left
  756. X * one_right
  757. X *
  758. X * Move cursor one char {left,right} or one line {up,down}.
  759. X *
  760. X * Return TRUE when successful, FALSE when we hit a boundary
  761. X * (of a line, or the file).
  762. X */
  763. X
  764. X/*
  765. X * Move the cursor up 'nlines' lines.
  766. X *
  767. X * Returns TRUE if we moved at all.
  768. X */
  769. Xbool_t
  770. Xoneup(win, nlines)
  771. Xregister Xviwin    *win;
  772. Xlong        nlines;
  773. X{
  774. X    Posn        *pp;
  775. X    register Line    *curr_line;
  776. X    long        k;
  777. X
  778. X    pp = win->w_cursor;
  779. X    curr_line = pp->p_line;
  780. X
  781. X    for (k = 0; k < nlines; k++) {
  782. X    /*
  783. X     * Look for the previous line.
  784. X     */
  785. X    if (curr_line == win->w_buffer->b_file) {
  786. X        /*
  787. X         * If we've at least backed up a little ...
  788. X         */
  789. X        if (k > 0) {
  790. X        break;    /* to update the cursor, etc. */
  791. X        } else {
  792. X        return(FALSE);
  793. X        }
  794. X    }
  795. X    curr_line = curr_line->l_prev;
  796. X    }
  797. X
  798. X    pp->p_line = curr_line;
  799. X    pp->p_index = 0;
  800. X    win->w_curs_new = TRUE;
  801. X
  802. X    /*
  803. X     * Try to advance to the column we want to be at.
  804. X     */
  805. X    coladvance(win, win->w_curswant);
  806. X    return(TRUE);
  807. X}
  808. X
  809. X/*
  810. X * Move the cursor down 'nlines' lines.
  811. X *
  812. X * Returns TRUE if we moved at all.
  813. X */
  814. Xbool_t
  815. Xonedown(win, nlines)
  816. Xregister Xviwin    *win;
  817. Xlong        nlines;
  818. X{
  819. X    Posn        *pp;
  820. X    register Line    *curr_line;
  821. X    long        k;
  822. X
  823. X    pp = win->w_cursor;
  824. X    curr_line = pp->p_line;
  825. X
  826. X    for (k = 0; k < nlines; k++) {
  827. X    /*
  828. X     * Look for the next line.
  829. X     */
  830. X    if (curr_line->l_next == win->w_buffer->b_lastline) {
  831. X        if (k > 0) {
  832. X        break;
  833. X        } else {
  834. X        return(FALSE);
  835. X        }
  836. X    }
  837. X    curr_line = curr_line->l_next;
  838. X    }
  839. X
  840. X    pp->p_line = curr_line;
  841. X    pp->p_index = 0;
  842. X    win->w_curs_new = TRUE;
  843. X
  844. X    /*
  845. X     * Try to advance to the column we want to be at.
  846. X     */
  847. X    coladvance(win, win->w_curswant);
  848. X
  849. X    return(TRUE);
  850. X}
  851. X
  852. X/*ARGSUSED*/
  853. Xbool_t
  854. Xone_left(window, unused)
  855. XXviwin    *window;
  856. Xbool_t    unused;
  857. X{
  858. X    Posn    *p;
  859. X
  860. X    window->w_set_want_col = TRUE;
  861. X    p = window->w_cursor;
  862. X
  863. X    if (p->p_index > 0) {
  864. X    p->p_index--;
  865. X    curs_horiz(window, -1);
  866. X    return(TRUE);
  867. X    } else {
  868. X    return(FALSE);
  869. X    }
  870. X}
  871. X
  872. X/*
  873. X * The move_past_end parameter will be TRUE if moving past the end
  874. X * of the line (onto the first '\0' character) is allowed. We will
  875. X * never move past this character.
  876. X */
  877. Xbool_t
  878. Xone_right(window, move_past_end)
  879. XXviwin    *window;
  880. Xbool_t    move_past_end;
  881. X{
  882. X    Posn    *p;
  883. X    char    *txtp;
  884. X
  885. X    window->w_set_want_col = TRUE;
  886. X    p = window->w_cursor;
  887. X    txtp = &p->p_line->l_text[p->p_index];
  888. X
  889. X    if (txtp[0] != '\0' && (move_past_end || txtp[1] != '\0')) {
  890. X    p->p_index++;
  891. X    curs_horiz(window, 1);
  892. X    return(TRUE);
  893. X    } else {
  894. X    return(FALSE);
  895. X    }
  896. X}
  897. X
  898. Xvoid
  899. Xbegin_line(window, flag)
  900. XXviwin    *window;
  901. Xbool_t    flag;
  902. X{
  903. X    register Posn    *pos;
  904. X    register int    c;
  905. X
  906. X    pos = window->w_cursor;
  907. X
  908. X    if (flag) {
  909. X    char        *startp;
  910. X    register char    *p;
  911. X
  912. X    startp = p = pos->p_line->l_text;
  913. X    while ((c = *p) != '\0' && p[1] != '\0' && is_space(c)) {
  914. X        p++;
  915. X    }
  916. X    pos->p_index = p - startp;
  917. X    } else {
  918. X    pos->p_index = 0;
  919. X    }
  920. X
  921. X    window->w_set_want_col = TRUE;
  922. X    window->w_curs_new = TRUE;
  923. X}
  924. X
  925. X/*
  926. X * coladvance(win, col)
  927. X *
  928. X * Try to advance to the specified column, starting at p.
  929. X */
  930. Xvoid
  931. Xcoladvance(win, col)
  932. Xregister Xviwin    *win;
  933. Xregister int    col;
  934. X{
  935. X    register int    c;
  936. X    register char    *tstart, *tp;
  937. X
  938. X    tp = tstart = win->w_cursor->p_line->l_text;
  939. X    /*
  940. X     * Try to advance to the specified column.
  941. X     */
  942. X    for (c = 0; c < col; ) {
  943. X    if (*tp == '\0') {
  944. X        /*
  945. X         * We're at the end of the line.
  946. X         */
  947. X        break;
  948. X    }
  949. X    c += vischar(*tp, (char **) NULL, (Pb(P_list) ? -1 : c));
  950. X
  951. X    tp++;
  952. X    }
  953. X
  954. X    /*
  955. X     * Move back onto last character if we have to.
  956. X     */
  957. X    if ((*tp == '\0' || c > col) && tp > tstart)
  958. X    --tp;
  959. X    win->w_cursor->p_index = tp - tstart;
  960. X    curwin->w_curs_new = TRUE;
  961. X}
  962. X
  963. X/*
  964. X * Go to the specified line number in the current buffer.
  965. X * Position the cursor at the first non-white.
  966. X */
  967. Xvoid
  968. Xdo_goto(line)
  969. Xlong line;
  970. X{
  971. X    curwin->w_cursor->p_line = gotoline(curbuf, line);
  972. X    curwin->w_cursor->p_index = 0;
  973. X    curwin->w_curs_new = TRUE;
  974. X    begin_line(curwin, TRUE);
  975. X}
  976. X
  977. X/*
  978. X * Move the cursor to the specified line, at the specified position.
  979. X */
  980. Xvoid
  981. Xmove_cursor(win, lp, index)
  982. XXviwin    *win;
  983. XLine    *lp;
  984. Xint    index;
  985. X{
  986. X    win->w_cursor->p_line = lp;
  987. X    win->w_cursor->p_index = index;
  988. X    win->w_curs_new = TRUE;
  989. X}
  990. X
  991. X/*
  992. X * Adjust window so that currline is, as far as possible, in the
  993. X * middle of it.
  994. X *
  995. X * Don't update the screen: move_window_to_cursor() does that.
  996. X */
  997. Xstatic void
  998. Xjump(win, currline, halfwinsize)
  999. XXviwin        *win;
  1000. XLine        *currline;
  1001. Xint        halfwinsize;
  1002. X{
  1003. X    register int    count;
  1004. X    register int    spare;
  1005. X    register Line    *topline;
  1006. X    register Line    *filestart = win->w_buffer->b_file;
  1007. X
  1008. X    spare = win->w_nrows - (unsigned int) plines(win, topline = currline) - 1;
  1009. X    for (count = 0; count < halfwinsize && topline != filestart;) {
  1010. X    topline = topline->l_prev;
  1011. X    count += (unsigned int) plines(win, topline);
  1012. X    if (count >= spare) {
  1013. X        if (count > spare)
  1014. X        topline = topline->l_next;
  1015. X        break;
  1016. X    }
  1017. X    }
  1018. X    win->w_topline = topline;
  1019. X    update_buffer(win->w_buffer);
  1020. X
  1021. X    /*
  1022. X     * The result of calling show_file_info here is that if the
  1023. X     * cursor moves a long away - e.g. for a "G" command or a search
  1024. X     * - the status line is updated with the correct line number.
  1025. X     * This is a small cost compared to updating the whole window.
  1026. X     */
  1027. X    show_file_info(win);
  1028. X}
  1029. X
  1030. X/*
  1031. X * Update the position of the window relative to the buffer, moving
  1032. X * the window if necessary to ensure that the cursor is inside the
  1033. X * window boundary. w_topline, w_botline and w_cursor must be set to
  1034. X * something reasonable for us to be able to test whether the cursor
  1035. X * is in the window or not, unless (as a special case) the buffer is
  1036. X * empty - in this case, the cursor sits at top left, despite there
  1037. X * being no character there for it to sit on.
  1038. X *
  1039. X * If we have to move the window only a small amount, we try to scroll
  1040. X * it rather than redrawing. If we have to redraw, we also rewrite the
  1041. X * status line on the principle that it's probably a negligible cost
  1042. X * compared to updating the whole window.
  1043. X */
  1044. Xvoid
  1045. Xmove_window_to_cursor(win)
  1046. Xregister Xviwin        *win;
  1047. X{
  1048. X    register Line    *currline;
  1049. X    int            halfwinsize;
  1050. X    long        distance;
  1051. X
  1052. X    currline = win->w_cursor->p_line;
  1053. X    halfwinsize = (win->w_nrows - 1) / 2;
  1054. X
  1055. X    /*
  1056. X     * First stage: move window towards cursor.
  1057. X     */
  1058. X    if (bufempty(win->w_buffer)) {
  1059. X    /*
  1060. X     * Special case - file is empty.
  1061. X     */
  1062. X    win->w_topline = win->w_buffer->b_file;
  1063. X    win->w_cursor->p_line = win->w_buffer->b_file;
  1064. X    win->w_cursor->p_index = 0;
  1065. X    win->w_curs_new = TRUE;
  1066. X
  1067. X    } else if (earlier(currline, win->w_topline)) {
  1068. X    long    nlines;
  1069. X
  1070. X    /*
  1071. X     * The cursor is above the top of the window; move the
  1072. X     * window towards it.
  1073. X     */
  1074. X
  1075. X    nlines = cntplines(win, currline, win->w_topline);
  1076. X
  1077. X    /*
  1078. X     * Decide whether it's worthwhile - & possible - to
  1079. X     * scroll to get the window to the right place.
  1080. X     *
  1081. X     * It's possible if we can have scrolling regions, or
  1082. X     * we can insert screen lines & the window is at the
  1083. X     * bottom of the screen.
  1084. X     *
  1085. X     * The actual scrolling is done by s_ins(), in
  1086. X     * screen.c.
  1087. X     *
  1088. X     * If Pn(P_jumpscroll) is js_OFF, we don't use
  1089. X     * jumpscroll anyway.
  1090. X     */
  1091. X    if (
  1092. X        nlines > halfwinsize
  1093. X        ||
  1094. X        Pn(P_jumpscroll) == js_ON
  1095. X        ||
  1096. X        (
  1097. X        !can_scroll_area
  1098. X        &&
  1099. X        Pn(P_jumpscroll) == js_AUTO
  1100. X        &&
  1101. X        (
  1102. X            !can_ins_line
  1103. X            ||
  1104. X            win->w_cmdline < (Rows - 1)
  1105. X        )
  1106. X        )
  1107. X    ) {
  1108. X        jump(win, currline, halfwinsize);
  1109. X    } else {
  1110. X        s_ins(win, 0, (int) nlines);
  1111. X        win->w_topline = currline;
  1112. X        update_window(win);
  1113. X    }
  1114. X    } else {
  1115. X    long    nlines;
  1116. X
  1117. X    /*
  1118. X     * The cursor is on or after the last line of the screen,
  1119. X     * so we might have to move the screen to it. Check to see
  1120. X     * whether we are actually off the screen; if not, we don't
  1121. X     * have to do anything. We do this in a certain way so as
  1122. X     * not to do any unnecessary calculations; this routine is
  1123. X     * called very often, so we must not take too much time.
  1124. X     */
  1125. X    if (earlier(currline, win->w_botline->l_prev) ||
  1126. X                (plines(win, currline) == 1 &&
  1127. X                 earlier(currline, win->w_botline))) {
  1128. X        return;
  1129. X    }
  1130. X    distance = cntplines(win, win->w_topline, currline->l_next);
  1131. X    if (distance <= win->w_nrows - 1) {
  1132. X        return;
  1133. X    }
  1134. X
  1135. X    /*
  1136. X     * The cursor is off the bottom of the window, or the
  1137. X     * line the cursor is on won't completely fit in the
  1138. X     * window.
  1139. X     */
  1140. X
  1141. X    nlines = distance - (win->w_nrows - 1);
  1142. X
  1143. X    /*
  1144. X     * Decide whether it's worthwhile - & possible - to
  1145. X     * scroll to get the window to the right place.
  1146. X     *
  1147. X     * It's possible if we can have scrolling regions, or
  1148. X     * we can delete screen lines & the window is at the
  1149. X     * bottom of the screen, or it's the only window on
  1150. X     * the screen.
  1151. X     *
  1152. X     * The actual scrolling is done by s_del(), in
  1153. X     * screen.c.
  1154. X     *
  1155. X     * If Pn(P_jumpscroll) is js_OFF, we don't use
  1156. X     * jumpscroll anyway.
  1157. X     */
  1158. X    if (
  1159. X        nlines > halfwinsize
  1160. X        ||
  1161. X        Pn(P_jumpscroll) == js_ON
  1162. X        ||
  1163. X        (
  1164. X        !can_scroll_area
  1165. X        &&
  1166. X        Pn(P_jumpscroll) == js_AUTO
  1167. X        &&
  1168. X        (
  1169. X            (
  1170. X            !can_del_line
  1171. X            &&
  1172. X            win->w_winpos != 0
  1173. X            )
  1174. X            ||
  1175. X            win->w_cmdline < (Rows - 1)
  1176. X        )
  1177. X        )
  1178. X    ) {
  1179. X        jump(win, currline, halfwinsize);
  1180. X    } else {
  1181. X        long    done = 0;
  1182. X        Line    *l;
  1183. X        Line    *newtopline;
  1184. X
  1185. X        /*
  1186. X         * Work out where we should place topline in
  1187. X         * order that the cursor line is made the
  1188. X         * bottom line of the screen.
  1189. X         */
  1190. X        for (l = currline;; l = l->l_prev) {
  1191. X        done += plines(win, l);
  1192. X        if (done >= win->w_nrows - 1)
  1193. X            break;
  1194. X        if (l == win->w_buffer->b_file)
  1195. X            break;
  1196. X        }
  1197. X        while (done > win->w_nrows - 1 && l != currline) {
  1198. X        done -= plines(win, l);
  1199. X        l = l->l_next;
  1200. X        }
  1201. X        newtopline = l;
  1202. X
  1203. X        /*
  1204. X         * Now work out how many screen lines we want
  1205. X         * to scroll the window by. This code assumes
  1206. X         * that the old value of topline is earlier
  1207. X         * in the buffer than the new, so check this
  1208. X         * first.
  1209. X         */
  1210. X        if (earlier(win->w_topline, newtopline)) {
  1211. X        done = cntplines(win, win->w_topline, newtopline);
  1212. X
  1213. X        if (done != 0) {
  1214. X            s_del(win, 0, (int) done);
  1215. X        }
  1216. X        }
  1217. X
  1218. X        win->w_topline = newtopline;
  1219. X        update_window(win);
  1220. X    }
  1221. X    }
  1222. X}
  1223. X
  1224. X/*
  1225. X * Make sure the cursor is within the given window.
  1226. X *
  1227. X * This is needed for commands like control-E & control-Y.
  1228. X */
  1229. Xvoid
  1230. Xmove_cursor_to_window(win)
  1231. XXviwin        *win;
  1232. X{
  1233. X    Posn    *cp;
  1234. X
  1235. X    cp = win->w_cursor;
  1236. X
  1237. X    if (earlier(cp->p_line, win->w_topline)) {
  1238. X    cp->p_line = win->w_topline;
  1239. X    coladvance(win, win->w_curswant);
  1240. X    } else if (!earlier(cp->p_line, win->w_botline)
  1241. X           && earlier(win->w_topline, win->w_botline)) {
  1242. X    cp->p_line = win->w_botline->l_prev;
  1243. X    coladvance(win, win->w_curswant);
  1244. X    }
  1245. X    win->w_curs_new = TRUE;
  1246. X}
  1247. END_OF_FILE
  1248.   if test 12825 -ne `wc -c <'xvi/src/movement.c'`; then
  1249.     echo shar: \"'xvi/src/movement.c'\" unpacked with wrong size!
  1250.   fi
  1251.   # end of 'xvi/src/movement.c'
  1252. fi
  1253. if test -f 'xvi/src/qnx.c' -a "${1}" != "-c" ; then 
  1254.   echo shar: Will not clobber existing file \"'xvi/src/qnx.c'\"
  1255. else
  1256.   echo shar: Extracting \"'xvi/src/qnx.c'\" \(13461 characters\)
  1257.   sed "s/^X//" >'xvi/src/qnx.c' <<'END_OF_FILE'
  1258. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1259. X#ifndef lint
  1260. Xstatic char *sccsid = "@(#)qnx.c    2.2 (Chris & John Downey) 8/7/92";
  1261. X#endif
  1262. X
  1263. X/***
  1264. X
  1265. X* program name:
  1266. X    xvi
  1267. X* function:
  1268. X    PD version of UNIX "vi" editor, with extensions.
  1269. X* module name:
  1270. X    qnx.c
  1271. X* module function:
  1272. X    QNX system interface module.
  1273. X
  1274. X    Note that this module assumes the C86 compiler,
  1275. X    which is an ANSI compiler, rather than the standard
  1276. X    QNX compiler, which is not.
  1277. X
  1278. X* history:
  1279. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  1280. X    Originally by Tim Thompson (twitch!tjt)
  1281. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  1282. X    Heavily modified by Chris & John Downey
  1283. X
  1284. X***/
  1285. X
  1286. X/*
  1287. X * QNX-specific include files.
  1288. X *
  1289. X * <stdio.h> etc. get included by "xvi.h".
  1290. X */
  1291. X#include <io.h>
  1292. X#include <dev.h>
  1293. X#include <sys/stat.h>
  1294. X#include <timer.h>
  1295. X#include <tcap.h>
  1296. X#include <tcapkeys.h>
  1297. X#include <taskmsgs.h>
  1298. X
  1299. X#include "xvi.h"
  1300. X
  1301. X#define    PIPE_MASK_1    "/tmp/xvipipe1XXXXXX"
  1302. X#define    PIPE_MASK_2    "/tmp/xvipipe2XXXXXX"
  1303. X#define    EXPAND_MASK    "/tmp/xvexpandXXXXXX"
  1304. X
  1305. Xextern    int        tcap_row;
  1306. Xextern    int        tcap_col;
  1307. X
  1308. Xint            can_scroll_area;
  1309. Xvoid            (*up_func)(int, int, int);
  1310. Xvoid            (*down_func)(int, int, int);
  1311. X
  1312. Xstatic    int        disp_inited = 0;
  1313. Xstatic    unsigned    screen_colour = DEF_COLOUR;
  1314. Xstatic    int        old_options;
  1315. X
  1316. Xstatic    bool_t        triggered;
  1317. X
  1318. Xstatic void
  1319. Xcatch_usr1(i)
  1320. Xint    i;
  1321. X{
  1322. X    (void) signal(SIGUSR1, SIG_IGN);
  1323. X    triggered = TRUE;
  1324. X}
  1325. X
  1326. X/*
  1327. X * inchar() - get a character from the keyboard
  1328. X */
  1329. Xint
  1330. Xinchar(timeout)
  1331. Xlong    timeout;
  1332. X{
  1333. X    register int    c;
  1334. X    bool_t        setsignal = FALSE;
  1335. X
  1336. X    /*
  1337. X     * Set a timeout on input if asked to do so.
  1338. X     */
  1339. X    if (timeout != 0) {
  1340. X    /*
  1341. X     * Timeout value is in milliseconds, so we have to convert
  1342. X     * to 50 millisecond ticks, rounding up as we do it.
  1343. X     */
  1344. X    (void) signal(SIGUSR1, catch_usr1);
  1345. X    (void) set_timer(TIMER_SET_EXCEPTION, RELATIVE,
  1346. X            (int) ((timeout + 19) / 20),
  1347. X            SIGUSR1,
  1348. X            (char *) NULL);
  1349. X    setsignal = TRUE;
  1350. X    }
  1351. X
  1352. X    flush_output();
  1353. X    for (;;) {
  1354. X    triggered = FALSE;
  1355. X
  1356. X    c = term_key();
  1357. X
  1358. X    if (triggered) {
  1359. X        return(EOF);
  1360. X    }
  1361. X
  1362. X    if (c > 127) {
  1363. X        /*
  1364. X         * Must be a function key press.
  1365. X         */
  1366. X
  1367. X        if (State != NORMAL) {
  1368. X        /*
  1369. X         * Function key pressed during insert
  1370. X         * or command line mode.
  1371. X         */
  1372. X        alert();
  1373. X        continue;
  1374. X        }
  1375. X
  1376. X        switch (c) {
  1377. X        case KEY_F1: /* F1 key */
  1378. X        c = K_HELP;
  1379. X        break;
  1380. X        case KEY_HOME:
  1381. X        c = 'H';
  1382. X        break;
  1383. X        case KEY_END:
  1384. X        c = 'L';
  1385. X        break;
  1386. X        case KEY_PAGE_UP:
  1387. X        c = CTRL('B');
  1388. X        break;
  1389. X        case KEY_PAGE_DOWN:
  1390. X        c = CTRL('F');
  1391. X        break;
  1392. X        case KEY_UP:
  1393. X        c = K_UARROW;
  1394. X        break;
  1395. X        case KEY_LEFT:
  1396. X        c = K_LARROW;
  1397. X        break;
  1398. X        case KEY_RIGHT:
  1399. X        c = K_RARROW;
  1400. X        break;
  1401. X        case KEY_DOWN:
  1402. X        c = K_DARROW;
  1403. X        break;
  1404. X        case KEY_WORD_LEFT:
  1405. X        c = 'b';
  1406. X        break;
  1407. X        case KEY_WORD_RIGHT:
  1408. X        c = 'w';
  1409. X        break;
  1410. X        case KEY_INSERT:
  1411. X        c = 'i';
  1412. X        break;
  1413. X        case KEY_DELETE:
  1414. X        c = 'x';
  1415. X        break;
  1416. X        case KEY_RUBOUT:
  1417. X        c = '\b';
  1418. X        break;
  1419. X        case KEY_TAB:
  1420. X        c = '\t';
  1421. X        break;
  1422. X        }
  1423. X    }
  1424. X    if (setsignal)
  1425. X        (void) signal(SIGUSR1, SIG_IGN);
  1426. X    return(c);
  1427. X    }
  1428. X    /*NOTREACHED*/
  1429. X}
  1430. X
  1431. Xvoid
  1432. Xsys_init()
  1433. X{
  1434. X    if (!disp_inited) {
  1435. X    term_load(stdin);
  1436. X    term_video_on();
  1437. X    }
  1438. X    if (strcmp(tcap_entry.term_name, "qnx") == 0) {
  1439. X    up_func = co_up;
  1440. X    down_func = co_down;
  1441. X    can_scroll_area = TRUE;
  1442. X    } else if (strncmp(tcap_entry.term_name, "vt100", 5) == 0) {
  1443. X    up_func = vt_up;
  1444. X    down_func = vt_down;
  1445. X    can_scroll_area = TRUE;
  1446. X    } else {
  1447. X    can_scroll_area = FALSE;
  1448. X    }
  1449. X
  1450. X    /*
  1451. X     * Support different number of rows for VGA text modes.
  1452. X     */
  1453. X    if (tcap_entry.term_type == VIDEO_MAPPED) {
  1454. X    unsigned    console;
  1455. X    unsigned    row_col;
  1456. X
  1457. X    console = fdevno(stdout);
  1458. X    row_col = video_get_size(console);
  1459. X    Rows = (row_col >> 8) & 0xff;
  1460. X    Columns = row_col & 0xff;
  1461. X    }
  1462. X
  1463. X    sys_startv();
  1464. X    disp_inited = 1;
  1465. X}
  1466. X
  1467. Xstatic    int        pcmode;            /* display mode */
  1468. X
  1469. Xvoid
  1470. Xsys_exit(r)
  1471. Xint    r;
  1472. X{
  1473. X    if (disp_inited) {
  1474. X    term_cur(Rows - 1, 0);
  1475. X    sys_endv();
  1476. X    }
  1477. X    exit(r);
  1478. X}
  1479. X
  1480. X/*
  1481. X * Returns TRUE if file does not exist or exists and is writeable.
  1482. X */
  1483. Xbool_t
  1484. Xcan_write(file)
  1485. Xchar    *file;
  1486. X{
  1487. X    return(access(file, W_OK) == 0 || access(file, F_OK) != 0);
  1488. X}
  1489. X
  1490. Xbool_t
  1491. Xexists(file)
  1492. Xchar *file;
  1493. X{
  1494. X    return(access(file, F_OK) == 0);
  1495. X}
  1496. X
  1497. X/*
  1498. X * Scroll an area on the console screen up by nlines.
  1499. X * The number of lines is always positive, and
  1500. X * we can assume we will not be called with
  1501. X * parameters which would result in scrolling
  1502. X * the entire window.
  1503. X *
  1504. X * Note that this routine will not be called unless
  1505. X * can_scroll_area is TRUE, which is only the case
  1506. X * for the console screen (i.e. term_name == "qnx").
  1507. X */
  1508. Xvoid
  1509. Xco_up(start, end, nlines)
  1510. Xint    start, end, nlines;
  1511. X{
  1512. X    char    *buf;
  1513. X    int        i;
  1514. X
  1515. X    buf = malloc((unsigned) Columns * term_save_image(0, 0, NULL, 0));
  1516. X    if (buf == NULL)
  1517. X    return;
  1518. X
  1519. X    for (i = start; i <= end - nlines; i++) {
  1520. X    term_save_image(i + nlines, 0, buf, Columns);
  1521. X    term_restore_image(i, 0, buf, Columns);
  1522. X    }
  1523. X
  1524. X    for ( ; i <= end; i++) {
  1525. X    term_cur(i, 0);
  1526. X    term_clear(_CLS_EOL);
  1527. X    }
  1528. X
  1529. X    free(buf);
  1530. X}
  1531. X
  1532. X/*
  1533. X * Scroll an area on the console screen down by nlines.
  1534. X * The number of lines is always positive, and
  1535. X * we can assume we will not be called with
  1536. X * parameters which would result in scrolling
  1537. X * the entire window.
  1538. X *
  1539. X * Note that this routine will not be called unless
  1540. X * can_scroll_area is TRUE, which is only the case
  1541. X * for the console screen (i.e. term_name == "qnx").
  1542. X */
  1543. Xvoid
  1544. Xco_down(start, end, nlines)
  1545. Xint    start, end, nlines;
  1546. X{
  1547. X    char    *buf;
  1548. X    int        i;
  1549. X
  1550. X    buf = malloc((unsigned) Columns * term_save_image(0, 0, NULL, 0));
  1551. X    if (buf == NULL)
  1552. X    return;
  1553. X
  1554. X    for (i = end; i >= start + nlines; --i) {
  1555. X    term_save_image(i - nlines, 0, buf, Columns);
  1556. X    term_restore_image(i, 0, buf, Columns);
  1557. X    }
  1558. X
  1559. X    for ( ; i >= start; --i) {
  1560. X    term_cur(i, 0);
  1561. X    term_clear(_CLS_EOL);
  1562. X    }
  1563. X
  1564. X    free(buf);
  1565. X}
  1566. X
  1567. X/*
  1568. X * Scroll an area on a vt100 terminal screen up by nlines.
  1569. X * The number of lines is always positive, and we can assume
  1570. X * we will not be called with parameters which would result
  1571. X * in scrolling the entire window.
  1572. X */
  1573. Xvoid
  1574. Xvt_up(start, end, nlines)
  1575. Xint    start, end, nlines;
  1576. X{
  1577. X    int        count;
  1578. X
  1579. X    (void) printf("\0337");                /* save cursor */
  1580. X    (void) printf("\033[%d;%dr", start + 1, end + 1);    /* set scroll region */
  1581. X    (void) printf("\033[%d;1H", end + 1);        /* goto bottom left */
  1582. X    for (count = 0; count < nlines; count++) {
  1583. X    putchar('\n');
  1584. X    }
  1585. X    (void) printf("\033[1;%dr", Rows);            /* set scroll region */
  1586. X    (void) printf("\0338");                /* restore cursor */
  1587. X}
  1588. X
  1589. X/*
  1590. X * Scroll an area on a vt100 terminal screen down by nlines.
  1591. X * The number of lines is always positive, and we can assume
  1592. X * we will not be called with parameters which would result
  1593. X * in scrolling the entire window.
  1594. X */
  1595. Xvoid
  1596. Xvt_down(start, end, nlines)
  1597. Xint    start, end, nlines;
  1598. X{
  1599. X    int        count;
  1600. X
  1601. X    (void) printf("\0337");                /* save cursor */
  1602. X    (void) printf("\033[%d;%dr", start + 1, end + 1);    /* set scroll region */
  1603. X    (void) printf("\033[%d;1H", start + 1);        /* goto top left */
  1604. X    for (count = 0; count < nlines; count++) {
  1605. X    fputs("\033[L", stdout);
  1606. X    }
  1607. X    (void) printf("\033[1;%dr", Rows);            /* set scroll region */
  1608. X    (void) printf("\0338");                /* restore cursor */
  1609. X}
  1610. X
  1611. Xint
  1612. Xcall_shell(sh)
  1613. Xchar    *sh;
  1614. X{
  1615. X    return(spawnlp(0, sh, sh, (char *) NULL));
  1616. X}
  1617. X
  1618. Xvoid
  1619. Xalert()
  1620. X{
  1621. X    putchar('\007');
  1622. X}
  1623. X
  1624. Xvoid
  1625. Xdelay()
  1626. X{
  1627. X    (void) set_timer(TIMER_WAKEUP, RELATIVE, 2, 0, NULL);
  1628. X}
  1629. X
  1630. Xvoid
  1631. Xoutchar(c)
  1632. Xint    c;
  1633. X{
  1634. X    char    cbuf[2];
  1635. X
  1636. X    cbuf[0] = c;
  1637. X    cbuf[1] = '\0';
  1638. X    outstr(cbuf);
  1639. X}
  1640. X
  1641. Xvoid
  1642. Xoutstr(s)
  1643. Xchar    *s;
  1644. X{
  1645. X    term_type(-1, -1, s, 0, screen_colour);
  1646. X}
  1647. X
  1648. Xvoid
  1649. Xflush_output()
  1650. X{
  1651. X    (void) fflush(stdout);
  1652. X}
  1653. X
  1654. Xvoid
  1655. Xset_colour(c)
  1656. Xint    c;
  1657. X{
  1658. X    screen_colour = (unsigned) c;
  1659. X    term_colour(screen_colour >> 8);
  1660. X}
  1661. X
  1662. Xvoid
  1663. Xtty_goto(r, c)
  1664. Xint    r, c;
  1665. X{
  1666. X    term_cur(r, c);
  1667. X}
  1668. X
  1669. Xvoid
  1670. Xsys_startv()
  1671. X{
  1672. X    /*
  1673. X     * Turn off:
  1674. X     *    EDIT    to get "raw" mode
  1675. X     *    ECHO    to stop characters being echoed
  1676. X     *    MAPCR    to stop mapping of \r into \n
  1677. X     */
  1678. X    old_options = get_option(stdin);
  1679. X    set_option(stdin, old_options & ~(EDIT | ECHO | MAPCR));
  1680. X}
  1681. X
  1682. Xvoid
  1683. Xsys_endv()
  1684. X{
  1685. X    term_cur(Rows - 1, 0);
  1686. X    set_colour(Pn(P_systemcolour));
  1687. X    erase_line();
  1688. X    flush_output();
  1689. X
  1690. X    /*
  1691. X     * This flushes the typeahead buffer so that recall of previous
  1692. X     * commands will not work - this is desirable because some of
  1693. X     * the commands typed to vi (i.e. control characters) will
  1694. X     * have a deleterious effect if given to the shell.
  1695. X     */
  1696. X    flush_input(stdin);
  1697. X
  1698. X    set_option(stdin, old_options);
  1699. X}
  1700. X
  1701. X/*
  1702. X * Construct unique name for temporary file,
  1703. X * to be used as a backup file for the named file.
  1704. X */
  1705. Xchar *
  1706. Xtempfname(srcname)
  1707. Xchar    *srcname;
  1708. X{
  1709. X    char    *newname;        /* ptr to allocated new pathname */
  1710. X    char    *last_slash;        /* ptr to last slash in srcname */
  1711. X    char    *last_hat;        /* ptr to last slash in srcname */
  1712. X    int        tail_length;        /* length of last component */
  1713. X    int        head_length;        /* length up to (including) '/' */
  1714. X
  1715. X    /*
  1716. X     * Obtain the length of the last component of srcname.
  1717. X     */
  1718. X    last_slash = strrchr(srcname, '/');
  1719. X    last_hat = strrchr(srcname, '^');
  1720. X    if ((last_slash == NULL) ||
  1721. X    (last_slash != NULL && last_hat != NULL && last_hat > last_slash)) {
  1722. X    last_slash = last_hat;
  1723. X    }
  1724. X
  1725. X    /*
  1726. X     * last_slash now points at the last delimiter in srcname,
  1727. X     * or is NULL if srcname contains no delimiters.
  1728. X     */
  1729. X    if (last_slash != NULL) {
  1730. X    tail_length = strlen(last_slash + 1);
  1731. X    head_length = last_slash - srcname;
  1732. X    } else {
  1733. X    tail_length = strlen(srcname);
  1734. X    head_length = 0;
  1735. X    }
  1736. X
  1737. X    /*
  1738. X     * We want to add ".tmp" onto the end of the name,
  1739. X     * and QNX restricts filenames to 16 characters.
  1740. X     * So we must ensure that the last component
  1741. X     * of the pathname is not more than 12 characters
  1742. X     * long, or truncate it so it isn't.
  1743. X     */
  1744. X    if (tail_length > 12)
  1745. X    tail_length = 12;
  1746. X
  1747. X    /*
  1748. X     * Create the new pathname. We need the total length
  1749. X     * of the path as is, plus ".tmp" plus a null byte.
  1750. X     */
  1751. X    newname = alloc(head_length + tail_length + 5);
  1752. X    if (newname != NULL) {
  1753. X    (void) strncpy(newname, srcname, head_length + tail_length);
  1754. X    }
  1755. X
  1756. X    {
  1757. X    char    *endp;
  1758. X    int    indexnum;
  1759. X
  1760. X    endp = newname + head_length + tail_length;
  1761. X    indexnum = 0;
  1762. X    do {
  1763. X        /*
  1764. X         * Keep trying this until we get a unique file name.
  1765. X         */
  1766. X        if (indexnum > 0) {
  1767. X        (void) sprintf(endp, ".%03d", indexnum);
  1768. X        } else {
  1769. X        (void) strcpy(endp, ".tmp");
  1770. X        }
  1771. X        indexnum++;
  1772. X    } while (access(newname, 0) == 0 && indexnum < 1000);
  1773. X    }
  1774. X
  1775. X    return(newname);
  1776. X}
  1777. X
  1778. X/*
  1779. X * Fake out a pipe by writing output to temp file, running a process with
  1780. X * i/o redirected from this file to another temp file, and then reading
  1781. X * the second temp file back in.
  1782. X */
  1783. Xbool_t
  1784. Xsys_pipe(cmd, writefunc, readfunc)
  1785. Xchar    *cmd;
  1786. Xint    (*writefunc) P((FILE *));
  1787. Xlong    (*readfunc) P((FILE *));
  1788. X{
  1789. X    Flexbuf        cmdbuf;
  1790. X    static char    *args[] = { NULL, "+s", NULL, NULL };
  1791. X    char        *temp1;
  1792. X    char        *temp2;
  1793. X    char        buffer[512];
  1794. X    FILE        *fp;
  1795. X    bool_t        retval = FALSE;
  1796. X
  1797. X    if (Ps(P_shell) == NULL) {
  1798. X    return(FALSE);
  1799. X    }
  1800. X    args[0] = Ps(P_shell);
  1801. X
  1802. X    temp1 = mktemp(PIPE_MASK_1);
  1803. X    temp2 = mktemp(PIPE_MASK_2);
  1804. X
  1805. X    if (temp1 == NULL || temp2 == NULL) {
  1806. X    return(FALSE);
  1807. X    }
  1808. X
  1809. X    /*
  1810. X     * At this stage we are comitted; any failures must go through
  1811. X     * the cleanup code at the end of the routine.
  1812. X     */
  1813. X
  1814. X    sys_endv();
  1815. X
  1816. X    flexnew(&cmdbuf);
  1817. X    (void) lformat(&cmdbuf, "%s < %s > %s", cmd, temp1, temp2);
  1818. X    args[2] = flexgetstr(&cmdbuf);
  1819. X
  1820. X    fp = fopen(temp1, "w+");
  1821. X    if (fp == NULL) {
  1822. X    retval = FALSE;
  1823. X    goto ret;
  1824. X    }
  1825. X
  1826. X    (void) (*writefunc)(fp);
  1827. X    (void) fclose(fp);
  1828. X
  1829. X    if (createv(buffer, 0, -1, 0, BEQUEATH_TTY, 0, args, NULL) != 0) {
  1830. X    retval = FALSE;
  1831. X    goto ret;
  1832. X    }
  1833. X
  1834. X    fp = fopen(temp2, "r");
  1835. X    if (fp == NULL) {
  1836. X    retval = FALSE;
  1837. X    goto ret;
  1838. X    }
  1839. X
  1840. X    (void) (*readfunc)(fp);
  1841. X    (void) fclose(fp);
  1842. X
  1843. X    retval = TRUE;
  1844. X
  1845. Xret:
  1846. X    flexdelete(&cmdbuf);
  1847. X
  1848. X    (void) remove(temp1);
  1849. X    (void) remove(temp2);
  1850. X    free(temp1);
  1851. X    free(temp2);
  1852. X
  1853. X    sys_startv();
  1854. X
  1855. X    return(retval);
  1856. X}
  1857. X
  1858. X/*
  1859. X * Expand filename.
  1860. X * Have to do this using the shell, using a /tmp filename in the vain
  1861. X * hope that it will be on a ramdisk and hence reasonably fast.
  1862. X */
  1863. Xchar *
  1864. Xfexpand(name)
  1865. Xchar    *name;
  1866. X{
  1867. X    static char    meta[] = "*?";
  1868. X    int        has_meta;
  1869. X    static char    *args[] = { NULL, "+s", NULL, NULL };
  1870. X    static char    *io[4];
  1871. X    Flexbuf    cmdbuf;
  1872. X    char    *temp = NULL;
  1873. X    FILE    *fp;
  1874. X    static char    newname[256];
  1875. X    char    *cp;
  1876. X
  1877. X    if (name == NULL || *name == '\0') {
  1878. X    return(name);
  1879. X    }
  1880. X
  1881. X    has_meta = FALSE;
  1882. X    for (cp = meta; *cp != '\0'; cp++) {
  1883. X    if (strchr(name, *cp) != NULL) {
  1884. X        has_meta = TRUE;
  1885. X        break;
  1886. X    }
  1887. X    }
  1888. X    if (!has_meta) {
  1889. X    return(name);
  1890. X    }
  1891. X
  1892. X    if (Ps(P_shell) == NULL) {
  1893. X    goto fail;
  1894. X    }
  1895. X    args[0] = Ps(P_shell);
  1896. X
  1897. X    temp = mktemp(EXPAND_MASK);
  1898. X
  1899. X    if (temp == NULL) {
  1900. X    goto fail;
  1901. X    }
  1902. X
  1903. X    flexnew(&cmdbuf);
  1904. X    (void) lformat(&cmdbuf, "echo %s > %s", name, temp);
  1905. X    args[2] = flexgetstr(&cmdbuf);
  1906. X
  1907. X    io[0] = io[1] = io[2] = "$tty99";
  1908. X    if (createv(NULL, 0, -1, 0, 0, 0, args, NULL) != 0) {
  1909. X    goto fail;
  1910. X    }
  1911. X    flexdelete(&cmdbuf);
  1912. X
  1913. X    fp = fopen(temp, "r");
  1914. X    if (fp == NULL) {
  1915. X    goto fail;
  1916. X    }
  1917. X
  1918. X    if (fgets(newname, sizeof(newname), fp) == NULL) {
  1919. X    (void) fclose(fp);
  1920. X    goto fail;
  1921. X    }
  1922. X    cp = strchr(newname, '\n');
  1923. X    if (cp != NULL) {
  1924. X    *cp = '\0';
  1925. X    }
  1926. X
  1927. X    (void) fclose(fp);
  1928. X    (void) remove(temp);
  1929. X    free(temp);
  1930. X
  1931. X    return(newname);
  1932. X    
  1933. Xfail:
  1934. X    if (temp != NULL) {
  1935. X    free(temp);
  1936. X    }
  1937. X    return(name);
  1938. X}
  1939. END_OF_FILE
  1940.   if test 13461 -ne `wc -c <'xvi/src/qnx.c'`; then
  1941.     echo shar: \"'xvi/src/qnx.c'\" unpacked with wrong size!
  1942.   fi
  1943.   # end of 'xvi/src/qnx.c'
  1944. fi
  1945. if test -f 'xvi/src/regmagic.h' -a "${1}" != "-c" ; then 
  1946.   echo shar: Will not clobber existing file \"'xvi/src/regmagic.h'\"
  1947. else
  1948.   echo shar: Extracting \"'xvi/src/regmagic.h'\" \(706 characters\)
  1949.   sed "s/^X//" >'xvi/src/regmagic.h' <<'END_OF_FILE'
  1950. X/***
  1951. X
  1952. X* @(#)regmagic.h    2.1 7/29/92
  1953. X
  1954. X* program name:
  1955. X    xvi
  1956. X* function:
  1957. X    PD version of UNIX "vi" editor, with extensions.
  1958. X* module name:
  1959. X    regmagic.h
  1960. X* module function:
  1961. X    Definition of magic number for regular expression routines.
  1962. X
  1963. X* history:
  1964. X    Regular expression routines by Henry Spencer.
  1965. X    Modfied for use with STEVIE (ST Editor for VI Enthusiasts,
  1966. X     Version 3.10) by Tony Andrews.
  1967. X    Adapted for use with Xvi by Chris & John Downey.
  1968. X    Original copyright notice is in regexp.c.
  1969. X    Please note that this is a modified version.
  1970. X***/
  1971. X
  1972. X/*
  1973. X * The first byte of the regexp internal "program" is actually this magic
  1974. X * number; the start node begins in the second byte.
  1975. X */
  1976. X#define    MAGIC    0234
  1977. END_OF_FILE
  1978.   if test 706 -ne `wc -c <'xvi/src/regmagic.h'`; then
  1979.     echo shar: \"'xvi/src/regmagic.h'\" unpacked with wrong size!
  1980.   fi
  1981.   # end of 'xvi/src/regmagic.h'
  1982. fi
  1983. if test -f 'xvi/src/yankput.c' -a "${1}" != "-c" ; then 
  1984.   echo shar: Will not clobber existing file \"'xvi/src/yankput.c'\"
  1985. else
  1986.   echo shar: Extracting \"'xvi/src/yankput.c'\" \(11738 characters\)
  1987.   sed "s/^X//" >'xvi/src/yankput.c' <<'END_OF_FILE'
  1988. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  1989. X#ifndef lint
  1990. Xstatic char *sccsid = "@(#)yankput.c    2.4 (Chris & John Downey) 8/6/92";
  1991. X#endif
  1992. X
  1993. X/***
  1994. X
  1995. X* program name:
  1996. X    xvi
  1997. X* function:
  1998. X    PD version of UNIX "vi" editor, with extensions.
  1999. X* module name:
  2000. X    yankput.c
  2001. X* module function:
  2002. X    Functions to handle "yank" and "put" commands.
  2003. X
  2004. X    Note that there is still some code in normal.c to do
  2005. X    some of the work - this will have to be changed later.
  2006. X
  2007. X    Some of the routines and data structures herein assume ASCII
  2008. X    order, so I don't know if they are particularly portable.
  2009. X* history:
  2010. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  2011. X    Originally by Tim Thompson (twitch!tjt)
  2012. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  2013. X    Heavily modified by Chris & John Downey
  2014. X
  2015. X***/
  2016. X
  2017. X#include "xvi.h"
  2018. X
  2019. X/*
  2020. X * Structure to store yanked text or yanked lines.
  2021. X */
  2022. Xtypedef struct yankbuffer {
  2023. X    enum {
  2024. X    y_none,
  2025. X    y_chars,
  2026. X    y_lines
  2027. X    } y_type;
  2028. X
  2029. X    char    *y_1st_text;
  2030. X    char    *y_2nd_text;
  2031. X    Line    *y_line_buf;
  2032. X} Yankbuffer;
  2033. X
  2034. X/*
  2035. X * For named buffers, we have an array of yankbuffer structures,
  2036. X * mapped by printable ascii characters. Only the alphabetic
  2037. X * characters, and '@', are directly settable by the user.
  2038. X * The uppercase versions mean "append" rather than "replace".
  2039. X */
  2040. X#define    LOWEST_NAME    ' '
  2041. X#define    HIGHEST_NAME    'Z'
  2042. X#define    NBUFS        (HIGHEST_NAME - LOWEST_NAME + 1)
  2043. X#define    bufno(c)    ((c) - LOWEST_NAME)
  2044. X#define    validname(c)    ((c) >= LOWEST_NAME && (c) < 'A')
  2045. X
  2046. Xstatic    Yankbuffer    yb[NBUFS];
  2047. X
  2048. Xstatic    void        put P((char *, bool_t, bool_t));
  2049. Xstatic    Yankbuffer    *yp_get_buffer P((int));
  2050. Xstatic    Line        *copy_lines P((Line *, Line *));
  2051. Xstatic    char        *yanktext P((Posn *, Posn *));
  2052. Xstatic    void        yp_free P((Yankbuffer *));
  2053. X
  2054. Xvoid
  2055. Xinit_yankput()
  2056. X{
  2057. X}
  2058. X
  2059. X/*
  2060. X * Set the buffer name to be used for the next yank/put operation to
  2061. X * the given character. The character '@' is used as a synonym for the
  2062. X * default (unnamed) buffer.
  2063. X */
  2064. Xstatic Yankbuffer *
  2065. Xyp_get_buffer(name)
  2066. Xint    name;
  2067. X{
  2068. X    int    i;
  2069. X
  2070. X    if (validname(name)) {
  2071. X    i = bufno(name);
  2072. X    } else if (is_alpha(name)) {
  2073. X    if (is_upper(name)) {
  2074. X        show_message(curwin, "Appending to named buffers not supported");
  2075. X    }
  2076. X    i = bufno(to_upper(name));
  2077. X    } else {
  2078. X    show_error(curwin, "Illegal buffer name");
  2079. X    return(NULL);
  2080. X    }
  2081. X    return(&yb[i]);
  2082. X}
  2083. X
  2084. X/*
  2085. X * Yank the text specified by the given start/end positions.
  2086. X * The fourth parameter is TRUE if we are doing a character-
  2087. X * based, rather than a line-based, yank.
  2088. X *
  2089. X * For line-based yanks, the range of positions is inclusive.
  2090. X *
  2091. X * Returns TRUE if successfully yanked.
  2092. X *
  2093. X * Positions must be ordered properly, i.e. "from" <= "to".
  2094. X */
  2095. X/*ARGSUSED*/
  2096. Xbool_t
  2097. Xdo_yank(buffer, from, to, charbased, name)
  2098. XBuffer    *buffer;
  2099. XPosn    *from, *to;
  2100. Xbool_t    charbased;
  2101. Xint    name;
  2102. X{
  2103. X    Yankbuffer    *yp_buf;
  2104. X    long    nlines;
  2105. X
  2106. X    yp_buf = yp_get_buffer(name);
  2107. X    if (yp_buf == NULL) {
  2108. X    return(FALSE);
  2109. X    }
  2110. X    yp_free(yp_buf);
  2111. X
  2112. X    nlines = cntllines(from->p_line, to->p_line);
  2113. X
  2114. X    if (charbased) {
  2115. X    Posn        ptmp;
  2116. X
  2117. X    /*
  2118. X     * First yank either the whole of the text string
  2119. X     * specified (if from and to are on the same line),
  2120. X     * or from "from" to the end of the line.
  2121. X     */
  2122. X    ptmp.p_line = from->p_line;
  2123. X    if (to->p_line == from->p_line) {
  2124. X        ptmp.p_index = to->p_index;
  2125. X    } else {
  2126. X        ptmp.p_index = strlen(from->p_line->l_text) - 1;
  2127. X    }
  2128. X    yp_buf->y_1st_text = yanktext(from, &ptmp);
  2129. X    if (yp_buf->y_1st_text == NULL) {
  2130. X        return(FALSE);
  2131. X    }
  2132. X
  2133. X    /*
  2134. X     * Next, determine if it is a multi-line character-based
  2135. X     * yank, in which case we have to yank from the start of
  2136. X     * the line containing "to" up to "to" itself.
  2137. X     */
  2138. X    if (nlines > 1) {
  2139. X        ptmp.p_line = to->p_line;
  2140. X        ptmp.p_index = 0;
  2141. X        yp_buf->y_2nd_text = yanktext(&ptmp, to);
  2142. X        if (yp_buf->y_1st_text == NULL) {
  2143. X        free(yp_buf->y_1st_text);
  2144. X        return(FALSE);
  2145. X        }
  2146. X    }
  2147. X
  2148. X    /*
  2149. X     * Finally, we may need to yank any lines between "from"
  2150. X     * and "to".
  2151. X     */
  2152. X    if (nlines > 2) {
  2153. X        yp_buf->y_line_buf =
  2154. X        copy_lines(from->p_line->l_next, to->p_line);
  2155. X        if (yp_buf->y_line_buf == NULL) {
  2156. X        free(yp_buf->y_1st_text);
  2157. X        free(yp_buf->y_2nd_text);
  2158. X        return(FALSE);
  2159. X        }
  2160. X    }
  2161. X
  2162. X    yp_buf->y_type = y_chars;
  2163. X    } else {
  2164. X    /*
  2165. X     * Yank lines starting at "from", ending at "to".
  2166. X     */
  2167. X    yp_buf->y_line_buf = copy_lines(from->p_line,
  2168. X            to->p_line->l_next);
  2169. X    if (yp_buf->y_line_buf == NULL) {
  2170. X        return(FALSE);
  2171. X    }
  2172. X    yp_buf->y_type = y_lines;
  2173. X    }
  2174. X    return(TRUE);
  2175. X}
  2176. X
  2177. X/*
  2178. X * Yank the given string.
  2179. X *
  2180. X * Third parameter indicates whether to do it as a line or a string.
  2181. X *
  2182. X * Returns TRUE if successfully yanked.
  2183. X */
  2184. Xbool_t
  2185. Xyank_str(name, str, line_based)
  2186. Xint    name;
  2187. Xchar    *str;
  2188. Xbool_t    line_based;
  2189. X{
  2190. X    Yankbuffer        *yp_buf;
  2191. X    register Line    *tmp;
  2192. X    register char    *cp;
  2193. X
  2194. X    yp_buf = yp_get_buffer(name);
  2195. X    if (yp_buf == NULL) {
  2196. X    return(FALSE);
  2197. X    }
  2198. X    yp_free(yp_buf);
  2199. X
  2200. X    /*
  2201. X     * Obtain space to store the string.
  2202. X     */
  2203. X    if (line_based) {
  2204. X    /*
  2205. X     * First try to save the string. If no can do,
  2206. X     * return FALSE without affecting the current
  2207. X     * contents of the yank buffer.
  2208. X     */
  2209. X    tmp = newline(strlen(str) + 1);
  2210. X    if (tmp == NULL) {
  2211. X        return(FALSE);
  2212. X    }
  2213. X    tmp->l_prev = tmp->l_next = NULL;
  2214. X    (void) strcpy(tmp->l_text, str);
  2215. X    } else {
  2216. X        cp = strsave(str);
  2217. X    if (cp == NULL) {
  2218. X        return(FALSE);
  2219. X    }
  2220. X    }
  2221. X
  2222. X    /*
  2223. X     * Set up the yank structure.
  2224. X     */
  2225. X    if (line_based) {
  2226. X    yp_buf->y_type = y_lines;
  2227. X    yp_buf->y_line_buf = tmp;
  2228. X    } else {
  2229. X        yp_buf->y_type = y_chars;
  2230. X    yp_buf->y_1st_text = cp;
  2231. X    }
  2232. X
  2233. X    return(TRUE);
  2234. X}
  2235. X
  2236. X/*
  2237. X * Put back the last yank at the specified position,
  2238. X * in the specified direction.
  2239. X */
  2240. Xvoid
  2241. Xdo_put(win, location, direction, name)
  2242. XXviwin    *win;
  2243. XPosn    *location;
  2244. Xint    direction;
  2245. Xint    name;
  2246. X{
  2247. X    Yankbuffer        *yp_buf;
  2248. X    register Line    *currline;    /* line we are on now */
  2249. X    register Line    *nextline;    /* line after currline */
  2250. X    Buffer        *buffer;
  2251. X
  2252. X    yp_buf = yp_get_buffer(name);
  2253. X    if (yp_buf == NULL) {
  2254. X    return;
  2255. X    }
  2256. X
  2257. X    buffer = win->w_buffer;
  2258. X
  2259. X    /*
  2260. X     * Set up current and next line pointers.
  2261. X     */
  2262. X    currline = location->p_line;
  2263. X    nextline = currline->l_next;
  2264. X
  2265. X    /*
  2266. X     * See which type of yank it was ...
  2267. X     */
  2268. X    if (yp_buf->y_type == y_chars) {
  2269. X    int    l;
  2270. X
  2271. X    l = win->w_cursor->p_index;
  2272. X    if (direction == FORWARD && currline->l_text[l] != '\0') {
  2273. X        ++l;
  2274. X    }
  2275. X
  2276. X    if (!start_command(win)) {
  2277. X        return;
  2278. X    }
  2279. X
  2280. X    /*
  2281. X     * Firstly, insert the 1st_text buffer, since this is
  2282. X     * always present. We may wish to split the line after
  2283. X     * the inserted text if this was a multi-line yank.
  2284. X     */
  2285. X    replchars(win, currline, l, 0, yp_buf->y_1st_text);
  2286. X    updateline(win);
  2287. X
  2288. X    if (yp_buf->y_2nd_text != NULL) {
  2289. X        int    end_of_1st_text;
  2290. X        Line    *newl;
  2291. X
  2292. X        end_of_1st_text = l + strlen(yp_buf->y_1st_text);
  2293. X        newl = newline(strlen(yp_buf->y_1st_text) + SLOP);
  2294. X        if (newl == NULL)
  2295. X        return;
  2296. X
  2297. X        /*
  2298. X         * Link the new line into the list.
  2299. X         */
  2300. X        repllines(win, nextline, 0L, newl);
  2301. X        nextline = newl;
  2302. X        replchars(win, nextline, 0, 0,
  2303. X                currline->l_text + end_of_1st_text);
  2304. X        replchars(win, currline, end_of_1st_text,
  2305. X            strlen(currline->l_text + end_of_1st_text), "");
  2306. X
  2307. X    }
  2308. X
  2309. X    if (yp_buf->y_line_buf != NULL) {
  2310. X        Line    *newlines;
  2311. X
  2312. X        newlines = copy_lines(yp_buf->y_line_buf, (Line *) NULL);
  2313. X        if (newlines != NULL) {
  2314. X        repllines(win, nextline, 0L, newlines);
  2315. X        }
  2316. X    }
  2317. X
  2318. X    if (yp_buf->y_2nd_text != NULL) {
  2319. X        if (nextline == buffer->b_lastline) {
  2320. X        Line    *new;
  2321. X
  2322. X        /*
  2323. X         * Can't put the remainder of the text
  2324. X         * on the following line, 'cos there
  2325. X         * isn't one, so we have to create a
  2326. X         * new line.
  2327. X         */
  2328. X        new = newline(strlen(yp_buf->y_2nd_text) + 1);
  2329. X        if (new == NULL) {
  2330. X            end_command(win);
  2331. X            return;
  2332. X        }
  2333. X        repllines(win, nextline, 0L, new);
  2334. X        nextline = new;
  2335. X        }
  2336. X        replchars(win, nextline, 0, 0, yp_buf->y_2nd_text);
  2337. X    }
  2338. X
  2339. X    end_command(win);
  2340. X
  2341. X    /*
  2342. X     * Move on to the last character of the inserted text.
  2343. X     */
  2344. X    if (direction == BACKWARD) {
  2345. X        (void) one_left(curwin, FALSE);
  2346. X    }
  2347. X
  2348. X    cursupdate(win);
  2349. X    update_buffer(buffer);
  2350. X
  2351. X    } else if (yp_buf->y_type == y_lines) {
  2352. X
  2353. X    Line    *new;        /* first line of lines to be put */
  2354. X
  2355. X    /*
  2356. X     * Make a new copy of the saved lines.
  2357. X     */
  2358. X    new = copy_lines(yp_buf->y_line_buf, (Line *) NULL);
  2359. X    if (new == NULL) {
  2360. X        return;
  2361. X    }
  2362. X
  2363. X    repllines(win, (direction == FORWARD) ? nextline : currline, 0L, new);
  2364. X
  2365. X    /*
  2366. X     * Put the cursor at the "right" place
  2367. X     * (i.e. the place the "real" vi uses).
  2368. X     */
  2369. X    move_cursor(win, new, 0);
  2370. X    begin_line(win, TRUE);
  2371. X    move_window_to_cursor(win);
  2372. X    cursupdate(win);
  2373. X    update_buffer(buffer);
  2374. X    } else {
  2375. X    show_error(win, "Nothing to put!");
  2376. X    }
  2377. X}
  2378. X
  2379. X/*
  2380. X * Stuff the specified buffer into the input stream.
  2381. X * Called by the '@' command.
  2382. X *
  2383. X * The "vi_mode" parameter will be FALSE if the buffer should
  2384. X * be preceded by a ':' and followed by a '\n', i.e. it is the
  2385. X * result of a :@ command rather than a vi-mode @ command.
  2386. X */
  2387. Xvoid
  2388. Xyp_stuff_input(win, name, vi_mode)
  2389. XXviwin    *win;
  2390. Xint    name;
  2391. Xbool_t    vi_mode;
  2392. X{
  2393. X    Yankbuffer    *yp_buf;
  2394. X
  2395. X    yp_buf = yp_get_buffer(name);
  2396. X    if (yp_buf == NULL) {
  2397. X    show_error(win, "Nothing in buffer %c", name);
  2398. X    return;
  2399. X    }
  2400. X
  2401. X    switch (yp_buf->y_type) {
  2402. X    case y_chars:
  2403. X    put(yp_buf->y_1st_text, vi_mode, FALSE);
  2404. X    break;
  2405. X
  2406. X    case y_lines:
  2407. X    break;
  2408. X
  2409. X    default:
  2410. X    show_error(win, "Nothing to put!");
  2411. X    return;
  2412. X    }
  2413. X
  2414. X    if (yp_buf->y_line_buf != NULL) {
  2415. X    Line    *lp;
  2416. X
  2417. X    for (lp = yp_buf->y_line_buf; lp != NULL; lp = lp->l_next) {
  2418. X        put(lp->l_text, vi_mode, TRUE);
  2419. X    }
  2420. X    }
  2421. X
  2422. X    if (yp_buf->y_type == y_chars && yp_buf->y_2nd_text != NULL) {
  2423. X    put(yp_buf->y_2nd_text, vi_mode, FALSE);
  2424. X    }
  2425. X}
  2426. X
  2427. Xstatic void
  2428. Xput(str, vi_mode, newline)
  2429. Xchar    *str;
  2430. Xbool_t    vi_mode;
  2431. Xbool_t    newline;
  2432. X{
  2433. X    stuff("%s%s%s",
  2434. X        (!vi_mode && str[0] != ':') ? ":" : "",
  2435. X        str,
  2436. X        (!vi_mode || newline) ? "\n" : "");
  2437. X}
  2438. X
  2439. X/*
  2440. X * Copy the lines pointed at by "from", up to but not including
  2441. X * pointer "to" (which might be NULL), into new memory and return
  2442. X * a pointer to the start of the new list.
  2443. X *
  2444. X * Returns NULL for errors.
  2445. X */
  2446. Xstatic Line *
  2447. Xcopy_lines(from, to)
  2448. XLine    *from, *to;
  2449. X{
  2450. X    Line    *src;
  2451. X    Line    head;
  2452. X    Line    *dest = &head;
  2453. X
  2454. X    for (src = from; src != to; src = src->l_next) {
  2455. X    Line    *tmp;
  2456. X
  2457. X    tmp = newline(strlen(src->l_text) + 1);
  2458. X    if (tmp == NULL) {
  2459. X        throw(head.l_next);
  2460. X        return(NULL);
  2461. X    }
  2462. X
  2463. X    /*
  2464. X     * Copy the line's text over, and advance
  2465. X     * "dest" to point to the new line structure.
  2466. X     */
  2467. X    (void) strcpy(tmp->l_text, src->l_text);
  2468. X    tmp->l_next = NULL;
  2469. X    tmp->l_prev = dest;
  2470. X    dest->l_next = tmp;
  2471. X    dest = tmp;
  2472. X    }
  2473. X
  2474. X    return(head.l_next);
  2475. X}
  2476. X
  2477. Xstatic char *
  2478. Xyanktext(from, to)
  2479. XPosn    *from, *to;
  2480. X{
  2481. X    int        nchars;
  2482. X    char    *cp;
  2483. X
  2484. X    nchars = to->p_index - from->p_index + 1;
  2485. X    cp = (char *) alloc((unsigned) nchars + 1);
  2486. X    if (cp == NULL) {
  2487. X    return(NULL);
  2488. X    }
  2489. X
  2490. X    (void) strncpy(cp, from->p_line->l_text + from->p_index, nchars);
  2491. X    cp[nchars] = '\0';
  2492. X
  2493. X    return(cp);
  2494. X}
  2495. X
  2496. Xstatic void
  2497. Xyp_free(yp)
  2498. XYankbuffer    *yp;
  2499. X{
  2500. X    if (yp->y_type == y_lines) {
  2501. X    throw(yp->y_line_buf);
  2502. X    yp->y_line_buf = NULL;
  2503. X    } else if (yp->y_type == y_chars) {
  2504. X    free(yp->y_1st_text);
  2505. X    yp->y_1st_text = NULL;
  2506. X    if (yp->y_2nd_text != NULL)
  2507. X        free(yp->y_2nd_text);
  2508. X    yp->y_2nd_text = NULL;
  2509. X    if (yp->y_line_buf != NULL)
  2510. X        throw(yp->y_line_buf);
  2511. X    yp->y_line_buf = NULL;
  2512. X    }
  2513. X    yp->y_type = y_none;
  2514. X}
  2515. X
  2516. X/*
  2517. X * Push up buffers 1..8 by one, spilling 9 off the top.
  2518. X * Then move '@' into '1'.
  2519. X *
  2520. X * This routine assumes contiguity of characters '0' to '9',
  2521. X * i.e. probably ASCII, but what the hell.
  2522. X */
  2523. Xvoid
  2524. Xyp_push_deleted()
  2525. X{
  2526. X    Yankbuffer    *atp;
  2527. X    int        c;
  2528. X
  2529. X    yp_free(&yb[bufno('9')]);
  2530. X    for (c = '9'; c > '1'; --c) {
  2531. X        yb[bufno(c)] = yb[bufno(c - 1)];
  2532. X    }
  2533. X    atp = &yb[bufno('@')];
  2534. X    yb[bufno('1')] = *atp;
  2535. X    atp->y_type = y_none;
  2536. X    atp->y_line_buf = NULL;
  2537. X    atp->y_1st_text = NULL;
  2538. X    atp->y_2nd_text = NULL;
  2539. X}
  2540. END_OF_FILE
  2541.   if test 11738 -ne `wc -c <'xvi/src/yankput.c'`; then
  2542.     echo shar: \"'xvi/src/yankput.c'\" unpacked with wrong size!
  2543.   fi
  2544.   # end of 'xvi/src/yankput.c'
  2545. fi
  2546. echo shar: End of archive 13 \(of 18\).
  2547. cp /dev/null ark13isdone
  2548. MISSING=""
  2549. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  2550.     if test ! -f ark${I}isdone ; then
  2551.     MISSING="${MISSING} ${I}"
  2552.     fi
  2553. done
  2554. if test "${MISSING}" = "" ; then
  2555.     echo You have unpacked all 18 archives.
  2556.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2557. else
  2558.     echo You still must unpack the following archives:
  2559.     echo "        " ${MISSING}
  2560. fi
  2561. exit 0
  2562. exit 0 # Just in case...
  2563.