Commit | Line | Data |
---|---|---|
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 | ||
13 | undo(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 | ||
121 | somechange() | |
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 | } |