home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / xvi / part08 < prev    next >
Encoding:
Text File  |  1992-10-22  |  55.1 KB  |  2,018 lines

  1. Newsgroups: comp.sources.misc
  2. From: jmd@cyclone.bt.co.uk (John Downey)
  3. Subject:  v33i017:  xvi - portable multi-window vi-like editor, Part08/18
  4. Message-ID: <1992Oct23.181342.391@sparky.imd.sterling.com>
  5. X-Md4-Signature: 98d37031a5d766c2ca44cecd730694f3
  6. Date: Fri, 23 Oct 1992 18:13:42 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 17
  11. Archive-name: xvi/part08
  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/undo.c xvi/src/xvi.h
  19. # Wrapped by kent@sparky on Thu Oct 22 09:03:42 1992
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 8 (of 18)."'
  23. if test -f 'xvi/src/undo.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'xvi/src/undo.c'\"
  25. else
  26.   echo shar: Extracting \"'xvi/src/undo.c'\" \(21383 characters\)
  27.   sed "s/^X//" >'xvi/src/undo.c' <<'END_OF_FILE'
  28. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  29. X#ifndef lint
  30. Xstatic char *sccsid = "@(#)undo.c    2.2 (Chris & John Downey) 8/28/92";
  31. X#endif
  32. X
  33. X/***
  34. X
  35. X* program name:
  36. X    xvi
  37. X* function:
  38. X    PD version of UNIX "vi" editor, with extensions.
  39. X* module name:
  40. X    undo.c
  41. X* module function:
  42. X    Code to implement "undo" command.
  43. X
  44. X* usage:
  45. X    We provide several primitive functions for "do"ing things,
  46. X    and an "undo" function to restore the previous state.
  47. X
  48. X    Normally, a primitive function is simply called, and will
  49. X    automatically throw away the old previous state before
  50. X    saving the current one and then making the change.
  51. X
  52. X    Alternatively, it is possible to bracket lots of changes
  53. X    between calls to the start_command() and end_command()
  54. X    functions; more global changes can then be effected,
  55. X    and undo still works as it should.  This is used for the
  56. X    "global" command, for multi-line substitutes, and for
  57. X    insert mode.
  58. X
  59. X* history:
  60. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  61. X    Originally by Tim Thompson (twitch!tjt)
  62. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  63. X    Heavily modified by Chris & John Downey
  64. X
  65. X***/
  66. X
  67. X#include "xvi.h"
  68. X
  69. Xstatic    void    save_position P((Xviwin *));
  70. Xstatic    void    free_changes P((Change *));
  71. Xstatic    void    report P((Xviwin *));
  72. X
  73. X/*
  74. X * This variable holds the total number of added/deleted lines
  75. X * for a change; it is used for reporting (the "report" parameter).
  76. X */
  77. Xstatic    long    total_lines;
  78. X
  79. Xvoid
  80. Xinit_undo(buffer)
  81. XBuffer    *buffer;
  82. X{
  83. X    /*
  84. X     * Initialise the undo-related variables in the Buffer.
  85. X     */
  86. X    buffer->b_nlevels = 0;
  87. X    buffer->b_change = NULL;
  88. X
  89. X    /*
  90. X     * Set line numbers.
  91. X     */
  92. X    buffer->b_line0->l_number = 0;
  93. X    buffer->b_file->l_number = 1;
  94. X    buffer->b_lastline->l_number = MAX_LINENO;
  95. X}
  96. X
  97. X/*
  98. X * Start a command. This routine may be called many times;
  99. X * what it does is increase the variable which shows how
  100. X * many times it has been called.  The end_command() then
  101. X * decrements the variable - so it is vital that calls
  102. X * of the two routines are matched.
  103. X *
  104. X * The effect of this is quite simple; if the nlevels variable
  105. X * is >0, the "do*" routines will not throw away the previous
  106. X * state before making a change; and thus we are able to undo
  107. X * multiple changes.
  108. X *
  109. X * All the do* routines, and start_command(), will throw away
  110. X * the previous saved state if the b_nlevels variable is 0.
  111. X */
  112. Xbool_t
  113. Xstart_command(window)
  114. XXviwin    *window;
  115. X{
  116. X    Buffer    *buffer;
  117. X
  118. X    buffer = window->w_buffer;
  119. X
  120. X    if (buffer->b_nlevels == 0) {
  121. X    if (not_editable(buffer)) {
  122. X        show_error(window, "Edit not allowed!");
  123. X        return(FALSE);
  124. X    }
  125. X    free_changes(buffer->b_change);
  126. X    buffer->b_change = NULL;
  127. X    }
  128. X
  129. X    buffer->b_nlevels += 1;
  130. X
  131. X    total_lines = 0;
  132. X
  133. X    save_position(window);
  134. X
  135. X    return(TRUE);
  136. X}
  137. X
  138. X/*
  139. X * Save the cursor position.
  140. X *
  141. X * This is called at the start of each change, so that
  142. X * the cursor will return to the right place after an undo.
  143. X */
  144. Xstatic void
  145. Xsave_position(window)
  146. XXviwin    *window;
  147. X{
  148. X    Buffer    *buffer;
  149. X    Change    *change;
  150. X
  151. X    buffer = window->w_buffer;
  152. X
  153. X    change = challoc();
  154. X    if (change == NULL)
  155. X    return;
  156. X
  157. X    change->c_type = C_POSITION;
  158. X    change->c_pline = lineno(buffer, window->w_cursor->p_line);
  159. X    change->c_pindex = window->w_cursor->p_index;
  160. X
  161. X    change->c_next = buffer->b_change;
  162. X    buffer->b_change = change;
  163. X}
  164. X
  165. Xvoid
  166. Xend_command(window)
  167. XXviwin    *window;
  168. X{
  169. X    Buffer    *buffer;
  170. X
  171. X    buffer = window->w_buffer;
  172. X
  173. X    if (buffer->b_nlevels > 0) {
  174. X    buffer->b_nlevels -= 1;
  175. X    if (buffer->b_nlevels == 0) {
  176. X        report(window);
  177. X    }
  178. X    } else {
  179. X    show_error(window, "Internal error: too many \"end_command\"s");
  180. X    }
  181. X}
  182. X
  183. X/*
  184. X * Replace the given section of the given line with the
  185. X * new (null-terminated) string. nchars may be zero for
  186. X * insertions of text; newstring may point to a 0-length
  187. X * string to delete text. start is the first character
  188. X * of the section which is to be replaced.
  189. X *
  190. X * Note that we don't call strcpy() to copy text here, for
  191. X * two reasons: firstly, we are likely to be copying small
  192. X * numbers of characters and it is therefore faster to do
  193. X * the copying ourselves, and secondly, strcpy() doesn't
  194. X * necessarily work for copying overlapping text towards
  195. X * higher locations in memory.
  196. X */
  197. Xvoid
  198. Xreplchars(window, line, start, nchars, newstring)
  199. XXviwin    *window;
  200. XLine    *line;
  201. Xint    start;
  202. Xint    nchars;
  203. Xchar    *newstring;
  204. X{
  205. X    register char    *from;        /* where to copy from */
  206. X    register char    *to;        /* where to copy to */
  207. X    register int    nlen;        /* length of newstring */
  208. X    register int    olen;        /* length of old line */
  209. X    register int    offset;        /* how much to move text by */
  210. X    Buffer        *buffer;
  211. X    Change        *change;
  212. X
  213. X    buffer = window->w_buffer;
  214. X
  215. X    /*
  216. X     * If this is a singleton command, make sure we
  217. X     * destroy the changes made as part of the last
  218. X     * command before we start the new one.
  219. X     */
  220. X    if (buffer->b_nlevels == 0) {
  221. X    if (not_editable(buffer)) {
  222. X        show_error(window, "Edit not allowed!");
  223. X        return;
  224. X    }
  225. X    free_changes(buffer->b_change);
  226. X    buffer->b_change = NULL;
  227. X    save_position(window);
  228. X    }
  229. X
  230. X    /*
  231. X     * First thing we have to do is to obtain a change
  232. X     * structure to record the change so we can be sure
  233. X     * that we can undo it. If this fails, we must not
  234. X     * make any change at all.
  235. X     */
  236. X    change = challoc();
  237. X    if (change == NULL)
  238. X    return;
  239. X
  240. X    nlen = strlen(newstring);
  241. X    olen = strlen(line->l_text + start);
  242. X    if (olen < nchars)
  243. X    nchars = olen;
  244. X    offset = nlen - nchars;
  245. X
  246. X    /*
  247. X     * Record the opposite change so we can undo it.
  248. X     */
  249. X    if (nchars == 0) {
  250. X    change->c_type = C_DEL_CHAR;
  251. X    } else {
  252. X    change->c_type = C_CHAR;
  253. X    change->c_chars = alloc((unsigned) nchars + 1);
  254. X    if (change->c_chars == NULL) {
  255. X        chfree(change);
  256. X        State = NORMAL;
  257. X        return;
  258. X    }
  259. X    (void) strncpy(change->c_chars, line->l_text + start, nchars);
  260. X    change->c_chars[nchars] = '\0';
  261. X    }
  262. X    change->c_lineno = lineno(buffer, line);
  263. X    change->c_index = start;
  264. X    change->c_nchars = nlen;
  265. X
  266. X    if (offset > 0) {
  267. X    register char    *s;
  268. X
  269. X    /*
  270. X     * Move existing text along by offset to the right.
  271. X     * First make some room in the line.
  272. X     */
  273. X    if (grow_line(line, offset) == FALSE) {
  274. X        free(change->c_chars);
  275. X        chfree(change);
  276. X        State = NORMAL;
  277. X        return;
  278. X    }
  279. X
  280. X    /*
  281. X     * Copy characters backwards, i.e. start
  282. X     * at the end of the line rather than at
  283. X     * the start.
  284. X     */
  285. X    from = line->l_text + start;
  286. X    to = from + offset + olen + 1;
  287. X    s = from + olen + 1;
  288. X    while (s > from) {
  289. X        *--to = *--s;
  290. X    }
  291. X
  292. X    } else if (offset < 0) {
  293. X
  294. X    /*
  295. X     * Move existing text along to the left.
  296. X     */
  297. X    offset = - offset;
  298. X    to = line->l_text + start;
  299. X    from = to + offset;
  300. X
  301. X    /*
  302. X     * Do classic K&R strcpy().
  303. X     */
  304. X    while ((*to++ = *from++) != '\0') {
  305. X        ;
  306. X    }
  307. X    }
  308. X
  309. X    /*
  310. X     * Finally, copy the new text into position.
  311. X     * Note that we are careful not to copy the
  312. X     * null terminator.
  313. X     */
  314. X    from = newstring;
  315. X    to = line->l_text + start;
  316. X    while (*from != '\0') {
  317. X    *to++ = *from++;
  318. X    }
  319. X
  320. X    buffer->b_flags |= FL_MODIFIED;
  321. X
  322. X    window->w_curs_new = TRUE;
  323. X    
  324. X    /*
  325. X     * Push this change onto the LIFO of changes
  326. X     * that form the current command.
  327. X     */
  328. X    change->c_next = buffer->b_change;
  329. X    buffer->b_change = change;
  330. X}
  331. X
  332. X/*
  333. X * Replace the specified set of lines with the replacement set.
  334. X * The number of lines to be replaced may be 0; the replacement
  335. X * list may be a NULL pointer.
  336. X */
  337. Xvoid
  338. Xrepllines(window, line, nolines, newlines)
  339. Xregister Xviwin    *window;
  340. XLine        *line;
  341. Xlong        nolines;
  342. XLine        *newlines;
  343. X{
  344. X    register Buffer    *buffer;    /* buffer window is mapped onto */
  345. X    Line        *firstp;    /* line before first to delete */
  346. X    Line        *lastp;        /* line after last to delete */
  347. X    Line        *lastline;    /* last line to delete */
  348. X    Line        *new_start;    /* start of lines to be inserted */
  349. X    Line        *new_end;    /* last line to be inserted */
  350. X    long        nnlines;    /* no. new logical lines */
  351. X    long        oplines;    /* no. physical lines to be replaced */
  352. X    long        nplines;    /* no. new physical lines */
  353. X    long        n;        /* lines done so far */
  354. X    register Xviwin    *wp;        /* loop variable */
  355. X    Change        *change;
  356. X
  357. X    buffer = window->w_buffer;
  358. X
  359. X    /*
  360. X     * If this is a singleton command, make sure we
  361. X     * destroy the changes made as part of the last
  362. X     * command before we start the new one.
  363. X     */
  364. X    if (buffer->b_nlevels == 0) {
  365. X    if (not_editable(buffer)) {
  366. X        show_error(window, "Edit not allowed!");
  367. X        return;
  368. X    }
  369. X    free_changes(buffer->b_change);
  370. X    buffer->b_change = NULL;
  371. X    total_lines = 0;
  372. X    save_position(window);
  373. X    }
  374. X
  375. X    /*
  376. X     * First thing we have to do is to obtain a change
  377. X     * structure to record the change so we can be sure
  378. X     * that we can undo it. If this fails, we must not
  379. X     * make any change at all.
  380. X     */
  381. X    change = challoc();
  382. X    if (change == NULL)
  383. X    return;
  384. X    change->c_type = C_LINE;
  385. X
  386. X    /*
  387. X     * Work out how many lines are in the new set, and set up
  388. X     * pointers to the beginning and end of the list.
  389. X     */
  390. X    if (newlines != NULL) {
  391. X    /*
  392. X     * We have a new set of lines to replace the old.
  393. X     */
  394. X    new_start = newlines;
  395. X    nnlines = 1;
  396. X    nplines = 0;
  397. X    for (new_end = newlines; new_end->l_next != NULL;
  398. X                        new_end = new_end->l_next) {
  399. X        nnlines++;
  400. X        nplines += plines(window, new_end);
  401. X    }
  402. X    nplines += plines(window, new_end);
  403. X    } else {
  404. X    /*
  405. X     * No new lines; we are just deleting some.
  406. X     */
  407. X    new_start = new_end = NULL;
  408. X    nnlines = 0;
  409. X    nplines = 0;
  410. X    }
  411. X
  412. X    /*
  413. X     * Point "firstp" at the line before the first to be deleted,
  414. X     * "lastline" at the last line to be deleted, and "lastp" at
  415. X     * the line after the last to be deleted. To do the latter,
  416. X     * we must loop through the buffer from the specified start
  417. X     * line "nolines" times. We also use this loop to set up the
  418. X     * "oplines" variable.
  419. X     *
  420. X     * The line number recorded for the change is the number of the
  421. X     * line immediately before it, plus 1. This copes with line being
  422. X     * equal to the lastline pointer, which is sometimes necessary
  423. X     * for deleting lines at the end of the file.
  424. X     */
  425. X    firstp = line->l_prev;
  426. X    lastline = line;
  427. X    change->c_lineno = firstp->l_number + 1;
  428. X
  429. X    oplines = 0;
  430. X    for (lastp = line, n = 0; lastp != buffer->b_lastline && n < nolines;
  431. X                        n++, lastp = lastp->l_next) {
  432. X
  433. X    lastline = lastp;
  434. X
  435. X    /*
  436. X     * Clear any marks that may have been set
  437. X     * on the lines to be deleted.
  438. X     */
  439. X    clrmark(lastp, buffer);
  440. X
  441. X    oplines += plines(window, lastp);
  442. X
  443. X    /*
  444. X     * Scan through all windows which are mapped
  445. X     * onto the buffer we are modifying, to see
  446. X     * if we need to update their w_topline and/or
  447. X     * w_cursor elements as a result of the change.
  448. X     *
  449. X     * There is a disgusting hack here. If the number
  450. X     * of lines being added/deleted is such that the
  451. X     * cursor could remain at the same logical line
  452. X     * in the file after the change, then it should.
  453. X     * Since the cursor could be in different places
  454. X     * in each window, we use the Posn.p_index field
  455. X     * to store the offset from the start of the
  456. X     * changed section. This is only used if the
  457. X     * Posn.p_line field has been set to NULL.
  458. X     */
  459. X    wp = window;
  460. X    do {
  461. X        if (wp->w_buffer != buffer)
  462. X        continue;
  463. X
  464. X        if (lastp == wp->w_cursor->p_line) {
  465. X        long    offset;
  466. X
  467. X        /*
  468. X         * Mark the cursor line as NULL
  469. X         * so we will know to re-assign
  470. X         * it later.
  471. X         */
  472. X        wp->w_cursor->p_line = NULL;
  473. X        offset = cntllines(line, lastp);
  474. X        if (offset > INT_MAX) {
  475. X            offset = 0;
  476. X        }
  477. X        wp->w_cursor->p_index = offset;
  478. X        }
  479. X    } while ((wp = next_window(wp)) != window);
  480. X    }
  481. X
  482. X    /*
  483. X     * Hack.
  484. X     *
  485. X     * If we are replacing the entire buffer with no lines, we must
  486. X     * insert a blank line to avoid the buffer becoming totally empty.
  487. X     */
  488. X    if (nnlines == 0 && firstp == buffer->b_line0 &&
  489. X                    lastp == buffer->b_lastline) {
  490. X    /*
  491. X     * We are going to delete all the lines - so we have
  492. X     * to insert a new blank one in their place.
  493. X     */
  494. X    new_start = newline(1);
  495. X    if (new_start == NULL) {
  496. X        show_error(window, "Can't get memory to delete lines");
  497. X        chfree(change);
  498. X        return;
  499. X    }
  500. X    new_end = new_start;
  501. X    nnlines = 1;
  502. X    nplines = 1;
  503. X    }
  504. X
  505. X    /*
  506. X     * Scan through all of the windows which are mapped onto
  507. X     * the buffer being changed, and do any screen updates
  508. X     * that seem like a good idea.
  509. X     */
  510. X    wp = window;
  511. X    do {
  512. X    /*
  513. X     * Only do windows onto the right buffer.
  514. X     */
  515. X    if (wp->w_buffer != buffer)
  516. X        continue;
  517. X
  518. X    /*
  519. X     * Redraw part of the screen if necessary.
  520. X     */
  521. X    if (!earlier(line, wp->w_topline) &&
  522. X        earlier(lastline, wp->w_botline)) {
  523. X
  524. X        int    start_row;
  525. X
  526. X        start_row = cntplines(wp, wp->w_topline, line);
  527. X        if (nplines > oplines && start_row > 0 &&
  528. X        (start_row + nplines - oplines) < wp->w_nrows - 2) {
  529. X
  530. X        s_ins(wp, start_row, (int) (nplines - oplines));
  531. X
  532. X        } else if (nplines < oplines &&
  533. X            (start_row + oplines - nplines) < (wp->w_nrows - 2)) {
  534. X
  535. X        s_del(wp, start_row, (int) (oplines - nplines));
  536. X        }
  537. X    }
  538. X    } while ((wp = next_window(wp)) != window);
  539. X
  540. X    /*
  541. X     * Record the old set of lines as the replacement
  542. X     * set for undo, if there were any.
  543. X     */
  544. X    if (nolines > 0) {
  545. X    lastp->l_prev->l_next = NULL;
  546. X    line->l_prev = NULL;
  547. X    change->c_lines = line;
  548. X    } else {
  549. X    change->c_lines = NULL;
  550. X    }
  551. X    change->c_nlines = nnlines;
  552. X
  553. X    /*
  554. X     * Link the buffer back together, using the new
  555. X     * lines if there are any, otherwise just linking
  556. X     * around the deleted lines.
  557. X     */
  558. X    if (new_start != NULL) {
  559. X    firstp->l_next = new_start;
  560. X    lastp->l_prev = new_end;
  561. X    new_end->l_next = lastp;
  562. X    new_start->l_prev = firstp;
  563. X    } else {
  564. X    firstp->l_next = lastp;
  565. X    lastp->l_prev = firstp;
  566. X    }
  567. X
  568. X    buffer->b_flags |= FL_MODIFIED;
  569. X
  570. X    window->w_curs_new = TRUE;
  571. X
  572. X    /*
  573. X     * Re-link the buffer file pointer
  574. X     * in case we deleted line 1.
  575. X     */
  576. X    buffer->b_file = buffer->b_line0->l_next;
  577. X
  578. X    /*
  579. X     * Push this change onto the LIFO of changes
  580. X     * that form the current command.
  581. X     */
  582. X    change->c_next = buffer->b_change;
  583. X    buffer->b_change = change;
  584. X
  585. X    /*
  586. X     * Update the w_cursor and w_topline fields in any Xviwins
  587. X     * for which the lines to which they were pointing have
  588. X     * been deleted.
  589. X     */
  590. X    wp = window;
  591. X    do {
  592. X    /*
  593. X     * Only do windows onto the right buffer.
  594. X     */
  595. X    if (wp->w_buffer != buffer)
  596. X        continue;
  597. X
  598. X    /*
  599. X     * Don't need to update the w_cursor or w_topline
  600. X     * elements of this window if no lines are being
  601. X     * deleted.
  602. X     */
  603. X    if (nolines == 0)
  604. X        continue;
  605. X
  606. X    /*
  607. X     * Need a new cursor line value.
  608. X     */
  609. X    if (wp->w_cursor->p_line == NULL) {
  610. X        if (wp->w_cursor->p_index == 0) {
  611. X        wp->w_cursor->p_line = (lastp != buffer->b_lastline) ?
  612. X                        lastp : lastp->l_prev;
  613. X        } else {
  614. X        wp->w_cursor->p_line = firstp;
  615. X        (void) onedown(wp, (long) wp->w_cursor->p_index);
  616. X        }
  617. X        wp->w_cursor->p_index = 0;
  618. X        begin_line(wp, TRUE);
  619. X    }
  620. X
  621. X    /*
  622. X     * Update the "topline" element of the Xviwin structure
  623. X     * if the current topline is one of those being replaced.
  624. X     */
  625. X    if (line->l_number <= wp->w_topline->l_number &&
  626. X            lastline->l_number >= wp->w_topline->l_number) {
  627. X        wp->w_topline = wp->w_cursor->p_line;
  628. X    }
  629. X    } while ((wp = next_window(wp)) != window);
  630. X
  631. X    /*
  632. X     * Renumber the buffer - but not until all the pointers,
  633. X     * especially the b_file pointer, have been re-linked.
  634. X     */
  635. X    {
  636. X    Line        *p;
  637. X    unsigned long    l;
  638. X
  639. X    p = firstp;
  640. X    l = p->l_number;
  641. X    for (p = p->l_next; p != buffer->b_lastline; p = p->l_next) {
  642. X        p->l_number = ++l;
  643. X    }
  644. X    buffer->b_lastline->l_number = MAX_LINENO;
  645. X    }
  646. X
  647. X    total_lines += nnlines - nolines;
  648. X    if (buffer->b_nlevels == 0)
  649. X    report(window);
  650. X}
  651. X
  652. X/*
  653. X * Replace the entire buffer with the specified list of lines.
  654. X * This is only used for the :edit command, and we assume that
  655. X * checking has already been done that we are not losing data.
  656. X * The buffer is marked as unmodified. No screen updating is
  657. X * performed. This is the only way to make a non-undoable change
  658. X * to a buffer.
  659. X */
  660. Xvoid
  661. Xreplbuffer(window, newlines)
  662. Xregister Xviwin    *window;
  663. XLine        *newlines;
  664. X{
  665. X    register Buffer    *buffer;    /* buffer window is mapped onto */
  666. X    Line        *new_end;    /* last line to be inserted */
  667. X    Line        *p;
  668. X    unsigned long    l;
  669. X    Xviwin        *wp;
  670. X
  671. X    buffer = window->w_buffer;
  672. X
  673. X    if (newlines == NULL) {
  674. X    show_error(window,
  675. X        "Internal error: replbuffer called with no lines");
  676. X    return;
  677. X    }
  678. X
  679. X    if (buffer->b_nlevels != 0) {
  680. X    show_error(window,
  681. X        "Internal error: replbuffer called with nlevels != 0");
  682. X    return;
  683. X    }
  684. X    free_changes(buffer->b_change);
  685. X    buffer->b_change = NULL;
  686. X    buffer->b_nlevels = 0;
  687. X
  688. X    /*
  689. X     * Point new_end at the last line of newlines.
  690. X     */
  691. X    for (new_end = newlines; new_end->l_next != NULL;
  692. X                        new_end = new_end->l_next) {
  693. X    ;
  694. X    }
  695. X
  696. X    /*
  697. X     * Free up the old list of lines.
  698. X     */
  699. X    buffer->b_lastline->l_prev->l_next = NULL;
  700. X    throw(buffer->b_file);
  701. X
  702. X    /*
  703. X     * Link the buffer back together with the new lines.
  704. X     */
  705. X    buffer->b_line0->l_next = buffer->b_file = newlines;
  706. X    newlines->l_prev = buffer->b_line0;
  707. X    buffer->b_lastline->l_prev = new_end;
  708. X    new_end->l_next = buffer->b_lastline;
  709. X
  710. X    /*
  711. X     * Update the w_cursor and w_topline fields in all Xviwins
  712. X     * mapped onto the current Buffer.
  713. X     */
  714. X    wp = window;
  715. X    do {
  716. X    if (wp->w_buffer != buffer)
  717. X        continue;
  718. X
  719. X    move_cursor(wp, buffer->b_file, 0);
  720. X    wp->w_topline = wp->w_cursor->p_line;
  721. X
  722. X    } while ((wp = next_window(wp)) != window);
  723. X
  724. X    /*
  725. X     * Renumber the buffer.
  726. X     */
  727. X    l = 0L;
  728. X    for (p = buffer->b_line0; p != buffer->b_lastline; p = p->l_next) {
  729. X    p->l_number = l++;
  730. X    }
  731. X    buffer->b_lastline->l_number = MAX_LINENO;
  732. X
  733. X    /*
  734. X     * Mark buffer as unmodified, and clear any marks it has.
  735. X     */
  736. X    buffer->b_flags &= ~FL_MODIFIED;
  737. X    init_marks(buffer);
  738. X}
  739. X
  740. X/*
  741. X * Undo the last change in the buffer mapped by the given window.
  742. X */
  743. Xvoid
  744. Xundo(window)
  745. XXviwin    *window;
  746. X{
  747. X    Buffer    *buffer;
  748. X    Change    *chp;
  749. X
  750. X    buffer = window->w_buffer;
  751. X
  752. X    if (buffer->b_nlevels != 0) {
  753. X    show_error(window, "Internal error: undo called with nlevels != 0");
  754. X    return;
  755. X    }
  756. X
  757. X    /*
  758. X     * Grab the list of transactions which formed the command
  759. X     * that has to be undone, and then call start_command() so
  760. X     * we start with a clean slate.
  761. X     */
  762. X    chp = buffer->b_change;
  763. X    buffer->b_change = NULL;
  764. X
  765. X    if (start_command(window) == FALSE) {
  766. X    return;
  767. X    }
  768. X
  769. X    while (chp != NULL) {
  770. X    Change    *tmp;
  771. X    Line    *lp;
  772. X
  773. X    tmp = chp;
  774. X    chp = chp->c_next;
  775. X
  776. X    lp = gotoline(buffer, tmp->c_lineno);
  777. X
  778. X    switch (tmp->c_type) {
  779. X    case C_LINE:
  780. X        /*
  781. X         * If the line corresponding to the given number
  782. X         * isn't the one we went to, then we must have
  783. X         * deleted it in the original change. If the change
  784. X         * structure says to insert lines, we must set the
  785. X         * line pointer to the lastline marker so that the
  786. X         * insert happens in the right place; otherwise,
  787. X         * we should not, because repllines won't handle
  788. X         * deleting lines from the lastline pointer.
  789. X         */
  790. X        if (lp->l_number < tmp->c_lineno && tmp->c_lines != NULL) {
  791. X        lp = buffer->b_lastline;
  792. X        }
  793. X        /*
  794. X         * Put the lines back as they were.
  795. X         * Note that we don't free the lines
  796. X         * here; that is only ever done by
  797. X         * free_changes, when the next line
  798. X         * change happens.
  799. X         */
  800. X        repllines(window, lp, tmp->c_nlines, tmp->c_lines);
  801. X        break;
  802. X
  803. X    case C_DEL_CHAR:
  804. X        replchars(window, lp, tmp->c_index, tmp->c_nchars, "");
  805. X        break;
  806. X
  807. X    case C_CHAR:
  808. X        replchars(window, lp, tmp->c_index, tmp->c_nchars, tmp->c_chars);
  809. X
  810. X        /*
  811. X         * Free up the string, since it was strsave'd
  812. X         * by replchars at the time the change was made.
  813. X         */
  814. X        free(tmp->c_chars);
  815. X        break;
  816. X
  817. X    case C_POSITION:
  818. X        move_cursor(window, gotoline(buffer, tmp->c_pline), tmp->c_pindex);
  819. X        break;
  820. X
  821. X    default:
  822. X        show_error(window,
  823. X         "Internal error in undo: invalid change type. This is serious.");
  824. X        break;
  825. X    }
  826. X    chfree(tmp);
  827. X    }
  828. X
  829. X    end_command(window);
  830. X    
  831. X    update_buffer(buffer);
  832. X}
  833. X
  834. Xstatic void
  835. Xfree_changes(chp)
  836. XChange    *chp;
  837. X{
  838. X    while (chp != NULL) {
  839. X    Change    *tmp;
  840. X
  841. X    tmp = chp;
  842. X    chp = chp->c_next;
  843. X
  844. X    switch (tmp->c_type) {
  845. X    case C_LINE:
  846. X        throw(tmp->c_lines);
  847. X        break;
  848. X    case C_CHAR:
  849. X        free(tmp->c_chars);
  850. X        break;
  851. X    case C_DEL_CHAR:
  852. X    case C_POSITION:
  853. X        break;
  854. X    }
  855. X    chfree(tmp);
  856. X    }
  857. X}
  858. X
  859. Xstatic void
  860. Xreport(window)
  861. XXviwin    *window;
  862. X{
  863. X    if (echo & e_REPORT) {
  864. X    if (total_lines > Pn(P_report)) {
  865. X        show_message(window, "%ld more lines", total_lines);
  866. X    } else if (-total_lines > Pn(P_report)) {
  867. X        show_message(window, "%ld fewer lines", -total_lines);
  868. X    }
  869. X    }
  870. X}
  871. X
  872. Xbool_t
  873. Xset_edit(window, new_value, interactive)
  874. XXviwin        *window;
  875. XParamval    new_value;
  876. Xbool_t        interactive;
  877. X{
  878. X    Xviwin    *wp;
  879. X
  880. X    /*
  881. X     * Disallow setting of "edit" parameter to TRUE if it is FALSE.
  882. X     * Hence, this parameter can only ever be set to FALSE.
  883. X     */
  884. X    if (new_value.pv_b == TRUE && !Pb(P_edit)) {
  885. X    if (interactive) {
  886. X        show_error(window, "Can't set edit once it has been unset");
  887. X    }
  888. X    return(FALSE);
  889. X    } else {
  890. X    /*
  891. X     * Set the "noedit" flag on all current buffers,
  892. X     * but only if we are in interactive mode
  893. X     * (otherwise the window pointer is unreliable).
  894. X     * This may set the flag several times on split
  895. X     * buffers, but it's no great problem so why not.
  896. X     */
  897. X    if (interactive) {
  898. X        wp = window;
  899. X        do {
  900. X        wp->w_buffer->b_flags |= FL_NOEDIT;
  901. X        } while ((wp = next_window(wp)) != window);
  902. X    }
  903. X    return(TRUE);
  904. X    }
  905. X}
  906. END_OF_FILE
  907.   if test 21383 -ne `wc -c <'xvi/src/undo.c'`; then
  908.     echo shar: \"'xvi/src/undo.c'\" unpacked with wrong size!
  909.   fi
  910.   # end of 'xvi/src/undo.c'
  911. fi
  912. if test -f 'xvi/src/xvi.h' -a "${1}" != "-c" ; then 
  913.   echo shar: Will not clobber existing file \"'xvi/src/xvi.h'\"
  914. else
  915.   echo shar: Extracting \"'xvi/src/xvi.h'\" \(30896 characters\)
  916.   sed "s/^X//" >'xvi/src/xvi.h' <<'END_OF_FILE'
  917. X/* Copyright (c) 1990,1991,1992 Chris and John Downey */
  918. X/***
  919. X
  920. X* @(#)xvi.h    2.5 (Chris & John Downey) 9/1/92
  921. X
  922. X* program name:
  923. X    xvi
  924. X* function:
  925. X    PD version of UNIX "vi" editor, with extensions.
  926. X* module name:
  927. X    xvi.h
  928. X* module function:
  929. X    General definitions for xvi.
  930. X
  931. X    This file should really be split up into several files
  932. X    rather than being concentrated into one huge monolith.
  933. X
  934. X* history:
  935. X    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  936. X    Originally by Tim Thompson (twitch!tjt)
  937. X    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  938. X    Heavily modified by Chris & John Downey
  939. X
  940. X***/
  941. X
  942. X/***************************************************************
  943. X *                                                             *
  944. X * SECTION 1: ENVIRONMENT                                      *
  945. X *                                                             *
  946. X * Most of this section is concerned with including the right  *
  947. X * header files; we also define some things by hand if the     *
  948. X * appropriate definitions are not provided by the system.     *
  949. X *                                                             *
  950. X ***************************************************************/
  951. X
  952. X/*
  953. X * System include files ...
  954. X */
  955. X#include <stdio.h>
  956. X#include <signal.h>
  957. X#include <string.h>
  958. X
  959. X#ifdef    __STDC__
  960. X
  961. X#   define  USE_STDHDRS
  962. X#   define  STRERROR_AVAIL
  963. X#   include <errno.h>
  964. X#   include <stdarg.h>
  965. X#   define  VA_START(a, b)    va_start(a, b)
  966. X#   define  P(args)        args
  967. X
  968. X#else    /* not __STDC__ */
  969. X
  970. X#   ifdef   ultrix
  971. X#       ifdef    mips
  972. X#           define  USE_STDHDRS
  973. X#       endif   /* mips */
  974. X#   endif   /* ultrix */
  975. X#   ifdef   sparc
  976. X#       define    USE_STDHDRS
  977. X#   endif   /* sparc */
  978. X#   include <varargs.h>
  979. X#   define  VA_START(a, b)    va_start(a)
  980. X
  981. X#   define  P(args)         ()
  982. X
  983. X#   define  const
  984. X#   define  volatile
  985. X
  986. X#endif    /* not __STDC__ */
  987. X
  988. X#ifdef    USE_STDHDRS
  989. X#   include <stdlib.h>
  990. X#   include <stddef.h>
  991. X#   include <limits.h>
  992. X#else    /* USE_STDHDRS not defined */
  993. X    extern  FILE    *fopen();
  994. X    extern  char    *malloc();
  995. X    extern  char    *realloc();
  996. X    extern  char    *getenv();
  997. X    extern  long    atol();
  998. X    extern  char    *memcpy();
  999. X    extern  char    *memset();
  1000. X    extern  void    exit();
  1001. X#endif    /* USE_STDHDRS not defined */
  1002. X
  1003. X#undef USE_STDHDRS
  1004. X
  1005. X/*
  1006. X * Functions which ANSI does not specify should
  1007. X * be included in any standard header file.
  1008. X */
  1009. Xextern    int    chdir P((const char *path));
  1010. Xextern    char    *getcwd P((char *, unsigned));
  1011. Xextern    void    sleep P((unsigned seconds));
  1012. X
  1013. X/*
  1014. X * If we have ANSI C, these should be defined in limits.h:
  1015. X */
  1016. X#ifndef INT_MAX
  1017. X#   define INT_MAX    ((int) ((unsigned int) ~0 >> 1))
  1018. X#endif
  1019. X#ifndef INT_MIN
  1020. X#   define INT_MIN    (~INT_MAX)
  1021. X#endif
  1022. X#ifndef ULONG_MAX
  1023. X#   define ULONG_MAX    0xffffffff
  1024. X#endif
  1025. X
  1026. X/*
  1027. X * Macro to convert a long to an int.
  1028. X * If a long is the same as an int, this is trivial.
  1029. X */
  1030. X#define    LONG2INT(n)    (sizeof(int) == sizeof(long) ? (int) (n) : \
  1031. X             (int) ((n) > INT_MAX ? INT_MAX : \
  1032. X              ((n) < INT_MIN ? INT_MIN : (n))))
  1033. X
  1034. X
  1035. X/***************************************************************
  1036. X *                                                             *
  1037. X * SECTION 2: FUNDAMENTAL TYPES                                *
  1038. X *                                                             *
  1039. X * These types are used by other included header files.        *
  1040. X *                                                             *
  1041. X ***************************************************************/
  1042. X
  1043. X/*
  1044. X * Boolean type.
  1045. X * It would be possible to make this an enumerated type,
  1046. X * but it isn't worth the hassle - enums don't confer any
  1047. X * real advantages, and it means we can't do things like
  1048. X *
  1049. X *    bool_t    value = (i == 47);
  1050. X *
  1051. X * but instead are forced to write the abominable
  1052. X *
  1053. X *    bool_t    value = (i == 47) ? TRUE : FALSE;
  1054. X *
  1055. X * which is silly.
  1056. X */
  1057. X#undef    FALSE            /* just in case */
  1058. X#undef    TRUE
  1059. X#define    FALSE        0
  1060. X#define    TRUE        1
  1061. Xtypedef    int        bool_t;
  1062. X
  1063. X
  1064. X/***************************************************************
  1065. X *                                                             *
  1066. X * SECTION 3: FUNDAMENTAL HEADER FILES                         *
  1067. X *                                                             *
  1068. X * These header files define types which are used by Xvi.      *
  1069. X *                                                             *
  1070. X ***************************************************************/
  1071. X
  1072. X#include "virtscr.h"
  1073. X
  1074. X
  1075. X/***************************************************************
  1076. X *                                                             *
  1077. X * SECTION 4: MISCELLANEOUS DEFINITIONS                        *
  1078. X *                                                             *
  1079. X * Definitions of limits and suchlike used within the editor.  *
  1080. X *                                                             *
  1081. X ***************************************************************/
  1082. X
  1083. X/*
  1084. X * Minimum number of rows a window can have, including status line.
  1085. X */
  1086. X#define    MINROWS        2
  1087. X
  1088. X/*
  1089. X * SLOP is the amount of extra space we get for text on a line during
  1090. X * editing operations that need more space. This keeps us from calling
  1091. X * malloc every time we get a character during insert mode. No extra
  1092. X * space is allocated when the file is initially read.
  1093. X */
  1094. X#define    SLOP        10
  1095. X
  1096. X/*
  1097. X * The number of characters taken up by the line number
  1098. X * when "number" is set; up to 6 digits plus two spaces.
  1099. X */
  1100. X#define    NUM_SIZE    8
  1101. X#define    NUM_FMT        "%6ld  "
  1102. X
  1103. X/*
  1104. X * (MAX_LINE_LENGTH - 1) gives the maximum line length this editor can read in.
  1105. X * Used by fileio.c (getfile()) and pipe.c (p_read()).
  1106. X */
  1107. X#define    MAX_LINE_LENGTH    1024
  1108. X
  1109. X/*
  1110. X * Maximum value for the tabstop parameter.
  1111. X */
  1112. X#define    MAX_TABSTOP    32
  1113. X
  1114. X/*
  1115. X * Default timeout for keystrokes (in milliseconds).
  1116. X * The timeout parameter is set to this value.
  1117. X */
  1118. X#define    DEF_TIMEOUT    200
  1119. X
  1120. X
  1121. X/***************************************************************
  1122. X *                                                             *
  1123. X * SECTION 5: PARAMETER TYPE DEFINITIONS                       *
  1124. X *                                                             *
  1125. X * These are definitions of types for particular parameters.   *
  1126. X *                                                             *
  1127. X ***************************************************************/
  1128. X
  1129. X/*
  1130. X * Regular expression search modes - used in search.c.
  1131. X * These are the integer values to which the P_regextype
  1132. X * enumerated parameter may be set. Note that these values
  1133. X * are ordered; e.g. rt_GREP is considered to be earlier
  1134. X * than, and/or less than, rt_EGREP. If the types are added
  1135. X * to, this ordering must be maintained. Also note that the
  1136. X * names in the rt_strings table must follow the same order.
  1137. X */
  1138. X#define rt_TAGS        0    /* only ^ and $ are significant */
  1139. X#define rt_GREP        1    /* like grep, but with \< and \> */
  1140. X#define rt_EGREP    2    /* like egrep, but with \< and \> */
  1141. X
  1142. X/*
  1143. X * Array of names for the P_regextype enumeration, defined in
  1144. X * search.c.
  1145. X */
  1146. Xextern    char        *rt_strings[];
  1147. X
  1148. X/*
  1149. X * Integer values for the P_preserve enumerated parameter. Note that
  1150. X * the names in psv_strings must follow the same order.
  1151. X */
  1152. X#define psv_UNSAFE    0    /* never preserve buffer before writing */
  1153. X#define psv_STANDARD    1    /*
  1154. X                 * only preserve buffer before writing
  1155. X                 * if it hasn't been preserved recently
  1156. X                 */
  1157. X#define psv_SAFE    2    /* always preserve buffer before writing */
  1158. X#define psv_PARANOID    3    /*
  1159. X                 * like psv_SAFE, but never remove the
  1160. X                 * preserve file
  1161. X                 */
  1162. X
  1163. X/*
  1164. X * Array of names for the P_preserve enumeration, defined in
  1165. X * search.c.
  1166. X */
  1167. Xextern    char        *psv_strings[];
  1168. X
  1169. X/*
  1170. X * Integer values for the P_format enumerated parameter. These are for
  1171. X * the formats we know about so far. Note that the entries in
  1172. X * fmt_strings & tftable (defined in fileio.c) must follow the same order.
  1173. X */
  1174. X#define    fmt_CSTRING    0
  1175. X#define    fmt_MACINTOSH    1
  1176. X#define    fmt_MSDOS    2
  1177. X#define    fmt_OS2        3
  1178. X#define    fmt_QNX        4
  1179. X#define    fmt_TOS        5
  1180. X#define    fmt_UNIX    6
  1181. X
  1182. X/*
  1183. X * Array of names for the P_format enumeration.
  1184. X */
  1185. Xextern    char        *fmt_strings[];
  1186. X
  1187. X/*
  1188. X * Integer values for the P_jumpscroll enumerated parameter. Note that
  1189. X * the entries in js_strings (defined in param.c) must follow the same
  1190. X * order.
  1191. X */
  1192. X#define    js_OFF        0
  1193. X#define    js_AUTO        1
  1194. X#define    js_ON        2
  1195. X
  1196. X/***************************************************************
  1197. X *                                                             *
  1198. X * SECTION 6: EDITOR TYPE DEFINITIONS                          *
  1199. X *                                                             *
  1200. X ***************************************************************/
  1201. X
  1202. X/*
  1203. X * Possible editor states.
  1204. X */
  1205. Xtypedef enum {
  1206. X    NORMAL,            /* command mode */
  1207. X    INSERT,            /* insert mode */
  1208. X    REPLACE,            /* overwrite mode */
  1209. X    CMDLINE,            /* on the : command line */
  1210. X    DISPLAY            /* in display mode (e.g. g//p or :set all) */
  1211. X} state_t;
  1212. X
  1213. Xextern    state_t        State;    /* defined in main.c */
  1214. X
  1215. X/*
  1216. X * Possible return values for cmd_input(), which deals with command
  1217. X * line input. This is for commands starting with :, /, ? and !.
  1218. X */
  1219. Xtypedef enum {
  1220. X    cmd_COMPLETE,        /* user hit return (cmd line available) */
  1221. X    cmd_INCOMPLETE,        /* not finished typing command line yet */
  1222. X    cmd_CANCEL            /* user aborted command line */
  1223. X} Cmd_State;
  1224. X
  1225. X/*
  1226. X * Possible directions for searching, and opening lines.
  1227. X */
  1228. X#define    FORWARD        0
  1229. X#define    BACKWARD    1
  1230. X
  1231. X/*
  1232. X * Line structure and its friends.
  1233. X *
  1234. X * The structure used to hold a line; this is used to form
  1235. X * a doubly-linked list of the lines comprising a file.
  1236. X *
  1237. X * The definition for MAX_LINENO depends on the type of
  1238. X * l_number, and on the size of the machine; we are fairly
  1239. X * safe setting all bits here so long as l_number is always
  1240. X * an unsigned type. Should really use a lineno_t here, and
  1241. X * get rid of the need for a maximum lineno.
  1242. X */
  1243. Xtypedef    struct    line {
  1244. X    struct line        *l_prev;    /* previous line */
  1245. X    struct line        *l_next;    /* next line */
  1246. X    char        *l_text;    /* text for this line */
  1247. X    int            l_size;        /* actual size of space at 's' */
  1248. X    unsigned long    l_number;    /* line "number" */
  1249. X} Line;
  1250. X
  1251. X#define    MAX_LINENO    ULONG_MAX
  1252. X
  1253. X/*
  1254. X * These pseudo-functions operate on lines in a buffer, returning TRUE
  1255. X * or FALSE according to whether l1 is later or earlier than l2.
  1256. X * Note that there is no macro for "same", which is excluded by both
  1257. X * "earlier" and "later".
  1258. X */
  1259. X#define    later(l1, l2)    ((l1)->l_number > (l2)->l_number)
  1260. X#define    earlier(l1, l2)    ((l1)->l_number < (l2)->l_number)
  1261. X
  1262. X/*
  1263. X * This macro gives the line number of line 'l' in buffer 'b'.
  1264. X */
  1265. X#define    lineno(b, l)    ((l)->l_number)
  1266. X
  1267. X/*
  1268. X * Easy ways of finding out whether a given line is the first
  1269. X * or last line of a buffer, without needing a buffer pointer.
  1270. X */
  1271. X#define    is_lastline(lp)    ((lp)->l_number == MAX_LINENO)
  1272. X#define    is_line0(lp)    ((lp)->l_number == 0)
  1273. X
  1274. X
  1275. X/*
  1276. X * Structure used to hold a position in a file;
  1277. X * this is just a pointer to the line, and an index.
  1278. X */
  1279. Xtypedef    struct    position {
  1280. X    Line        *p_line;    /* line we're referencing */
  1281. X    int            p_index;    /* position within that line */
  1282. X} Posn;
  1283. X
  1284. X/*
  1285. X * This is stuff to do with marks - it should be privately defined
  1286. X * in mark.c, but it needs to be related to each individual buffer.
  1287. X */
  1288. X#define    NMARKS    10        /* max. # of marks that can be saved */
  1289. X
  1290. Xtypedef    struct    mark {
  1291. X    char        m_name;
  1292. X    Posn        m_pos;
  1293. X} Mark;
  1294. X
  1295. X/*
  1296. X * Structure used to record a single change to a buffer.
  1297. X * A change may either be a number of lines replaced with a
  1298. X * new set, a number of characters removed or a number of
  1299. X * characters replaced with a new set. Character changes
  1300. X * never straddle line boundaries. A list of these
  1301. X * structures forms a complex change. There is also a fourth
  1302. X * type of "change", which does not actually change the
  1303. X * buffer, but is simply a record of the cursor position at
  1304. X * the time of the start of the change. This is needed so
  1305. X * that the cursor returns to the correct position after an
  1306. X * "undo".
  1307. X *
  1308. X * This entire structure is only used in undo.c and alloc.c, and
  1309. X * no other code should touch it.
  1310. X */
  1311. Xtypedef    struct change {
  1312. X    struct change    *c_next;
  1313. X    enum {
  1314. X    C_LINE,
  1315. X    C_CHAR,
  1316. X    C_DEL_CHAR,
  1317. X    C_POSITION
  1318. X    }            c_type;
  1319. X    unsigned long    c_lineno;
  1320. X    union {
  1321. X    struct {
  1322. X        long    cul_nlines;
  1323. X        Line    *cul_lines;
  1324. X    }    cu_l;
  1325. X    struct {
  1326. X        int        cuc_index;
  1327. X        int        cuc_nchars;
  1328. X        char    *cuc_chars;
  1329. X    }    cu_c;
  1330. X    struct {
  1331. X        long    cup_line;
  1332. X        int        cup_index;
  1333. X    }    cu_p;
  1334. X    }            c_u;
  1335. X} Change;
  1336. X
  1337. X#define    c_nlines    c_u.cu_l.cul_nlines
  1338. X#define    c_lines        c_u.cu_l.cul_lines
  1339. X#define    c_index        c_u.cu_c.cuc_index
  1340. X#define    c_nchars    c_u.cu_c.cuc_nchars
  1341. X#define    c_chars        c_u.cu_c.cuc_chars
  1342. X#define    c_pline        c_u.cu_p.cup_line
  1343. X#define    c_pindex    c_u.cu_p.cup_index
  1344. X
  1345. X/*
  1346. X * Variable-length FIFO queue of characters.
  1347. X */
  1348. Xtypedef struct
  1349. X{
  1350. X    char        *fxb_chars;    /* pointer to allocated space */
  1351. X    unsigned    fxb_max;    /* size of allocated space */
  1352. X    unsigned    fxb_rcnt;    /* number of characters read */
  1353. X    unsigned    fxb_wcnt;    /* number of characters written */
  1354. X/* public: */
  1355. X/*
  1356. X * Initialize a Flexbuf.
  1357. X */
  1358. X#define            flexnew(f)    ((f)->fxb_wcnt = (f)->fxb_max = 0)
  1359. X/*
  1360. X * Reset a Flexbuf by clearing its contents, but without freeing the
  1361. X * dynamically allocated space.
  1362. X */
  1363. X#define            flexclear(f)    ((f)->fxb_wcnt = 0)
  1364. X/*
  1365. X * Test whether a Flexbuf is empty.
  1366. X */
  1367. X#define            flexempty(f)    ((f)->fxb_rcnt >= (f)->fxb_wcnt)
  1368. X/*
  1369. X * Remove last character from a Flexbuf.
  1370. X */
  1371. X#define            flexrmchar(f)    (!flexempty(f) && --(f)->fxb_wcnt)
  1372. X/*
  1373. X * Return number of characters in a Flexbuf.
  1374. X */
  1375. X#define            flexlen(f)    (flexempty(f) ? 0 : \
  1376. X                     (f)->fxb_wcnt - (f)->fxb_rcnt)
  1377. X}
  1378. XFlexbuf;
  1379. X
  1380. X/*
  1381. X * Structure used to hold all information about a "buffer" -
  1382. X * i.e. the representation of a file in memory.
  1383. X */
  1384. Xtypedef struct buffer {
  1385. X    Line        *b_line0;    /* ptr to zeroth line of file */
  1386. X    Line        *b_file;    /* ptr to first line of file */
  1387. X    Line        *b_lastline;    /* ptr to (n+1)th line of file */
  1388. X
  1389. X    /*
  1390. X     * All of these are allocated, and should be freed
  1391. X     * before assigning any new value to them.
  1392. X     */
  1393. X    char        *b_filename;    /* file name, if any */
  1394. X    char        *b_tempfname;    /* name for temporary copy of file */
  1395. X
  1396. X    unsigned int     b_flags;    /* flags */
  1397. X
  1398. X    int            b_nwindows;    /* no of windows open on this buffer */
  1399. X
  1400. X    /*
  1401. X     * The following only used in mark.c.
  1402. X     */
  1403. X    Mark        b_mlist[NMARKS];    /* current marks */
  1404. X    Mark        b_pcmark;        /* previous context mark */
  1405. X    bool_t        b_pcvalid;        /* true if pcmark is valid */
  1406. X
  1407. X    /*
  1408. X     * The following only used in undo.c.
  1409. X     */
  1410. X    unsigned int    b_nlevels;    /* number of brackets surrounding */
  1411. X                    /* current change to buffer */
  1412. X    Change        *b_change;    /* ptr to list of changes made */
  1413. X
  1414. X} Buffer;
  1415. X
  1416. X/*
  1417. X * Definitions for the "flags" field of a buffer.
  1418. X */
  1419. X#define    FL_MODIFIED    0x1
  1420. X#define    FL_READONLY    0x2
  1421. X#define    FL_NOEDIT    0x4
  1422. X#define    is_modified(b)    ((b)->b_flags & FL_MODIFIED)
  1423. X#define    is_readonly(b)    (Pb(P_readonly) || ((b)->b_flags & FL_READONLY))
  1424. X#define    not_editable(b)    ((b)->b_flags & FL_NOEDIT)
  1425. X
  1426. X/*
  1427. X * Structure used to hold information about a "window" -
  1428. X * this is intimately associated with the Buffer structure.
  1429. X */
  1430. Xtypedef struct window {
  1431. X    Posn        *w_cursor;    /* cursor's position in buffer */
  1432. X
  1433. X    Buffer        *w_buffer;    /* buffer we are a window into */
  1434. X
  1435. X    Line        *w_topline;    /* line at top of screen */
  1436. X    Line        *w_botline;    /* line below bottom of screen */
  1437. X
  1438. X    VirtScr        *w_vs;        /* virtual screen for window */
  1439. X
  1440. X    unsigned        w_nrows;    /* number of rows in window */
  1441. X    unsigned        w_ncols;    /* number of columns in window */
  1442. X    unsigned        w_winpos;    /* row of top line of window */
  1443. X    unsigned        w_cmdline;    /* row of window command line */
  1444. X
  1445. X    /*
  1446. X     * These are used by the ^O command to store the previous
  1447. X     * size of the window so that we can return to it.
  1448. X     */
  1449. X    int            w_2winpos;    /* last row of top line of window */
  1450. X    int            w_2nrows;    /* last no of rows in buffer window */
  1451. X    int            w_2cmdline;    /* last row of window command line */
  1452. X
  1453. X
  1454. X    /*
  1455. X     * Allocated within screen.c.
  1456. X     */
  1457. X    Flexbuf        w_statusline;    /* status information on status line */
  1458. X
  1459. X
  1460. X    /*
  1461. X     * These elements are related to the cursor's position in the window.
  1462. X     */
  1463. X    int            w_row, w_col;    /* cursor's position in window */
  1464. X
  1465. X    int            w_virtcol;    /* column number of the file's actual */
  1466. X                    /* line, as opposed to the column */
  1467. X                    /* number we're at on the screen. */
  1468. X                    /* This makes a difference on lines */
  1469. X                    /* which span more than one screen */
  1470. X                    /* line. */
  1471. X
  1472. X    int            w_curswant;    /* The column we'd like to be at. */
  1473. X                    /* This is used to try to stay in */
  1474. X                    /* the same column through up/down */
  1475. X                    /* cursor motions. */
  1476. X
  1477. X    bool_t        w_set_want_col;    /* If set, then update w_curswant */
  1478. X                    /* the next time through cursupdate() */
  1479. X                    /* to the current virtual column */
  1480. X
  1481. X    int            w_c_line_size;    /* current size of cursor line */
  1482. X
  1483. X    bool_t        w_curs_new;    /* true if cursor should be updated */
  1484. X
  1485. X    /*
  1486. X     * The following only used in windows.c.
  1487. X     */
  1488. X    struct window    *w_last;    /* first and last pointers */
  1489. X    struct window    *w_next;
  1490. X} Xviwin;
  1491. X
  1492. X/*
  1493. X * Values returned by inc() & dec().
  1494. X */
  1495. Xenum mvtype {
  1496. X    mv_NOMOVE = -1,    /* at beginning or end of buffer */
  1497. X    mv_SAMELINE = 0,    /* still within same line */
  1498. X    mv_CHLINE = 1,    /* changed to different line */
  1499. X    mv_EOL = 2        /* in same line, at terminating '\0' */
  1500. X};
  1501. X
  1502. X/*
  1503. X * Number of input characters since the last buffer preservation.
  1504. X */
  1505. Xextern volatile int    keystrokes;
  1506. X
  1507. X/*
  1508. X * Minimum number of keystrokes after which we do an automatic
  1509. X * preservation of all modified buffers.
  1510. X */
  1511. X#define PSVKEYS        60
  1512. X
  1513. X/*
  1514. X * Exceptional return values for get_file().
  1515. X */
  1516. X#define gf_NEWFILE    ((long)-1)    /* no such file */
  1517. X#define gf_CANTOPEN    ((long)-2)    /* error opening file */
  1518. X#define gf_IOERR    ((long)-3)    /* error reading from file */
  1519. X#define gf_NOMEM    ((long)-4)    /* not enough memory */
  1520. X
  1521. X/*
  1522. X * Editor input events. Handled by xvi_handle_event().
  1523. X */
  1524. Xtypedef struct event {
  1525. X    enum {
  1526. X    Ev_char,
  1527. X    Ev_timeout
  1528. X    }            ev_type;
  1529. X    union {
  1530. X    /* Ev_char: */
  1531. X    int    evu_inchar;
  1532. X
  1533. X    /* Ev_timeout: */
  1534. X    }            ev_u;
  1535. X} xvEvent;
  1536. X
  1537. X#define    ev_inchar    ev_u.evu_inchar
  1538. X
  1539. X
  1540. X/***************************************************************
  1541. X *                                                             *
  1542. X * SECTION 7: MISCELLANEOUS MACROS                             *
  1543. X *                                                             *
  1544. X ***************************************************************/
  1545. X
  1546. X
  1547. X/***************************************************************
  1548. X *                                                             *
  1549. X * SECTION 8: XVI-LOCAL HEADER FILES                           *
  1550. X *                                                             *
  1551. X * Various subsidiary header files with definitions relating   *
  1552. X * to particular areas of the editor (or its environment).     *
  1553. X * Note that these header files may use definitions in this    *
  1554. X * file, so are included after all types are defined.          *
  1555. X *                                                             *
  1556. X ***************************************************************/
  1557. X
  1558. X#include "ascii.h"
  1559. X#include "param.h"
  1560. X#include "ptrfunc.h"
  1561. X
  1562. X
  1563. X/***************************************************************
  1564. X *                                                             *
  1565. X * SECTION 9: SYSTEM-SPECIFIC HEADER FILES                     *
  1566. X *                                                             *
  1567. X ***************************************************************/
  1568. X
  1569. X/*
  1570. X * Include file for system interface module.
  1571. X * We must have one of these.
  1572. X */
  1573. X
  1574. X#ifdef    ATARI
  1575. X#   include "tos.h"
  1576. X#   define    GOT_OS
  1577. X#endif
  1578. X
  1579. X#ifdef    UNIX
  1580. X#   include "unix.h"
  1581. X#   define    GOT_OS
  1582. X#endif
  1583. X
  1584. X#ifdef    OS2
  1585. X    /*
  1586. X     * Microsoft's wonderful compiler defines MSDOS, even when
  1587. X     * we're compiling for OS/2, but it doesn't define OS2.
  1588. X     * Ingenious, eh?
  1589. X     */
  1590. X#   undef MSDOS
  1591. X#   include "os2vio.h"
  1592. X#   define    GOT_OS
  1593. X#endif
  1594. X
  1595. X#ifdef    MSDOS
  1596. X#   include "msdos.h"
  1597. X#   define    GOT_OS
  1598. X#endif
  1599. X
  1600. X#ifdef    QNX
  1601. X#   include "qnx.h"
  1602. X#   define    GOT_OS
  1603. X#endif
  1604. X
  1605. X#ifndef    GOT_OS
  1606. X    no system-specific include file found
  1607. X#endif
  1608. X
  1609. X
  1610. X/***************************************************************
  1611. X *                                                             *
  1612. X * SECTION 10: GLOBAL VARIABLE DECLARATIONS                    *
  1613. X *                                                             *
  1614. X ***************************************************************/
  1615. X
  1616. X/*
  1617. X * Miscellaneous global vars.
  1618. X */
  1619. Xextern    Buffer        *curbuf;    /* current buffer */
  1620. Xextern    Xviwin        *curwin;    /* current window */
  1621. X
  1622. Xextern    int        indentchars;    /* auto-indentation on current line */
  1623. Xextern    char        *altfilename;    /* name of current alternate file */
  1624. Xextern    char        Version[];    /* version string for :ve command */
  1625. X
  1626. X/*
  1627. X * This flag is set when a keyboard interrupt is received.
  1628. X */
  1629. Xextern volatile unsigned char kbdintr;
  1630. X
  1631. X/*
  1632. X * This one indicates whether we should display the "Interrupted"
  1633. X * message.
  1634. X */
  1635. Xextern    bool_t        imessage;
  1636. X
  1637. X/*
  1638. X * This variable (defined in main.c) is a bitmap which controls the
  1639. X * verbosity of screen output. The meanings of the individual bits
  1640. X * are:
  1641. X *
  1642. X *    e_CHARUPDATE means it's OK to update individual characters in
  1643. X *    any window.
  1644. X *
  1645. X *    e_SCROLL means it's OK to scroll any area of the screen up or
  1646. X *    down.
  1647. X *
  1648. X *    e_REPORT means it's OK for report() to report the number of
  1649. X *    lines inserted or deleted.
  1650. X *
  1651. X *    e_SHOWINFO means it's OK for show_file_info() to display file
  1652. X *    information for any buffer.
  1653. X *
  1654. X *    e_BEEP: not implemented yet.
  1655. X *
  1656. X *    e_REGERR means it's OK for functions in search.c to display
  1657. X *    messages which may have resulted from an invalid regular
  1658. X *    expression string.
  1659. X *
  1660. X *    e_NOMATCH means it's OK for functions in search.c to complain
  1661. X *    if they fail to match a regular expression at least once.
  1662. X *
  1663. X * If we're reading an input sequence & e_CHARUPDATE & e_SCROLL are
  1664. X * turned off, no screen updating will be done until an ESC is
  1665. X * received.
  1666. X */
  1667. Xextern    unsigned    echo;
  1668. X
  1669. X#define    e_CHARUPDATE    1
  1670. X#define    e_SCROLL    2
  1671. X#define    e_REPORT    4
  1672. X#define    e_SHOWINFO    010
  1673. X#define    e_BEEP        020
  1674. X#define    e_REGERR    040
  1675. X#define    e_NOMATCH    0100
  1676. X
  1677. X#define e_ANY        0xffff
  1678. X
  1679. X
  1680. X/***************************************************************
  1681. X *                                                             *
  1682. X * SECTION 11: FUNCTION DECLARATIONS                           *
  1683. X *                                                             *
  1684. X ***************************************************************/
  1685. X
  1686. X/*
  1687. X * Declarations of all the routines exported from the various .c files.
  1688. X */
  1689. X
  1690. X/*
  1691. X * main.c
  1692. X */
  1693. Xextern    Xviwin    *xvi_startup P((VirtScr *, int, char **, char *));
  1694. X
  1695. X/*
  1696. X * alloc.c
  1697. X */
  1698. Xextern    Change    *challoc P((void));
  1699. Xextern    void    chfree P((Change *));
  1700. Xextern    char    *alloc P((unsigned int));
  1701. Xextern    char    *strsave P((const char *));
  1702. Xextern    Line    *newline P((int));
  1703. Xextern    bool_t    bufempty P((Buffer *));
  1704. Xextern    bool_t    buf1line P((Buffer *));
  1705. Xextern    bool_t    endofline P((Posn *));
  1706. Xextern    bool_t    grow_line P((Line *, int));
  1707. Xextern    void    throw P((Line *));
  1708. X
  1709. X/*
  1710. X * ascii.c
  1711. X */
  1712. Xextern unsigned vischar P((int, char **, int));
  1713. X
  1714. X/*
  1715. X * buffers.c
  1716. X */
  1717. Xextern    Buffer    *new_buffer P((void));
  1718. Xextern    void    free_buffer P((Buffer *));
  1719. Xextern    bool_t    clear_buffer P((Buffer *));
  1720. Xextern    int    nbuffers;
  1721. X
  1722. X/*
  1723. X * edit.c
  1724. X */
  1725. Xextern    bool_t    i_proc P((int));
  1726. Xextern    bool_t    r_proc P((int));
  1727. Xextern    void    startinsert P((int));
  1728. Xextern    void    startreplace P((int));
  1729. Xextern    char    *mkstr P((int));
  1730. X
  1731. X/*
  1732. X * events.c
  1733. X */
  1734. Xextern    long    xvi_handle_event P((xvEvent *));
  1735. X
  1736. X/*
  1737. X * cmdline.c
  1738. X */
  1739. Xextern    void    do_colon P((char *, bool_t));
  1740. Xextern    void    wait_return P((void));
  1741. X
  1742. X/*
  1743. X * cursor.c
  1744. X */
  1745. Xextern    void    cursupdate P((Xviwin *));
  1746. Xextern    void    curs_horiz P((Xviwin *, int));
  1747. X
  1748. X/*
  1749. X * ex_cmds1.c
  1750. X */
  1751. Xextern    void    do_quit P((Xviwin *, bool_t));
  1752. Xextern    void    do_split_window P((Xviwin *));
  1753. Xextern    bool_t    do_buffer P((Xviwin *, char *));
  1754. Xextern    void    do_close_window P((Xviwin *, bool_t));
  1755. Xextern    void    do_xit P((Xviwin *));
  1756. Xextern    bool_t    do_edit P((Xviwin *, bool_t, char *));
  1757. Xextern    void    do_args P((Xviwin *));
  1758. Xextern    void    do_next P((Xviwin *, int, char **, bool_t));
  1759. Xextern    void    do_rewind P((Xviwin *, bool_t));
  1760. Xextern    bool_t    do_write P((Xviwin *, char *, Line *, Line *, bool_t));
  1761. Xextern    void    do_wq P((Xviwin *, char *, bool_t));
  1762. Xextern    void    do_read P((Xviwin *, char *, Line *));
  1763. Xextern    void    do_alt_edit P((Xviwin *));
  1764. Xextern    void    do_compare P((void));
  1765. X
  1766. X/*
  1767. X * ex_cmds2.c
  1768. X */
  1769. Xextern    void    do_shell P((Xviwin *));
  1770. Xextern    void    do_shcmd P((Xviwin *, char *));
  1771. Xextern    void    do_suspend P((Xviwin *));
  1772. Xextern    void    do_equals P((Xviwin *, Line *));
  1773. Xextern    void    do_help P((Xviwin *));
  1774. Xextern    bool_t    do_source P((bool_t, char *));
  1775. Xextern    char    *do_chdir P((char *));
  1776. Xextern    void    do_cdmy P((int, Line *, Line *, Line *));
  1777. X
  1778. X/*
  1779. X * fileio.c
  1780. X */
  1781. Xextern    bool_t    set_format P((Xviwin *, Paramval, bool_t));
  1782. Xextern    long    get_file P((Xviwin *, char *, Line **, Line **, char *,
  1783. X                            char *));
  1784. Xextern    bool_t    writeit P((Xviwin *, char *, Line *, Line *, bool_t));
  1785. Xextern    bool_t    put_file P((Xviwin *, FILE *, Line *, Line *,
  1786. X                unsigned long *, unsigned long *));
  1787. X
  1788. X/*
  1789. X * find.c
  1790. X */
  1791. Xextern    Posn    *searchc P((int, int, int, int));
  1792. Xextern    Posn    *crepsearch P((Buffer *, int, int));
  1793. Xextern    Posn    *showmatch P((void));
  1794. Xextern    Posn    *find_pattern P((char *, int, int));
  1795. Xextern    Posn    *fwd_word P((Posn *, int, bool_t));
  1796. Xextern    Posn    *bck_word P((Posn *, int, bool_t));
  1797. Xextern    Posn    *end_word P((Posn *, int, bool_t));
  1798. Xextern    bool_t    dosearch P((Xviwin *, char *, int));
  1799. X
  1800. X/*
  1801. X * flexbuf.c
  1802. X */
  1803. Xextern    bool_t    flexaddch P((Flexbuf *, int));
  1804. Xextern    char    *flexgetstr P((Flexbuf *));
  1805. Xextern    int    flexpopch P((Flexbuf *));
  1806. Xextern    void    flexdelete P((Flexbuf *));
  1807. Xextern    bool_t    vformat P((Flexbuf *, char *, va_list));
  1808. Xextern    bool_t    lformat P((Flexbuf *, char *, ...));
  1809. X
  1810. X/*
  1811. X * map.c
  1812. X */
  1813. Xextern    void    stuff P((char *, ...));
  1814. Xextern    int    map_getc P((void));
  1815. Xextern    void    map_char P((int));
  1816. Xextern    void    map_timeout P((void));
  1817. Xextern    bool_t    map_waiting P((void));
  1818. Xextern    int    mapped_char P((int));
  1819. Xextern    void    xvi_map P((int, char **, bool_t, bool_t));
  1820. Xextern    void    xvi_keymap P((char *, char *));
  1821. Xextern    void    xvi_unmap P((int, char **, bool_t, bool_t));
  1822. Xextern    void    do_unmap P((int, char **, bool_t, bool_t));
  1823. X
  1824. X/*
  1825. X * mark.c
  1826. X */
  1827. Xextern    void    init_marks P((Buffer *));
  1828. Xextern    bool_t    setmark P((int, Buffer *, Posn *));
  1829. Xextern    void    setpcmark P((Xviwin *));
  1830. Xextern    Posn    *getmark P((int, Buffer *));
  1831. Xextern    void    clrmark P((Line *, Buffer *));
  1832. X
  1833. X/*
  1834. X * misccmds.c
  1835. X */
  1836. Xextern    bool_t    openfwd P((bool_t));
  1837. Xextern    bool_t    openbwd P((void));
  1838. Xextern    long    cntllines P((Line *, Line *));
  1839. Xextern    long    cntplines P((Xviwin *, Line *, Line *));
  1840. Xextern    long    plines P((Xviwin *, Line *));
  1841. Xextern    Line    *gotoline P((Buffer *, unsigned long));
  1842. Xextern    int    get_indent P((Line *));
  1843. Xextern    int    set_indent P((Line *, int));
  1844. Xextern    void    tabinout P((int, Line *, Line *));
  1845. Xextern    void    makeargv P((char *, int *, char ***, char *));
  1846. X
  1847. X/*
  1848. X * mouse.c
  1849. X */
  1850. Xextern    void    mouseclick P((int, int));
  1851. Xextern    void    mousedrag P((int, int, int, int));
  1852. X
  1853. X/*
  1854. X * movement.c
  1855. X */
  1856. Xextern    int    shiftdown P((Xviwin *, unsigned));
  1857. Xextern    int    shiftup P((Xviwin *, unsigned));
  1858. Xextern    void    scrolldown P((Xviwin *, unsigned));
  1859. Xextern    void    scrollup P((Xviwin *, unsigned));
  1860. Xextern    bool_t    oneup P((Xviwin *, long));
  1861. Xextern    bool_t    onedown P((Xviwin *, long));
  1862. Xextern    bool_t    one_left P((Xviwin *, bool_t));
  1863. Xextern    bool_t    one_right P((Xviwin *, bool_t));
  1864. Xextern    void    begin_line P((Xviwin *, bool_t));
  1865. Xextern    void    coladvance P((Xviwin *, int));
  1866. Xextern    void    do_goto P((long));
  1867. Xextern    void    move_cursor P((Xviwin *, Line *, int));
  1868. Xextern    void    move_window_to_cursor P((Xviwin *));
  1869. Xextern    void    move_cursor_to_window P((Xviwin *));
  1870. X
  1871. X/*
  1872. X * normal.c
  1873. X */
  1874. Xextern    bool_t    normal P((int));
  1875. X
  1876. X/*
  1877. X * param.c
  1878. X */
  1879. Xextern    void    init_params P((void));
  1880. Xextern    void    do_set P((Xviwin *, int, char **, bool_t));
  1881. Xextern    void    set_param P((int, ...));
  1882. X
  1883. X/*
  1884. X * pipe.c
  1885. X */
  1886. Xextern    void    specify_pipe_range P((Xviwin *, Line *, Line *));
  1887. Xextern    void    do_pipe P((Xviwin *, char *));
  1888. X
  1889. X/*
  1890. X * preserve.c
  1891. X */
  1892. Xextern    bool_t    preservebuf P((Xviwin *));
  1893. Xextern    bool_t    do_preserve P((void));
  1894. X
  1895. X/*
  1896. X * ptrfunc.c
  1897. X */
  1898. Xextern    enum mvtype    inc P((Posn *));
  1899. Xextern    enum mvtype    dec P((Posn *));
  1900. Xextern    void    pswap P((Posn *, Posn *));
  1901. Xextern    bool_t    lt P((Posn *, Posn *));
  1902. X
  1903. X/*
  1904. X * screen.c
  1905. X */
  1906. Xextern    void    init_screen P((Xviwin *));
  1907. Xextern    void    updateline P((Xviwin *));
  1908. Xextern    void    update_sline P((Xviwin *));
  1909. Xextern    void    update_window P((Xviwin *));
  1910. Xextern    void    update_all P((void));
  1911. Xextern    void    redraw_screen P((void));
  1912. Xextern    void    clear P((Xviwin *));
  1913. Xextern    void    s_ins P((Xviwin *, int, int));
  1914. Xextern    void    s_del P((Xviwin *, int, int));
  1915. Xextern    void    s_inschar P((Xviwin *, int));
  1916. Xextern    void    wind_goto P((Xviwin *));
  1917. Xextern    void    cmd_init P((Xviwin *, int));
  1918. Xextern    Cmd_State
  1919. X        cmd_input P((Xviwin *, int));
  1920. Xextern    char    *get_cmd P((Xviwin *));
  1921. Xextern    void    gotocmd P((Xviwin *, bool_t));
  1922. Xextern    void    prompt P((char *));
  1923. Xextern    void    beep P((Xviwin *));
  1924. Xextern    void    disp_init P((Xviwin *, char *(*) P((void)), int, bool_t));
  1925. Xextern    bool_t    disp_screen P((Xviwin *));
  1926. X
  1927. X/*
  1928. X * search.c
  1929. X */
  1930. Xextern    Posn    *search P((Xviwin *, Line *, int, int, char **));
  1931. Xextern    Posn    *nsearch P((Xviwin *, Line *, int, int, char *));
  1932. Xextern    Line    *linesearch P((Xviwin *, int, char **));
  1933. Xextern    void    do_global P((Xviwin *, Line *, Line *, char *, bool_t));
  1934. Xextern    long    do_substitute P((Xviwin *, Line *, Line *, char *));
  1935. Xextern    long    do_ampersand P((Xviwin *, Line *, Line *, char *));
  1936. Xextern    long    do_tilde P((Xviwin *, Line *, Line *, char *));
  1937. X
  1938. X/*
  1939. X * signal.c
  1940. X */
  1941. Xextern    void    ignore_signals P((void));
  1942. Xextern    void    catch_signals P((void));
  1943. X
  1944. X/*
  1945. X * status.c
  1946. X */
  1947. Xextern    void    init_sline P((Xviwin *));
  1948. Xextern    void    show_message P((Xviwin *, char *, ...));
  1949. Xextern    void    show_error P((Xviwin *, char *, ...));
  1950. Xextern    void    show_file_info P((Xviwin *));
  1951. X
  1952. X/*
  1953. X * tags.c
  1954. X */
  1955. Xextern    bool_t    set_tags P((Xviwin *, Paramval, bool_t));
  1956. Xextern    void    tagword P((void));
  1957. Xextern    bool_t    do_tag P((Xviwin *, char *, bool_t, bool_t, bool_t));
  1958. X
  1959. X/*
  1960. X * undo.c
  1961. X */
  1962. Xextern    void    init_undo P((Buffer *));
  1963. Xextern    bool_t    start_command P((Xviwin *));
  1964. Xextern    void    end_command P((Xviwin *));
  1965. Xextern    void    replchars P((Xviwin *, Line *, int, int, char *));
  1966. Xextern    void    repllines P((Xviwin *, Line *, long, Line *));
  1967. Xextern    void    replbuffer P((Xviwin *, Line *));
  1968. Xextern    void    undo P((Xviwin *));
  1969. Xextern    bool_t    set_edit P((Xviwin *, Paramval, bool_t));
  1970. X
  1971. X/*
  1972. X * windows.c
  1973. X */
  1974. Xextern    Xviwin    *init_window P((VirtScr *));
  1975. Xextern    void    free_window P((Xviwin *));
  1976. Xextern    Xviwin    *split_window P((Xviwin *));
  1977. Xextern    void    map_window_onto_buffer P((Xviwin *, Buffer *));
  1978. Xextern    void    unmap_window P((Xviwin *));
  1979. Xextern    Xviwin    *next_window P((Xviwin *));
  1980. Xextern    Xviwin    *find_window P((Xviwin *, char *));
  1981. Xextern    void    resize_window P((Xviwin *, int));
  1982. Xextern    int    move_sline P((Xviwin *, int));
  1983. Xextern    void    update_buffer P((Buffer *));
  1984. Xextern    bool_t    can_split P((void));
  1985. X
  1986. X/*
  1987. X * yankput.c
  1988. X */
  1989. Xextern    void    init_yankput P((void));
  1990. Xextern    bool_t    do_yank P((Buffer *, Posn *, Posn *, bool_t, int));
  1991. Xextern    bool_t    yank_str P((int, char *, bool_t));
  1992. Xextern    void    do_put P((Xviwin *, Posn *, int, int));
  1993. Xextern    void    yp_stuff_input P((Xviwin *, int, bool_t));
  1994. Xextern    void    yp_push_deleted P((void));
  1995. END_OF_FILE
  1996.   if test 30896 -ne `wc -c <'xvi/src/xvi.h'`; then
  1997.     echo shar: \"'xvi/src/xvi.h'\" unpacked with wrong size!
  1998.   fi
  1999.   # end of 'xvi/src/xvi.h'
  2000. fi
  2001. echo shar: End of archive 8 \(of 18\).
  2002. cp /dev/null ark8isdone
  2003. MISSING=""
  2004. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  2005.     if test ! -f ark${I}isdone ; then
  2006.     MISSING="${MISSING} ${I}"
  2007.     fi
  2008. done
  2009. if test "${MISSING}" = "" ; then
  2010.     echo You have unpacked all 18 archives.
  2011.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2012. else
  2013.     echo You still must unpack the following archives:
  2014.     echo "        " ${MISSING}
  2015. fi
  2016. exit 0
  2017. exit 0 # Just in case...
  2018.