rework initial error handling -- since we check for any screens on
[nvi.git] / vi / v_undo.c
blob9b3cb11aaa7b0599e2deaacc99dd926c501f8754
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: v_undo.c,v 8.6 1994/01/08 13:56:10 bostic Exp $ (Berkeley) $Date: 1994/01/08 13:56:10 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include "vi.h"
19 #include "vcmd.h"
22 * v_Undo -- U
23 * Undo changes to this line.
25 int
26 v_Undo(sp, ep, vp, fm, tm, rp)
27 SCR *sp;
28 EXF *ep;
29 VICMDARG *vp;
30 MARK *fm, *tm, *rp;
33 * Historically, U reset the cursor to the first column in the line
34 * (not the first non-blank). This seems a bit non-intuitive, but,
35 * considering that we may have undone multiple changes, anything
36 * else (including the cursor position stored in the logging records)
37 * is going to appear random.
39 rp->lno = fm->lno;
40 rp->cno = 0;
43 * !!!
44 * Set up the flags so that an immediately subsequent 'u' will roll
45 * forward, instead of backward. In historic vi, a 'u' following a
46 * 'U' redid all of the changes to the line. Given that the user has
47 * explicitly discarded those changes by entering 'U', it seems likely
48 * that the user wants something between the original and end forms of
49 * the line, so starting to replay the changes seems the best way to
50 * get to there.
52 F_SET(ep, F_UNDO);
53 ep->lundo = BACKWARD;
55 return (log_setline(sp, ep));
59 * v_undo -- u
60 * Undo the last change.
62 int
63 v_undo(sp, ep, vp, fm, tm, rp)
64 SCR *sp;
65 EXF *ep;
66 VICMDARG *vp;
67 MARK *fm, *tm, *rp;
69 /* Set the command count. */
70 VIP(sp)->u_ccnt = sp->ccnt;
73 * !!!
74 * In historic vi, 'u' toggled between "undo" and "redo", i.e. 'u'
75 * undid the last undo. However, if there has been a change since
76 * the last undo/redo, we always do an undo. To make this work when
77 * the user can undo multiple operations, we leave the old semantic
78 * unchanged, but make '.' after a 'u' do another undo/redo operation.
79 * This has two problems.
81 * The first is that 'u' didn't set '.' in historic vi. So, if a
82 * user made a change, realized it was in the wrong place, does a
83 * 'u' to undo it, moves to the right place and then does '.', the
84 * change was reapplied. To make this work, we only apply the '.'
85 * to the undo command if it's the command immediately following an
86 * undo command. See vi/vi.c:getcmd() for the details.
88 * The second is that the traditional way to view the numbered cut
89 * buffers in vi was to enter the commands "1pu.u.u.u. which will
90 * no longer work because the '.' immediately follows the 'u' command.
91 * Since we provide a much better method of viewing buffers, and
92 * nobody can think of a better way of adding in multiple undo, this
93 * remains broken.
95 if (!F_ISSET(ep, F_UNDO)) {
96 F_SET(ep, F_UNDO);
97 ep->lundo = BACKWARD;
98 } else if (!F_ISSET(vp, VC_ISDOT))
99 ep->lundo = ep->lundo == BACKWARD ? FORWARD : BACKWARD;
101 switch (ep->lundo) {
102 case BACKWARD:
103 return (log_backward(sp, ep, rp));
104 case FORWARD:
105 return (log_forward(sp, ep, rp));
106 default:
107 abort();
109 /* NOTREACHED */