2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid
[] = "$Id: v_undo.c,v 10.6 2001/06/25 15:19:36 skimo Exp $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
20 #include <bitstring.h>
27 #include "../common/common.h"
32 * Undo changes to this line.
34 * PUBLIC: int v_Undo(SCR *, VICMD *);
37 v_Undo(SCR
*sp
, VICMD
*vp
)
40 * Historically, U reset the cursor to the first column in the line
41 * (not the first non-blank). This seems a bit non-intuitive, but,
42 * considering that we may have undone multiple changes, anything
43 * else (including the cursor position stored in the logging records)
44 * is going to appear random.
50 * Set up the flags so that an immediately subsequent 'u' will roll
51 * forward, instead of backward. In historic vi, a 'u' following a
52 * 'U' redid all of the changes to the line. Given that the user has
53 * explicitly discarded those changes by entering 'U', it seems likely
54 * that the user wants something between the original and end forms of
55 * the line, so starting to replay the changes seems the best way to
58 F_SET(sp
->ep
, F_UNDO
);
59 sp
->ep
->lundo
= BACKWARD
;
61 return (log_setline(sp
));
66 * Undo the last change.
68 * PUBLIC: int v_undo(SCR *, VICMD *);
71 v_undo(SCR
*sp
, VICMD
*vp
)
75 /* Set the command count. */
76 VIP(sp
)->u_ccnt
= sp
->ccnt
;
80 * In historic vi, 'u' toggled between "undo" and "redo", i.e. 'u'
81 * undid the last undo. However, if there has been a change since
82 * the last undo/redo, we always do an undo. To make this work when
83 * the user can undo multiple operations, we leave the old semantic
84 * unchanged, but make '.' after a 'u' do another undo/redo operation.
85 * This has two problems.
87 * The first is that 'u' didn't set '.' in historic vi. So, if a
88 * user made a change, realized it was in the wrong place, does a
89 * 'u' to undo it, moves to the right place and then does '.', the
90 * change was reapplied. To make this work, we only apply the '.'
91 * to the undo command if it's the command immediately following an
92 * undo command. See vi/vi.c:getcmd() for the details.
94 * The second is that the traditional way to view the numbered cut
95 * buffers in vi was to enter the commands "1pu.u.u.u. which will
96 * no longer work because the '.' immediately follows the 'u' command.
97 * Since we provide a much better method of viewing buffers, and
98 * nobody can think of a better way of adding in multiple undo, this
102 * There is change to historic practice for the final cursor position
103 * in this implementation. In historic vi, if an undo was isolated to
104 * a single line, the cursor moved to the start of the change, and
105 * then, subsequent 'u' commands would not move it again. (It has been
106 * pointed out that users used multiple undo commands to get the cursor
107 * to the start of the changed text.) Nvi toggles between the cursor
108 * position before and after the change was made. One final issue is
109 * that historic vi only did this if the user had not moved off of the
110 * line before entering the undo command; otherwise, vi would move the
111 * cursor to the most attractive position on the changed line.
113 * It would be difficult to match historic practice in this area. You
114 * not only have to know that the changes were isolated to one line,
115 * but whether it was the first or second undo command as well. And,
116 * to completely match historic practice, we'd have to track users line
117 * changes, too. This isn't worth the effort.
120 if (!F_ISSET(ep
, F_UNDO
)) {
122 ep
->lundo
= BACKWARD
;
123 } else if (!F_ISSET(vp
, VC_ISDOT
))
124 ep
->lundo
= ep
->lundo
== BACKWARD
? FORWARD
: BACKWARD
;
128 return (log_backward(sp
, &vp
->m_final
));
130 return (log_forward(sp
, &vp
->m_final
));