BSD 2 development
[unix-history] / .ref-BSD-1 / ex-1.1 / exu.c
CommitLineData
09a0104b
BJ
1#include "ex.h"
2/*
3 * Ex - a text editor
4 * Bill Joy UCB June/September 1977
5 *
6 * Pointers for lines deleted by the last buffer editing
7 * command are salted away between dol and unddol. Unddel
8 * marks the line which was before this group prior to the last
9 * command. If undap1 != undap2 then the lines from undap1
10 * to undap2-1 were appended by the last command.
11 */
12
13undo(c)
14 char c;
15{
16 register int i, *jp, *kp;
17 int *dolp1, *newdol, *newadot;
18
19 if (inglobal)
20 error("Can't undo in global@commands");
21 if (!c)
22 somechange();
23 change();
24 if (undkind == UNDMOVE) {
25 /*
26 * Command to be undone is a move command.
27 * This is handled as a special case by noting that
28 * a move "a,b m c" can be inverted by another move.
29 */
30 if ((i = (jp = unddel) - undap2) > 0) {
31 /*
32 * when c > b inverse is a+(c-b),c m a-1
33 */
34 addr2 = jp;
35 addr1 = (jp = undap1) + i;
36 unddel = jp-1;
37 } else {
38 /*
39 * when b > c inverse is c+1,c+1+(b-a) m b
40 */
41 addr1 = ++jp;
42 addr2 = jp + ((unddel = undap2) - undap1);
43 }
44 kp = undap1;
45 move1(0, unddel);
46 dot = kp;
47 Command = "move";
48 killed();
49 } else {
50 int cnt;
51
52 newadot = dot;
53 cnt = dol - zero;
54 newdol = dol;
55 dolp1 = dol + 1;
56 /*
57 * Command to be undone is a non-move.
58 * All such commands are treated as a combination of
59 * a delete command and a append command.
60 * We first move the lines appended by the last command
61 * from undap1 to undap2-1 so that they are just before the
62 * saved deleted lines.
63 */
64 if ((i = (kp = undap2) - (jp = undap1)) > 0) {
65 reverse(jp, kp);
66 reverse(kp, dolp1);
67 reverse(jp, dolp1);
68 /*
69 * Account for possible backward motion of target
70 * for restoration of saved deleted lines.
71 */
72 if (unddel >= jp)
73 unddel =- i;
74 newdol =- i;
75 /*
76 * For the case where no lines are restored, dot
77 * is the line before the first line deleted.
78 */
79 dot = jp-1;
80 }
81 /*
82 * Now put the deleted lines, if any, back where they were.
83 * Basic operation is: dol+1,unddol m unddel
84 */
85 jp = unddel + 1;
86 if ((i = (kp = unddol) - dol) > 0) {
87 if (jp != dolp1) {
88 reverse(jp, dolp1);
89 reverse(dolp1, ++kp);
90 reverse(jp, kp);
91 }
92 /*
93 * Account for possible forward motion of the target
94 * for restoration of the deleted lines.
95 */
96 if (undap1 >= jp)
97 undap1 =+ i;
98 /*
99 * Dot is the first resurrected line.
100 */
101 dot = jp;
102 newdol =+ i;
103 }
104 /*
105 * Clean up so we are invertible
106 */
107 unddel = undap1 - 1;
108 undap1 = jp;
109 undap2 = jp + i;
110 dol = newdol;
111 netchHAD(cnt);
112 if (undkind == UNDALL) {
113 dot = undadot;
114 undadot = newadot;
115 }
116 }
117 if (dot == zero && dot != dol)
118 dot = one;
119}
120
121somechange()
122{
123 register int *ip, *jp;
124
125 switch (undkind) {
126 case UNDMOVE:
127 return;
128 case UNDCHANGE:
129 if (undap1 == undap2 && dol == unddol)
130 break;
131 return;
132 case UNDALL:
133 if (unddol - dol != dol - zero)
134 return;
135 for (ip = one, jp = dol + 1; ip <= dol; ip++, jp++)
136 if ((*ip &~ 01) != (*jp &~ 01))
137 return;
138 break;
139 case UNDNONE:
140 error("Nothing to undo");
141 }
142 error("Nothing changed|Last undoable command didn't change anything");
143}