home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / x / xvisrc.zoo / ex_cmds1.c < prev    next >
C/C++ Source or Header  |  1992-07-28  |  19KB  |  860 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)ex_cmds1.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     ex_cmds1.c
  14. * module function:
  15.     File, window and buffer-related command functions
  16.     for ex (colon) commands.
  17. * history:
  18.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  19.     Originally by Tim Thompson (twitch!tjt)
  20.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  21.     Heavily modified by Chris & John Downey
  22.  
  23. ***/
  24.  
  25. #include "xvi.h"
  26.  
  27. #ifdef    MEGAMAX
  28. overlay "ex_cmds1"
  29. #endif
  30.  
  31. static    char    **files;    /* list of input files */
  32. static    int    numfiles;    /* number of input files */
  33. static    int    curfile;    /* number of the current file */
  34.  
  35. char        *altfilename;
  36. static    long    altfileline;
  37.  
  38. static    char    nowrtmsg[] = "No write since last change (use ! to override)";
  39. static    char    nowrtbufs[] = "Some buffers not written (use ! to override)";
  40.  
  41. static    bool_t    more_files P((void));
  42.  
  43. void
  44. do_quit(window, force)
  45. Xviwin    *window;
  46. bool_t    force;
  47. {
  48.     Xviwin    *wp;
  49.     bool_t    changed;
  50.     bool_t    canexit;
  51.  
  52.     if (force) {
  53.     canexit = TRUE;
  54.     } else {
  55.     /*
  56.      * See if any buffers remain modified and unwritten.
  57.      */
  58.     changed = FALSE;
  59.     wp = window;
  60.     do {
  61.         if (is_modified(wp->w_buffer)) {
  62.         changed = TRUE;
  63.         }
  64.     } while ((wp = next_window(wp)) != window);
  65.  
  66.     if (changed) {
  67.         show_error(window, nowrtbufs);
  68.         canexit = FALSE;
  69.     } else {
  70.         canexit = ! more_files();
  71.     }
  72.     }
  73.  
  74.     if (canexit) {
  75.     sys_exit(0);
  76.     }
  77. }
  78.  
  79. /*
  80.  * Split the current window into two, leaving both windows mapped
  81.  * onto the same buffer.
  82.  */
  83. void
  84. do_split_window(window)
  85. Xviwin    *window;
  86. {
  87.     Xviwin    *newwin;
  88.  
  89.     newwin = split_window(window);
  90.     if (newwin == NULL) {
  91.     show_error(window, "No more windows!");
  92.     return;
  93.     }
  94.  
  95.     map_window_onto_buffer(newwin, window->w_buffer);
  96.  
  97.     /*
  98.      * Update the status line of the old window
  99.      * (since it will have been moved).
  100.      * Also update the window - this will almost certainly
  101.      * have no effect on the screen, but is necessary.
  102.      */
  103.     show_file_info(window);
  104.     update_window(window);
  105.  
  106.     /*
  107.      * Show the new window.
  108.      */
  109.     init_sline(newwin);
  110.     update_window(newwin);
  111.     show_file_info(newwin);
  112.  
  113.     /*
  114.      * Update the global window variable.
  115.      */
  116.     curwin = newwin;
  117. }
  118.  
  119. /*
  120.  * Open a new buffer window, with a possible filename arg.
  121.  *
  122.  * do_buffer() is responsible for updating the screen image for the
  123.  * old window, but not the new one, since we may want to move to a
  124.  * different location in the new buffer (e.g. for a tag search).
  125.  */
  126. bool_t
  127. do_buffer(window, filename)
  128. Xviwin    *window;
  129. char    *filename;
  130. {
  131.     Buffer    *buffer;
  132.     Buffer    *new;
  133.     Xviwin    *newwin;
  134.  
  135.     buffer = window->w_buffer;
  136.  
  137.     if (window->w_nrows < (MINROWS + 1) * 2) {
  138.     show_error(window, "Not enough room!");
  139.     return(FALSE);
  140.     }
  141.  
  142.     new = new_buffer();
  143.     if (new == NULL) {
  144.     show_error(window, "No more buffers!");
  145.     return(FALSE);
  146.     }
  147.     newwin = split_window(window);
  148.     if (newwin == NULL) {
  149.     free_buffer(new);
  150.     show_error(window, "No more windows!");
  151.     return(FALSE);
  152.     }
  153.  
  154.     map_window_onto_buffer(newwin, new);
  155.  
  156.     /*
  157.      * Update the status lines of each buffer.
  158.      *
  159.      * Even if (echo & e_SHOWINFO) is turned off, show_file_info()
  160.      * will always call update_sline(), which is what we really
  161.      * need here.
  162.      *
  163.      * Note that we don't need to call move_window_to_cursor() for
  164.      * the old window until it becomes the current window again.
  165.      */
  166.     show_file_info(window);
  167.     init_sline(newwin);
  168.  
  169.     if (filename != NULL) {
  170.     (void) do_edit(newwin, FALSE, filename);
  171.     } else {
  172.     new->b_filename = new->b_tempfname = NULL;
  173.     show_file_info(newwin);
  174.     }
  175.  
  176.     update_window(window);
  177.  
  178.     /*
  179.      * The current buffer (a global variable) has
  180.      * to be updated here. No way around this.
  181.      */
  182.     curbuf = new;
  183.     curwin = newwin;
  184.  
  185.     return(TRUE);
  186. }
  187.  
  188. /*
  189.  * "close" (the current window).
  190.  */
  191. void
  192. do_close_window(win, force)
  193. Xviwin    *win;
  194. bool_t    force;
  195. {
  196.     Buffer    *buffer;
  197.     Xviwin    *best;
  198.  
  199.     buffer = win->w_buffer;
  200.  
  201.     if (is_modified(buffer) && !force && buffer->b_nwindows < 2) {
  202.     /*
  203.      * Don't close a modified buffer.
  204.      */
  205.     show_error(win, nowrtmsg);
  206.     } else if (next_window(win) != win || !more_files()) {
  207.     Xviwin    *w;
  208.  
  209.     /*
  210.      * We can close this window if:
  211.      *
  212.      * (
  213.      *    the buffer has not been modified
  214.      *  or    they are forcing the close
  215.      *  or    there are other windows onto this buffer
  216.      * )
  217.      * AND
  218.      * (
  219.      *    there are other windows still open
  220.      *  or    there are no more files to be edited
  221.      * )
  222.      */
  223.  
  224.     /*
  225.      * Find an adjacent window to take up the screen
  226.      * space used by the one being closed.
  227.      */
  228.     best = NULL;
  229.     for (w = next_window(win); w != win; w = next_window(w)) {
  230.  
  231.         if (w->w_cmdline + 1 == win->w_winpos ||
  232.         w->w_winpos - 1 == win->w_cmdline ||
  233.         w->w_nrows == 0) {
  234.  
  235.         /*
  236.          * We have found an adjacent window;
  237.          * if it is the first such, or if
  238.          * it is smaller than the previous
  239.          * best, it is now the new best.
  240.          */
  241.         if (best == NULL || w->w_nrows < best->w_nrows) {
  242.             best = w;
  243.         }
  244.         }
  245.     }
  246.  
  247.     if (best == NULL) {
  248.         sys_exit(0);
  249.     }
  250.  
  251.     if (buffer->b_nwindows == 1 && buffer->b_filename != NULL) {
  252.         /*
  253.          * Before we free the buffer, save its filename.
  254.          */
  255.         if (altfilename != NULL) {
  256.         free(altfilename);
  257.         }
  258.         altfilename = buffer->b_filename;
  259.         buffer->b_filename = NULL;
  260.         altfileline = lineno(buffer,
  261.             win->w_cursor->p_line);
  262.     }
  263.  
  264.     /*
  265.      * Now "best" points  to the smallest adjacent window;
  266.      * amalgamate the spaces used.
  267.      */
  268.     if (best->w_winpos > win->w_winpos) {
  269.         best->w_winpos = win->w_winpos;
  270.     }
  271.     best->w_nrows += win->w_nrows;
  272.     best->w_cmdline = best->w_winpos + best->w_nrows - 1;
  273.     free_window(win);
  274.  
  275.     if (buffer->b_nwindows == 0) {
  276.         free_buffer(buffer);
  277.     }
  278.  
  279.     /*
  280.      * Have to update the globals "curbuf" and "curwin" here.
  281.      */
  282.     curwin = best;
  283.     curbuf = best->w_buffer;
  284.     {
  285.         unsigned    savecho;
  286.  
  287.         savecho = echo;
  288.         /*
  289.          * Adjust position of new current window
  290.          * within buffer before updating it, to avoid
  291.          * wasting screen output - but don't do any
  292.          * scrolling at this stage because the old
  293.          * window is still on the screen.
  294.          */
  295.         echo &= ~(e_CHARUPDATE | e_SHOWINFO | e_SCROLL);
  296.         move_window_to_cursor(curwin);
  297.         echo = savecho;
  298.  
  299.     }
  300.     update_window(curwin);
  301.     show_file_info(curwin);
  302.     }
  303. }
  304.  
  305. /*
  306.  * Close current window.
  307.  *
  308.  * If it is the last window onto the buffer, also close the buffer.
  309.  *
  310.  * If the buffer has been modified, we must write it out before closing it.
  311.  */
  312. void
  313. do_xit(window)
  314. Xviwin    *window;
  315. {
  316.     Buffer    *buffer;
  317.  
  318.     buffer = window->w_buffer;
  319.  
  320.     if (is_modified(buffer) && buffer->b_nwindows < 2) {
  321.     if (buffer->b_filename != NULL) {
  322.         if (!writeit(window, buffer->b_filename,
  323.                 (Line *) NULL, (Line *) NULL, FALSE)) {
  324.         return;
  325.         }
  326.     } else {
  327.         show_error(window, "No output file");
  328.         return;
  329.     }
  330.     }
  331.  
  332.     do_close_window(window, FALSE);
  333. }
  334.  
  335. /*
  336.  * Edit the given filename in the given buffer,
  337.  * replacing any current contents.  Note that the
  338.  * screen is not updated, since there are routines
  339.  * which use this function before moving the cursor
  340.  * to a different position in the file.
  341.  *
  342.  * Returns TRUE for success, FALSE for failure.
  343.  */
  344. bool_t
  345. do_edit(window, force, arg)
  346. Xviwin    *window;
  347. bool_t    force;
  348. char    *arg;
  349. {
  350.     long    line = 1;        /* line # to go to in new file */
  351.     long    nlines;            /* no of lines read from file */
  352.     Line    *head;            /* start of list of lines */
  353.     Line    *tail;            /* last element of list of lines */
  354.     bool_t    readonly;        /* true if cannot write file */
  355.     Buffer    *buffer;
  356.     Xviwin    *wp;
  357.  
  358.     buffer = window->w_buffer;
  359.  
  360.     if (!force && is_modified(buffer)) {
  361.     show_error(window, nowrtmsg);
  362.     return(FALSE);
  363.     }
  364.  
  365.     if (arg == NULL || arg[0] == '\0') {
  366.     /*
  367.      * No filename specified; we must already have one.
  368.      */
  369.     if (buffer->b_filename == NULL) {
  370.         show_error(window, "No filename");
  371.         return(FALSE);
  372.     }
  373.     } else /* arg != NULL */ {
  374.     /*
  375.      * Filename specified.
  376.      */
  377.  
  378.     /*
  379.      * First detect a ":e" on the current file. This is mainly
  380.      * for ":ta" commands where the destination is within the
  381.      * current file.
  382.      */
  383.     if (buffer->b_filename != NULL &&
  384.         strcmp(arg, buffer->b_filename) == 0) {
  385.         if (!is_modified(buffer) || (is_modified(buffer) && !force)) {
  386.         return(TRUE);
  387.         }
  388.     }
  389.  
  390.     /*
  391.      * Detect an edit of the alternate file, and set
  392.      * the line number.
  393.      */
  394.     if (altfilename != NULL && strcmp(arg, altfilename) == 0) {
  395.         line = altfileline;
  396.     }
  397.  
  398.     /*
  399.      * Save the name of the previous file.
  400.      * If the strsave() of the new filename
  401.      * fails, we will have lost the previous
  402.      * value of altfilename. What a shame.
  403.      */
  404.     if (buffer->b_filename != NULL) {
  405.         if (altfilename != NULL)
  406.         free(altfilename);
  407.         altfilename = strsave(buffer->b_filename);
  408.         altfileline = lineno(buffer, window->w_cursor->p_line);
  409.     }
  410.  
  411.     /*
  412.      * Edit a named file.
  413.      */
  414.     buffer->b_filename = strsave(arg);
  415.     if (buffer->b_filename == NULL)
  416.         return(FALSE);
  417.     if (buffer->b_tempfname != NULL)
  418.         free(buffer->b_tempfname);
  419.     buffer->b_tempfname = NULL;
  420.     }
  421.  
  422.     /*
  423.      * Clear out the old buffer and read the file.
  424.      */
  425.     if (clear_buffer(buffer) == FALSE) {
  426.     show_error(window, "Out of memory");
  427.     return(FALSE);
  428.     }
  429.  
  430.     /*
  431.      * Be sure to re-map all window structures onto the buffer,
  432.      * in order to eliminate any pointers into the old buffer.
  433.      */
  434.     wp = window;
  435.     do {
  436.     if (wp->w_buffer != buffer)
  437.         continue;
  438.  
  439.     unmap_window(wp);
  440.     map_window_onto_buffer(wp, buffer);
  441.  
  442.     } while ((wp = next_window(wp)) != window);
  443.  
  444.     readonly = Pb(P_readonly) || !can_write(buffer->b_filename);
  445.  
  446.     nlines = get_file(window, buffer->b_filename, &head, &tail,
  447.                     (readonly ? " [Read only]" : ""),
  448.                     " [New file]");
  449.  
  450.     update_sline(window);        /* ensure colour is updated */
  451.  
  452.     if (nlines == gf_NEWFILE) {    /* no such file */
  453.     return(FALSE);
  454.     } else if (nlines >= 0) {
  455.     unsigned savecho;
  456.  
  457.     /*
  458.      * Success.
  459.      */
  460.     if (readonly) {
  461.         buffer->b_flags |= FL_READONLY;
  462.     } else {
  463.         buffer->b_flags &= ~FL_READONLY;
  464.     }
  465.  
  466.     if (nlines == 0) {    /* empty file */
  467.         return(TRUE);
  468.     }
  469.  
  470.     /*
  471.      * We have successfully read the file in,
  472.      * so now we must link it into the buffer.
  473.      */
  474.     replbuffer(window, head);
  475.  
  476.     move_cursor(window, gotoline(buffer, line), 0);
  477.     begin_line(window, TRUE);
  478.     setpcmark(window);
  479.  
  480.     /*
  481.      * We only call update_window() here because we want
  482.      * window->w_botline to be updated; we don't let it do any
  483.      * actual screen updating, for the reason explained above.
  484.      */
  485.     savecho = echo;
  486.     echo &= ~(e_CHARUPDATE | e_SCROLL | e_REPORT | e_SHOWINFO);
  487.     update_window(window);
  488.     echo = savecho;
  489.  
  490.     return(TRUE);
  491.     } else {
  492.     /*
  493.      * We failed to read in the file. An appropriate
  494.      * message will already have been printed by
  495.      * get_file() (or alloc()).
  496.      */
  497.  
  498.     if (buffer->b_filename != NULL)
  499.         free(buffer->b_filename);
  500.     if (buffer->b_tempfname != NULL)
  501.         free(buffer->b_tempfname);
  502.     buffer->b_filename = buffer->b_tempfname = NULL;
  503.     return(FALSE);
  504.     }
  505. }
  506.  
  507. void
  508. do_args(window)
  509. Xviwin    *window;
  510. {
  511.     register char    *tmpbuf;
  512.     int        count;
  513.     register int    curpos = 0;
  514.  
  515.     if (numfiles == 0) {
  516.     show_message(window, "No files");
  517.     return;
  518.     }
  519.  
  520.     tmpbuf = alloc((unsigned) window->w_ncols + 1);
  521.     if (tmpbuf == NULL) {
  522.     return;
  523.     }
  524.  
  525.     for (count = 0; count < numfiles; count++) {
  526.     register char    *sp;
  527.  
  528.     if (count == curfile && curpos < window->w_ncols)
  529.         tmpbuf[curpos++] =  '[';
  530.     for (sp = files[count]; curpos < window->w_ncols &&
  531.             (tmpbuf[curpos] = *sp++) != '\0'; curpos++) {
  532.         ;
  533.     }
  534.     if (count == curfile && curpos < window->w_ncols)
  535.         tmpbuf[curpos++] =  ']';
  536.     if (curpos < window->w_ncols)
  537.         tmpbuf[curpos++] =  ' ';
  538.     }
  539.     tmpbuf[curpos < window->w_ncols ? curpos : window->w_ncols] =  '\0';
  540.  
  541.     show_message(window, "%s", tmpbuf);
  542.  
  543.     free(tmpbuf);
  544. }
  545.  
  546. /*
  547.  * Change the current file list to the one specified, or edit the next
  548.  * file in the current file list, or edit the next file in the list if
  549.  * no argument is given.
  550.  */
  551. void
  552. do_next(window, argc, argv, force)
  553. Xviwin    *window;
  554. int    argc;
  555. char    *argv[];
  556. bool_t    force;
  557. {
  558.     unsigned    savecho;
  559.  
  560.     savecho = echo;
  561.     if (argc > 0) {
  562.     int    count;
  563.  
  564.     /*
  565.      * Arguments given - this means a new set of filenames.
  566.      */
  567.     if (!force && is_modified(window->w_buffer)) {
  568.         show_error(window, nowrtmsg);
  569.         return;
  570.     }
  571.  
  572.     /*
  573.      * There were no files before, so start from square one.
  574.      */
  575.     if (numfiles == 0) {
  576.         files = (char **) alloc((unsigned) argc * sizeof(char *));
  577.         if (files == NULL) {
  578.         return;
  579.         }
  580.     } else {
  581.         /*
  582.          * We can change the existing list of files.
  583.          * Free up all the individual filenames
  584.          * which we got last time.
  585.          */
  586.         for (count = 0; count < numfiles; count++) {
  587.         free(files[count]);
  588.         }
  589.         if (argc != numfiles) {
  590.         files = (char **) realloc((char *) files,
  591.                     (unsigned) argc * sizeof(char *));
  592.         if (files == NULL) {
  593.             numfiles = 0;
  594.             return;
  595.         }
  596.         }
  597.     }
  598.  
  599.     /*
  600.      * Now record all the new filenames.
  601.      */
  602.     for (count = 0; count < argc; count++) {
  603.         files[count] = strsave(argv[count]);
  604.         if (files[count] == NULL) {
  605.         /*
  606.          * Aargh. Failed half-way through.
  607.          * Clean up the mess ...
  608.          */
  609.         while (--count >= 0)
  610.             free(files[count]);
  611.         free((char *) files);
  612.         files = NULL;
  613.         numfiles = 0;
  614.         return;
  615.         }
  616.     }
  617.     numfiles = argc;
  618.     curfile = 0;
  619.  
  620.     /*
  621.      * And try to edit the first few of them.
  622.      *
  623.      * In this case, we don't want report() or
  624.      * show_file_info() to be called, because otherwise
  625.      * the messages printed by get_file() won't be seen.
  626.      */
  627.     echo &= ~(e_SCROLL | e_REPORT | e_SHOWINFO);
  628.  
  629.     (void) do_edit(curwin, force, files[0]);
  630.  
  631.     /*
  632.      * This is not very good because it
  633.      * doesn't split the screen evenly for
  634.      * autosplit > 2.  However, it will
  635.      * just have to do for the moment.
  636.      */
  637.  
  638.     /*
  639.      * Update the current window before
  640.      * creating any new ones.
  641.      */
  642.     move_window_to_cursor(curwin);
  643.  
  644.     while ((curfile + 1) < numfiles && can_split()) {
  645.         bool_t    success;
  646.  
  647.         success = do_buffer(curwin, files[++curfile]);
  648.         /*
  649.          * Make sure move_window_to_cursor() is called
  650.          * for every window before calling
  651.          * update_buffer().
  652.          */
  653.         move_window_to_cursor(curwin);
  654.         if (!success)
  655.         break;
  656.     }
  657.     update_window(curwin);
  658.  
  659.     } else if ((curfile + 1) < numfiles) {
  660.     /*
  661.      * No arguments; this is the normal usage, and
  662.      * indicates we should edit the next file in the list.
  663.      * Don't grab the next file if the current one is
  664.      * modified and not written, or we will "lose"
  665.      * files from the list.
  666.      */
  667.     if (!force && is_modified(window->w_buffer)) {
  668.         show_error(window, nowrtmsg);
  669.         return;
  670.     }
  671.  
  672.     /*
  673.      * Just edit the next file.
  674.      */
  675.     echo &= ~(e_SCROLL | e_REPORT | e_SHOWINFO);
  676.     (void) do_edit(window, force, files[++curfile]);
  677.     move_window_to_cursor(window);
  678.     update_buffer(window->w_buffer);
  679.     } else {
  680.     show_message(window, "No more files");
  681.     }
  682.     echo = savecho;
  683. }
  684.  
  685. /*ARGSUSED*/
  686. void
  687. do_rewind(window, force)
  688. Xviwin    *window;
  689. bool_t    force;
  690. {
  691.     unsigned    savecho;
  692.  
  693.     if (numfiles <= 1)        /* nothing to rewind */
  694.     return;
  695.  
  696.     curfile = 0;
  697.  
  698.     savecho = echo;
  699.     echo &= ~(e_SCROLL | e_REPORT | e_SHOWINFO);
  700.     (void) do_edit(window, force, files[0]);
  701.     move_window_to_cursor(window);
  702.     update_buffer(window->w_buffer);
  703.     echo = savecho;
  704. }
  705.  
  706. /*
  707.  * Write out the buffer, to the given filename,
  708.  * from "line1" to "line2", forcing if necessary.
  709.  *
  710.  * If no filename given, use the buffer's filename.
  711.  */
  712. bool_t
  713. do_write(window, filename, l1, l2, force)
  714. Xviwin    *window;
  715. char    *filename;
  716. Line    *l1, *l2;
  717. bool_t    force;
  718. {
  719.     if (filename == NULL) {
  720.     filename = window->w_buffer->b_filename;
  721.     }
  722.  
  723.     if (filename == NULL) {
  724.     show_error(window, "No output file");
  725.     return(FALSE);
  726.     } else {
  727.     return(writeit(window, filename, l1, l2, force));
  728.     }
  729. }
  730.  
  731. /*
  732.  * Write to the given filename then quit.
  733.  */
  734. void
  735. do_wq(window, filename, force)
  736. Xviwin    *window;
  737. char    *filename;
  738. bool_t    force;
  739. {
  740.     if (do_write(window, filename, (Line *) NULL, (Line *) NULL, force)) {
  741.     do_quit(window, force);    
  742.     }
  743. }
  744.  
  745. /*
  746.  * Read the given file into the buffer after the specified line.
  747.  * The line may not be NULL, but should be a line in the buffer
  748.  * referenced by the passed window parameter.
  749.  */
  750. void
  751. do_read(window, filename, atline)
  752. Xviwin    *window;
  753. char    *filename;
  754. Line    *atline;
  755. {
  756.     Line    *head;        /* start of list of lines */
  757.     Line    *tail;        /* last element of list of lines */
  758.     long    nlines;        /* number of lines read */
  759.  
  760.     nlines = get_file(window, filename, &head, &tail, "", " No such file");
  761.  
  762.     /*
  763.      * If nlines > 0, we need to insert the lines returned into
  764.      * the buffer. Otherwise, either the file is empty or an error
  765.      * message has already been printed: in either case, we don't
  766.      * need to do anything.
  767.      */
  768.     if (nlines > 0) {
  769.     /*
  770.      * We want to see the message printed by
  771.      * get_file() here, not the message printed by
  772.      * report().
  773.      */
  774.     echo &= ~e_REPORT;
  775.     repllines(window, atline->l_next, 0L, head);
  776.     echo |= e_REPORT;
  777.     update_buffer(window->w_buffer);
  778.  
  779.     /*
  780.      * Move the cursor to the first character
  781.      * of the file we just read in.
  782.      */
  783.     move_cursor(window, atline->l_next, 0);
  784.     begin_line(window, TRUE);
  785.     }
  786. }
  787.  
  788. /*
  789.  * Edit alternate file. Called when control-^ is typed.
  790.  */
  791. void
  792. do_alt_edit(window)
  793. Xviwin    *window;
  794. {
  795.     if (altfilename == NULL) {
  796.     show_error(window, "No alternate file to edit");
  797.     } else {
  798.     if (do_buffer(window, altfilename)) {
  799.         move_window_to_cursor(curwin);
  800.         update_window(curwin);
  801.     }
  802.     }
  803. }
  804.  
  805. void
  806. do_compare()
  807. {
  808.     Xviwin        *w;
  809.     enum mvtype    incres;
  810.     Posn        pos1, pos2;
  811.  
  812.     w = next_window(curwin);
  813.     if (w == curwin) {
  814.     show_error(curwin, "No other buffers to compare");
  815.     } else if (w->w_buffer == curbuf) {
  816.     show_error(curwin, "Next window has same buffer");
  817.     } else {
  818.     pos1 = *(curwin->w_cursor);
  819.     pos2 = *(w->w_cursor);
  820.     while ((incres = inc(&pos1)) == inc(&pos2)) {
  821.         if (incres == mv_EOL) {
  822.         continue;
  823.         } else if (incres == mv_NOMOVE) {
  824.         (void) dec(&pos1);
  825.         (void) dec(&pos2);
  826.         break;
  827.         } else {
  828.         if (gchar(&pos1) != gchar(&pos2)) {
  829.             break;
  830.         }
  831.         }
  832.     }
  833.     if (gchar(&pos1) == '\0' && pos1.p_index > 0) {
  834.         (void) dec(&pos1);
  835.     }
  836.     if (gchar(&pos2) == '\0' && pos2.p_index > 0) {
  837.         (void) dec(&pos2);
  838.     }
  839.     move_cursor(curwin, pos1.p_line, pos1.p_index);
  840.     move_cursor(w, pos2.p_line, pos2.p_index);
  841.     move_window_to_cursor(w);
  842.     cursupdate(w);
  843.     wind_goto(w);
  844.     }
  845. }
  846.  
  847. static bool_t
  848. more_files()
  849. {
  850.     int    n;
  851.  
  852.     n = numfiles - (curfile + 1);
  853.     if (n > 0) {
  854.     show_error(curwin, "%d more file%s to edit", n, (n > 1) ? "s" : "");
  855.     return(TRUE);
  856.     } else {
  857.     return(FALSE);
  858.     }
  859. }
  860.