1 /* $MirOS: contrib/code/jupp/undo.c,v 1.3 2010/04/08 15:31:05 tg Exp $ */
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
25 static UNDO undos = { {&undos, &undos} };
26 static UNDO frdos = { {&frdos, &frdos} };
33 UNDOREC yanked = { {&yanked, &yanked} };
38 UNDOREC frrecs = { {&frrecs, &frrecs} };
40 static UNDOREC *alrec(void)
42 UNDOREC *rec = (UNDOREC *) alitem(&frrecs, sizeof(UNDOREC));
47 static void frrec(UNDOREC *rec)
59 enquef(UNDOREC, link, &frrecs, rec);
64 UNDO *undo = (UNDO *) alitem(&frdos, sizeof(UNDO));
71 izque(UNDOREC, link, &undo->recs);
72 enquef(UNDO, link, &undos, undo);
76 void undorm(UNDO *undo)
78 frchn(&frrecs, &undo->recs);
79 demote(UNDO, link, &frdos, undo);
82 static void doundo(BW *bw, UNDOREC *ptr)
88 binsm(bw->cursor, ptr->small, (int) ptr->len);
93 binsb(bw->cursor, bcpy(b->bof, b->eof));
97 P *q = pdup(bw->cursor);
103 bw->b->changed = ptr->changed;
109 UNDO *undo = bw->b->undo;
116 pgoto(bw->cursor, undo->recs.link.prev->where);
117 undo->ptr = &undo->recs;
118 /* If this return is uncommented, then uundo will jump
119 to where the undo is about to occur before actually
123 if (undo->ptr->link.prev == &undo->recs)
125 upto = undo->ptr->link.prev->unit;
127 undo->ptr = undo->ptr->link.prev;
128 pgoto(bw->cursor, undo->ptr->where);
130 doundo(bw, undo->ptr);
132 if (upto && upto != undo->ptr)
141 UNDO *undo = bw->b->undo;
147 if (undo->ptr == &undo->recs)
149 upto = undo->recs.link.prev->unit;
151 ptr = undo->recs.link.prev;
152 pgoto(bw->cursor, ptr->where);
156 frrec(deque_f(UNDOREC, link, ptr));
157 undo->ptr = undo->ptr->link.next;
158 } while (upto && upto != ptr);
166 for (undo = undos.link.next; undo != &undos; undo = undo->link.next) {
169 for (rec = undo->recs.link.next; rec != &undo->recs; rec = rec->link.next)
174 /* Eliminate excess undo records */
176 static void undogc(UNDO *undo)
178 UNDOREC *unit = undo->recs.link.next->unit;
181 if (undo->ptr && undo->ptr->link.prev == &undo->recs)
184 while (unit != undo->recs.link.next)
185 frrec(deque_f(UNDOREC, link, undo->recs.link.next));
186 frrec(deque_f(UNDOREC, link, undo->recs.link.next));
189 undo->ptr = undo->recs.link.next;
196 for (undo = undos.link.next; undo != &undos; undo = undo->link.next)
198 undo->first->unit = undo->last;
199 undo->last->unit = undo->first;
200 undo->first = undo->last = 0;
201 if (++undo->nrecs == UNDOKEEP)
206 /* Delete the alternate time-line after the user has resumed editing after
207 * undoing some number of changes
210 static void undoover(UNDO *undo)
215 void undoins(UNDO *undo, P *p, long size)
222 if (undo->ptr && undo->ptr != &undo->recs)
224 rec = undo->recs.link.prev;
225 if (rec != &undo->recs && rec->min && !rec->del && (p->byte == rec->where + rec->len || p->byte == rec->where))
233 rec->where = p->byte;
237 rec->changed = undo->b->changed;
238 enqueb(UNDOREC, link, &undo->recs, rec);
245 UNDOREC *rec = yanked.link.prev;
248 rec->where = bw->cursor->byte;
252 static void yankdel(long where, B *b)
255 long size = b->eof->byte;
257 /* Store in yank buffer */
258 rec = yanked.link.prev;
260 if (rec != &yanked && where == rec->where && justkilled) {
261 if (rec->len + size >= SMALL) {
262 if (rec->len < SMALL) {
263 rec->big = bmk(NULL);
264 binsm(rec->big->bof, rec->small, (int) rec->len);
266 joe_free(rec->small);
269 binsb(rec->big->eof, bcpy(b->bof, b->eof));
272 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
273 brmem(b->bof, rec->small + rec->len, (int) size);
276 } else if (rec != &yanked && where + size == rec->where && justkilled) {
277 if (rec->len + size >= SMALL) {
278 if (rec->len < SMALL) {
279 rec->big = bmk(NULL);
280 binsm(rec->big->bof, rec->small, (int) rec->len);
282 joe_free(rec->small);
285 binsb(rec->big->bof, bcpy(b->bof, b->eof));
288 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
289 mmove(rec->small + size, rec->small, (int) rec->len);
290 brmem(b->bof, rec->small, (int) size);
295 if (++nyanked == 100) {
296 frrec(deque_f(UNDOREC, link, yanked.link.next));
301 rec->small = (unsigned char *) joe_malloc(size);
302 brmem(b->bof, rec->small, (int) b->eof->byte);
304 rec->big = bcpy(b->bof, b->eof);
310 enqueb(UNDOREC, link, &yanked, rec);
315 void undodel(UNDO *undo, long where, B *b)
318 long size = b->eof->byte;
325 if (undo->ptr && undo->ptr != &undo->recs)
330 /* Store in undo buffer */
331 rec = undo->recs.link.prev;
332 if (rec != &undo->recs && rec->min && rec->del && where == rec->where) {
333 if (rec->len + size >= SMALL) {
334 if (rec->len < SMALL) {
335 rec->big = bmk(NULL);
336 binsm(rec->big->bof, rec->small, (int) rec->len);
338 joe_free(rec->small);
341 binsb(rec->big->eof, b);
344 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
345 brmem(b->bof, rec->small + rec->len, (int) size);
349 } else if (rec != &undo->recs && rec->min && rec->del && where + size == rec->where) {
350 if (rec->len + size >= SMALL) {
351 if (rec->len < SMALL) {
352 rec->big = bmk(NULL);
353 binsm(rec->big->bof, rec->small, (int) rec->len);
355 joe_free(rec->small);
358 binsb(rec->big->bof, b);
361 rec->small = (unsigned char *) joe_realloc(rec->small, rec->len + size);
362 mmove(rec->small + size, rec->small, (int) rec->len);
363 brmem(b->bof, rec->small, (int) size);
371 rec->small = (unsigned char *) joe_malloc(size);
372 brmem(b->bof, rec->small, (int) b->eof->byte);
386 rec->changed = undo->b->changed;
387 enqueb(UNDOREC, link, &undo->recs, rec);
396 UNDOREC *ptr = yanked.link.prev;
398 if (ptr != &yanked) {
399 if (ptr->len < SMALL)
400 binsm(bw->cursor, ptr->small, (int) ptr->len);
405 binsb(bw->cursor, bcpy(b->bof, b->eof));
408 pfwrd(bw->cursor, ptr->len);
410 yankwhere = bw->cursor->byte;
418 if (bw->b == yankbuf && bw->cursor->byte == yankwhere) {
420 UNDOREC *ptr = yanked.link.prev;
422 deque(UNDOREC, link, &yanked);
423 enqueb(UNDOREC, link, ptr, &yanked);
424 q = pdup(bw->cursor);
435 /* Clear changed-flag: make buffer look unmodified */
440 msgnw(bw->parent, US "Modified flag cleared");
446 if (markv(1) && !square) {
447 B *b = bcpy(markb, markk);
449 yankdel(markb->byte, b);
455 msgnw(bw->parent, US "No block");