source: trunk/third/nvi/vi/v_undo.c @ 14302

Revision 14302, 4.3 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14301, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
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.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10#include "config.h"
11
12#ifndef lint
13static const char sccsid[] = "@(#)v_undo.c      10.5 (Berkeley) 3/6/96";
14#endif /* not lint */
15
16#include <sys/types.h>
17#include <sys/queue.h>
18#include <sys/time.h>
19
20#include <bitstring.h>
21#include <errno.h>
22#include <limits.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "../common/common.h"
28#include "vi.h"
29
30/*
31 * v_Undo -- U
32 *      Undo changes to this line.
33 *
34 * PUBLIC: int v_Undo __P((SCR *, VICMD *));
35 */
36int
37v_Undo(sp, vp)
38        SCR *sp;
39        VICMD *vp;
40{
41        /*
42         * Historically, U reset the cursor to the first column in the line
43         * (not the first non-blank).  This seems a bit non-intuitive, but,
44         * considering that we may have undone multiple changes, anything
45         * else (including the cursor position stored in the logging records)
46         * is going to appear random.
47         */
48        vp->m_final.cno = 0;
49
50        /*
51         * !!!
52         * Set up the flags so that an immediately subsequent 'u' will roll
53         * forward, instead of backward.  In historic vi, a 'u' following a
54         * 'U' redid all of the changes to the line.  Given that the user has
55         * explicitly discarded those changes by entering 'U', it seems likely
56         * that the user wants something between the original and end forms of
57         * the line, so starting to replay the changes seems the best way to
58         * get to there.
59         */
60        F_SET(sp->ep, F_UNDO);
61        sp->ep->lundo = BACKWARD;
62
63        return (log_setline(sp));
64}
65
66/*
67 * v_undo -- u
68 *      Undo the last change.
69 *
70 * PUBLIC: int v_undo __P((SCR *, VICMD *));
71 */
72int
73v_undo(sp, vp)
74        SCR *sp;
75        VICMD *vp;
76{
77        EXF *ep;
78
79        /* Set the command count. */
80        VIP(sp)->u_ccnt = sp->ccnt;
81
82        /*
83         * !!!
84         * In historic vi, 'u' toggled between "undo" and "redo", i.e. 'u'
85         * undid the last undo.  However, if there has been a change since
86         * the last undo/redo, we always do an undo.  To make this work when
87         * the user can undo multiple operations, we leave the old semantic
88         * unchanged, but make '.' after a 'u' do another undo/redo operation.
89         * This has two problems.
90         *
91         * The first is that 'u' didn't set '.' in historic vi.  So, if a
92         * user made a change, realized it was in the wrong place, does a
93         * 'u' to undo it, moves to the right place and then does '.', the
94         * change was reapplied.  To make this work, we only apply the '.'
95         * to the undo command if it's the command immediately following an
96         * undo command.  See vi/vi.c:getcmd() for the details.
97         *
98         * The second is that the traditional way to view the numbered cut
99         * buffers in vi was to enter the commands "1pu.u.u.u. which will
100         * no longer work because the '.' immediately follows the 'u' command.
101         * Since we provide a much better method of viewing buffers, and
102         * nobody can think of a better way of adding in multiple undo, this
103         * remains broken.
104         *
105         * !!!
106         * There is change to historic practice for the final cursor position
107         * in this implementation.  In historic vi, if an undo was isolated to
108         * a single line, the cursor moved to the start of the change, and
109         * then, subsequent 'u' commands would not move it again. (It has been
110         * pointed out that users used multiple undo commands to get the cursor
111         * to the start of the changed text.)  Nvi toggles between the cursor
112         * position before and after the change was made.  One final issue is
113         * that historic vi only did this if the user had not moved off of the
114         * line before entering the undo command; otherwise, vi would move the
115         * cursor to the most attractive position on the changed line.
116         *
117         * It would be difficult to match historic practice in this area. You
118         * not only have to know that the changes were isolated to one line,
119         * but whether it was the first or second undo command as well.  And,
120         * to completely match historic practice, we'd have to track users line
121         * changes, too.  This isn't worth the effort.
122         */
123        ep = sp->ep;
124        if (!F_ISSET(ep, F_UNDO)) {
125                F_SET(ep, F_UNDO);
126                ep->lundo = BACKWARD;
127        } else if (!F_ISSET(vp, VC_ISDOT))
128                ep->lundo = ep->lundo == BACKWARD ? FORWARD : BACKWARD;
129
130        switch (ep->lundo) {
131        case BACKWARD:
132                return (log_backward(sp, &vp->m_final));
133        case FORWARD:
134                return (log_forward(sp, &vp->m_final));
135        default:
136                abort();
137        }
138        /* NOTREACHED */
139}
Note: See TracBrowser for help on using the repository browser.