size_t beg; /* beginning of affected region */
size_t end; /* end of affected region*/
char* data; /* pointer to deleted character data */
+ long transid; /* id of transaction this item is a part of */
} Log;
/* cursor/selection representation */
char* gapend; /* end of the gap */
Log* undo; /* undo list */
Log* redo; /* redo list */
+ long transid; /* id number of the current transaction */
Sel selection; /* the currently selected text */
} Buf;
buf->gapend = buf->bufend;
buf->undo = NULL;
buf->redo = NULL;
+ buf->transid = -1;
buf->selection = (Sel){0,0,0};
assert(buf->bufstart);
}
Log* prev = buf->undo;
log_clear(&(buf->redo));
/* decide if this is an insert or delete */
- if (!data) {
- if (prev && !prev->data && prev->end == beg)
- prev->end = end;
- else
- buf->undo = mklog(beg, end, data, prev);
+ if (!prev || (buf->transid > 0 && buf->transid == prev->transid)) {
+ buf->undo = mklog(beg, end, data, prev);
+ } else if (!data && !prev->data && prev->end == beg) {
+ prev->end = end;
+ } else if (prev->data && data && prev->beg == beg) {
+ char* newdata = strmcat(prev->data, data, 0);
+ free(data);
+ free(prev->data);
+ prev->data = newdata;
+ } else if (prev->data && data && prev->beg == beg+1) {
+ char* newdata = strmcat(data, prev->data, 0);
+ free(data);
+ free(prev->data);
+ prev->data = newdata;
+ prev->end = --prev->beg;
} else {
- if (prev && prev->data && prev->beg == beg) {
- char* newdata = strmcat(prev->data, data, 0);
- free(data);
- free(prev->data);
- prev->data = newdata;
- } else if (prev && prev->data && prev->beg == beg+1) {
- char* newdata = strmcat(data, prev->data, 0);
- free(data);
- free(prev->data);
- prev->data = newdata;
- prev->end = --prev->beg;
- } else {
- buf->undo = mklog(beg, end, data, prev);
- }
+ buf->undo = mklog(beg, end, data, prev);
}
dumplog(buf);
}
char* str = buf_gets(buf);
buf_syncgap(buf, sel.beg);
buf->gapend += nbytes;
- sel.end = sel.beg;
+ sel.end = sel.beg = (sel.beg < sel.end ? sel.beg : sel.end);
buf->selection = sel;
log_add(buf, sel.beg, sel.end, str);
}