qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs buffer.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs buffer.c
Date: Mon, 13 Jan 2014 23:38:16 +0000

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        14/01/13 23:38:16

Modified files:
        .              : buffer.c 

Log message:
        fix undo bugs
        
        * use bit 2 in b->save_log to suspend callbacks and logging during 
transient
          undo phase.
        * dispatch callbacks before buffer modification (eb_delete)
        * this fixes bugs in the undo system where some offsets were not 
properly
          updated, color buffer was shifted, cursor would get lost and sometimes
          crash would follow.
        * buffer colors are not undone properly

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/buffer.c?cvsroot=qemacs&r1=1.57&r2=1.58

Patches:
Index: buffer.c
===================================================================
RCS file: /sources/qemacs/qemacs/buffer.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- buffer.c    13 Jan 2014 10:31:56 -0000      1.57
+++ buffer.c    13 Jan 2014 23:38:15 -0000      1.58
@@ -242,16 +242,25 @@
                      int size)
 {
     Page *p, *p_start, *q;
-    int len, n, page_index;
-    int size0 = size;
+    int len, n, page_index, size0;
 
     if (dest->flags & BF_READONLY)
         return 0;
 
+    /* Assert parameter consistency */
+    if (dest_offset < 0 || src_offset < 0 || src_offset >= src->total_size)
+        return 0;
+
+    if (src_offset + size > src->total_size)
+        size = src->total_size - src_offset;
+
+    if (dest_offset > dest->total_size)
+        dest_offset = dest->total_size;
+
     if (size <= 0)
         return 0;
 
-    /* CG: should assert parameter consistency */
+    size0 = size;
 
     eb_addlog(dest, LOGOP_INSERT, dest_offset, size);
 
@@ -374,9 +383,11 @@
     if (offset < 0 || size <= 0)
         return;
 
-    b->total_size -= size;
+    /* dispatch callbacks before buffer update */
     eb_addlog(b, LOGOP_DELETE, offset, size);
 
+    b->total_size -= size;
+
     /* find the correct page */
     p = find_page(b, &offset);
     n = 0;
@@ -469,7 +480,7 @@
     /* set default data type */
     b->data_type = &raw_data_type;
 
-    /* XXX: suppress save_log and always use flag ? */
+    /* initial value of save_log: 0 or 1 */
     b->save_log = ((flags & BF_SAVELOG) != 0);
 
     /* initialize default mode stuff */
@@ -518,6 +529,8 @@
 void eb_clear(EditBuffer *b)
 {
     b->flags &= ~BF_READONLY;
+
+    /* XXX: should just reset logging instead of disabling it */
     b->save_log = 0;
     eb_delete(b, 0, b->total_size);
     log_reset(b);
@@ -713,7 +726,7 @@
 }
 
 /* standard callback to move offsets */
-void eb_offset_callback(__unused__ EditBuffer *b, void *opaque,
+void eb_offset_callback(EditBuffer *b, void *opaque,
                         enum LogOperation op, int offset, int size)
 {
     int *offset_ptr = opaque;
@@ -751,6 +764,10 @@
     LogBuffer lb;
     EditBufferCallbackList *l;
 
+    /* callbacks and logging disabled for composite undo phase */
+    if (b->save_log & 2)
+        return;
+
     /* call each callback */
     for (l = b->first_callback; l != NULL; l = l->next) {
         l->callback(b, l->opaque, op, offset, size);
@@ -758,8 +775,10 @@
 
     was_modified = b->modified;
     b->modified = 1;
+
     if (!b->save_log)
         return;
+
     if (!b->log_buffer) {
         char buf[MAX_BUFFERNAME_SIZE];
         /* Name should be unique because b->name is, but b->name may
@@ -775,7 +794,8 @@
     /* XXX: better test to limit size */
     if (b->nb_logs >= (NB_LOGS_MAX-1)) {
         /* no free space, delete least recent entry */
-        eb_read(b->log_buffer, 0, &lb, sizeof(LogBuffer));
+        /* XXX: should check undo record integrity */
+        eb_read(b->log_buffer, 0, &lb, sizeof(lb));
         len = lb.size;
         if (lb.op == LOGOP_INSERT)
             len = 0;
@@ -787,6 +807,9 @@
         b->nb_logs--;
     }
 
+    /* XXX: should check undo record integrity */
+    /* XXX: if inserting, should coalesce log record with previous */
+
     /* header */
     lb.pad1 = '\n';   /* make log buffer display readable */
     lb.pad2 = ':';
@@ -794,8 +817,8 @@
     lb.offset = offset;
     lb.size = size;
     lb.was_modified = was_modified;
-    eb_write(b->log_buffer, b->log_new_index, &lb, sizeof(LogBuffer));
-    b->log_new_index += sizeof(LogBuffer);
+    eb_write(b->log_buffer, b->log_new_index, &lb, sizeof(lb));
+    b->log_new_index += sizeof(lb);
 
     /* data */
     switch (op) {
@@ -819,7 +842,7 @@
 void do_undo(EditState *s)
 {
     EditBuffer *b = s->b;
-    int log_index, saved, size_trailer;
+    int log_index, size_trailer;
     LogBuffer lb;
 
     if (!b->log_buffer)
@@ -855,11 +878,10 @@
     case LOGOP_WRITE:
         /* we must disable the log because we want to record a single
            write (we should have the single operation: eb_write_buffer) */
-        saved = b->save_log;
-        b->save_log = 0;
+        b->save_log |= 2;
         eb_delete(b, lb.offset, lb.size);
         eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
-        b->save_log = saved;
+        b->save_log &= ~2;
         eb_addlog(b, LOGOP_WRITE, lb.offset, lb.size);
         s->offset = lb.offset + lb.size;
         break;
@@ -867,10 +889,9 @@
         /* we must also disable the log there because the log buffer
            would be modified BEFORE we insert it by the implicit
            eb_addlog */
-        saved = b->save_log;
-        b->save_log = 0;
+        b->save_log |= 2;
         eb_insert_buffer(b, lb.offset, b->log_buffer, log_index, lb.size);
-        b->save_log = saved;
+        b->save_log &= ~2;
         eb_addlog(b, LOGOP_INSERT, lb.offset, lb.size);
         s->offset = lb.offset + lb.size;
         break;
@@ -1641,6 +1662,7 @@
         }
 
         /* well, not very fast, but simple */
+        /* XXX: should optimize save_log system for insert sequences */
         offset_max = min(src->total_size, src_offset + size);
         size = 0;
         for (offset = src_offset; offset < offset_max;) {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]