4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/undo.c,v 1.4 2017/12/02 02:07:36 tg Exp $");
26 static UNDO undos = { {&undos, &undos} };
27 static UNDO frdos = { {&frdos, &frdos} };
34 UNDOREC yanked = { {&yanked, &yanked} };
39 UNDOREC frrecs = { {&frrecs, &frrecs} };
41 static UNDOREC *alrec(void)
43 UNDOREC *rec = (UNDOREC *) alitem(&frrecs, sizeof(UNDOREC));
48 static void frrec(UNDOREC *rec)
60 enquef(UNDOREC, link, &frrecs, rec);
65 UNDO *undo = (UNDO *) alitem(&frdos, sizeof(UNDO));
72 izque(UNDOREC, link, &undo->recs);
73 enquef(UNDO, link, &undos, undo);
77 void undorm(UNDO *undo)
79 frchn(&frrecs, &undo->recs);
80 demote(UNDO, link, &frdos, undo);
83 static void doundo(BW *bw, UNDOREC *ptr)
89 binsm(bw->cursor, ptr->small, (int) ptr->len);
94 binsb(bw->cursor, bcpy(b->bof, b->eof));
98 P *q = pdup(bw->cursor);
104 bw->b->changed = ptr->changed;
110 UNDO *undo = bw->b->undo;
117 pgoto(bw->cursor, undo->recs.link.prev->where);
118 undo->ptr = &undo->recs;
119 /* If this return is uncommented, then uundo will jump
120 to where the undo is about to occur before actually
124 if (undo->ptr->link.prev == &undo->recs)
126 upto = undo->ptr->link.prev->unit;
128 undo->ptr = undo->ptr->link.prev;
129 pgoto(bw->cursor, undo->ptr->where);
131 doundo(bw, undo->ptr);
133 if (upto && upto != undo->ptr)
142 UNDO *undo = bw->b->undo;
148 if (undo->ptr == &undo->recs)
150 upto = undo->recs.link.prev->unit;
152 ptr = undo->recs.link.prev;
153 pgoto(bw->cursor, ptr->where);
157 frrec(deque_f(UNDOREC, link, ptr));
158 undo->ptr = undo->ptr->link.next;
159 } while (upto && upto != ptr);
167 for (undo = undos.link.next; undo != &undos; undo = undo->link.next) {
170 for (rec = undo->recs.link.next; rec != &undo->recs; rec = rec->link.next)
175 /* Eliminate excess undo records */
177 static void undogc(UNDO *undo)
179 UNDOREC *unit = undo->recs.link.next->unit;
182 if (undo->ptr && undo->ptr->link.prev == &undo->recs)
185 while (unit != undo->recs.link.next)
186 frrec(deque_f(UNDOREC, link, undo->recs.link.next));
187 frrec(deque_f(UNDOREC, link, undo->recs.link.next));
190 undo->ptr = undo->recs.link.next;
197 for (undo = undos.link.next; undo != &undos; undo = undo->link.next)
199 undo->first->unit = undo->last;
200 undo->last->unit = undo->first;
201 undo->first = undo->last = 0;
202 if (++undo->nrecs == UNDOKEEP)
207 /* Delete the alternate time-line after the user has resumed editing after
208 * undoing some number of changes
211 static void undoover(UNDO *undo)
216 void undoins(UNDO *undo, P *p, long size)
223 if (undo->ptr && undo->ptr != &undo->recs)
225 rec = undo->recs.link.prev;
226 if (rec != &undo->recs && rec->min && !rec->del && (p->byte == rec->where + rec->len || p->byte == rec->where))
234 rec->where = p->byte;
238 rec->changed = undo->b->changed;
239 enqueb(UNDOREC, link, &undo->recs, rec);
246 UNDOREC *rec = yanked.link.prev;
249 rec->where = bw->cursor->byte;
253 static void yankdel(long where, B *b)
256 long size = b->eof->byte;
258 /* Store in yank buffer */
259 rec = yanked.link.prev;
261 if (rec != &yanked && where == rec->where && justkilled) {
262 if (rec->len + size >= SMALL) {
263 if (rec->len < SMALL) {
264 rec->big = bmk(NULL);
265 binsm(rec->big->bof, rec->small, (int) rec->len);
267 joe_free(rec->small);
270 binsb(rec->big->eof, bcpy(b->bof, b->eof));
273 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
274 brmem(b->bof, rec->small + rec->len, (int) size);
277 } else if (rec != &yanked && where + size == rec->where && justkilled) {
278 if (rec->len + size >= SMALL) {
279 if (rec->len < SMALL) {
280 rec->big = bmk(NULL);
281 binsm(rec->big->bof, rec->small, (int) rec->len);
283 joe_free(rec->small);
286 binsb(rec->big->bof, bcpy(b->bof, b->eof));
289 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
290 mmove(rec->small + size, rec->small, (int) rec->len);
291 brmem(b->bof, rec->small, (int) size);
296 if (++nyanked == 100) {
297 frrec(deque_f(UNDOREC, link, yanked.link.next));
302 rec->small = (unsigned char *) joe_malloc(size);
303 brmem(b->bof, rec->small, (int) b->eof->byte);
305 rec->big = bcpy(b->bof, b->eof);
311 enqueb(UNDOREC, link, &yanked, rec);
316 void undodel(UNDO *undo, long where, B *b)
319 long size = b->eof->byte;
326 if (undo->ptr && undo->ptr != &undo->recs)
331 /* Store in undo buffer */
332 rec = undo->recs.link.prev;
333 if (rec != &undo->recs && rec->min && rec->del && where == rec->where) {
334 if (rec->len + size >= SMALL) {
335 if (rec->len < SMALL) {
336 rec->big = bmk(NULL);
337 binsm(rec->big->bof, rec->small, (int) rec->len);
339 joe_free(rec->small);
342 binsb(rec->big->eof, b);
345 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
346 brmem(b->bof, rec->small + rec->len, (int) size);
350 } else if (rec != &undo->recs && rec->min && rec->del && where + size == rec->where) {
351 if (rec->len + size >= SMALL) {
352 if (rec->len < SMALL) {
353 rec->big = bmk(NULL);
354 binsm(rec->big->bof, rec->small, (int) rec->len);
356 joe_free(rec->small);
359 binsb(rec->big->bof, b);
362 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
363 mmove(rec->small + size, rec->small, (int) rec->len);
364 brmem(b->bof, rec->small, (int) size);
372 rec->small = (unsigned char *) joe_malloc(size);
373 brmem(b->bof, rec->small, (int) b->eof->byte);
387 rec->changed = undo->b->changed;
388 enqueb(UNDOREC, link, &undo->recs, rec);
397 UNDOREC *ptr = yanked.link.prev;
399 if (ptr != &yanked) {
400 if (ptr->len < SMALL)
401 binsm(bw->cursor, ptr->small, (int) ptr->len);
406 binsb(bw->cursor, bcpy(b->bof, b->eof));
409 pfwrd(bw->cursor, ptr->len);
411 yankwhere = bw->cursor->byte;
419 if (bw->b == yankbuf && bw->cursor->byte == yankwhere) {
421 UNDOREC *ptr = yanked.link.prev;
423 deque(UNDOREC, link, &yanked);
424 enqueb(UNDOREC, link, ptr, &yanked);
425 q = pdup(bw->cursor);
436 /* Clear changed-flag: make buffer look unmodified */
441 msgnw(bw->parent, US "Modified flag cleared");
447 if (markv(1) && !square) {
448 B *b = bcpy(markb, markk);
450 yankdel(markb->byte, b);
456 msgnw(bw->parent, US "No block");