Fix undo-to-vanilla in TestFormExpenses.pdf.
authorRobin Watts <[email protected]>
Thu, 29 Jul 2021 18:15:05 +0000 (19:15 +0100)
committerRobin Watts <[email protected]>
Mon, 2 Aug 2021 11:15:06 +0000 (12:15 +0100)
If we load TestFormExpenses.pdf, fill in the name field, and then
undo, we do not return to the vanilla unchanged state.

This is because the first edit done to the file as part of editing
the name field is the addition of an object, rather than the
modification of an existing one. I had forgotten to add such objects
to the undo history, so they were left (unreferenced) in the
incremental history, making the document dirty.

The fix is to add these to the fragments too. The document now
behaves as expected.

include/mupdf/pdf/object.h
source/pdf/pdf-annot.c
source/pdf/pdf-object.c
source/pdf/pdf-xref.c

index ce6b0ef45f6350246ad53c74d754641402a0b40d..fbc6083fd8e8bc7c1736d6423e0a81ddd6a45ecf 100644 (file)
@@ -294,4 +294,7 @@ void pdf_serialise_journal(fz_context *ctx, pdf_document *doc, fz_output *out);
 /* Internal call as part of loading a snapshot of a PDF document. */
 void pdf_deserialise_journal(fz_context *ctx, pdf_document *doc, fz_stream *stm);
 
+/* Internal call as part of creating objects. */
+void pdf_add_journal_fragment(fz_context *ctx, pdf_document *doc, int parent, pdf_obj *copy, fz_buffer *copy_stream, int newobj);
+
 #endif
index dd80494d75e64fbf56bed2456f2a94b20a5ef267..394d7c6a3327c42a19ae47e34ba784ab34e9b676 100644 (file)
@@ -250,6 +250,13 @@ pdf_annot_request_resynthesis(fz_context *ctx, pdf_annot *annot)
                        return;
        }
 
+       /* If there are no changes, there is no need to request a resynthesis
+        * (and indeed, we must not, because any changes caused by the resynth
+        * will go in as implicit changes into a potentially-non-existent
+        * previous journal fragment). */
+       if (!pdf_has_unsaved_changes(ctx, annot->page->doc))
+               return;
+
        annot->needs_new_ap = 1;
        annot->page->doc->resynth_required = 1;
 }
index bee42a2df1454bd6f1c10f2fdcdba803f2d0c381..fe45adfa9fc5db6ed6b2d8462cca5a4ba5abf355 100644 (file)
@@ -746,9 +746,9 @@ new_entry(fz_context *ctx, pdf_document *doc, char *operation, int nest)
 
                /* We create a new entry, and link it into the middle of
                 * the chain. If we actually come to put anything into
-                * it later, then the call to add_fragment during that
-                * addition will discard everything in the history that
-                * follows it. */
+                * it later, then the call to pdf_add_journal_fragment
+                * during that addition will discard everything in the
+                * history that follows it. */
                entry = fz_malloc_struct(ctx, pdf_journal_entry);
 
                if (doc->journal->current == NULL)
@@ -1149,13 +1149,16 @@ pdf_serialise_journal(fz_context *ctx, pdf_document *doc, fz_output *out)
        fz_write_printf(ctx, out, "endjournal\n");
 }
 
-static void
-add_fragment(fz_context *ctx, pdf_document *doc, int parent, pdf_obj *copy, fz_buffer *copy_stream, int newobj)
+void
+pdf_add_journal_fragment(fz_context *ctx, pdf_document *doc, int parent, pdf_obj *copy, fz_buffer *copy_stream, int newobj)
 {
-       pdf_journal_entry *entry = doc->journal->current;
+       pdf_journal_entry *entry;
        pdf_journal_fragment *frag;
 
-       fz_var(copy_stream);
+       if (doc->journal == NULL)
+               return;
+
+       entry = doc->journal->current;
 
        if (entry->next)
        {
@@ -1293,7 +1296,7 @@ void pdf_deserialise_journal(fz_context *ctx, pdf_document *doc, fz_stream *stm)
                /* Read the object/stream for the next fragment. */
                obj = pdf_parse_journal_obj(ctx, doc, stm, &num, &buffer, &newobj);
 
-               add_fragment(ctx, doc, num, obj, buffer, newobj);
+               pdf_add_journal_fragment(ctx, doc, num, obj, buffer, newobj);
        }
 
        fz_skip_space(ctx, stm);
@@ -1440,7 +1443,7 @@ static void prepare_object_for_alteration(fz_context *ctx, pdf_obj *obj, pdf_obj
                        if (pdf_obj_num_is_stream(ctx, doc, parent))
                                copy_stream = pdf_load_raw_stream_number(ctx, doc, parent);
                }
-               add_fragment(ctx, doc, parent, copy, copy_stream, was_empty);
+               pdf_add_journal_fragment(ctx, doc, parent, copy, copy_stream, was_empty);
        }
        fz_always(ctx)
        {
index 16306153b5f2dc806d94d8e42d5d0e3ec604d213..287861dde3b694974c9b29308e60d4d310f1cd28 100644 (file)
@@ -2413,6 +2413,9 @@ pdf_create_object(fz_context *ctx, pdf_document *doc)
        entry->stm_ofs = 0;
        entry->stm_buf = NULL;
        entry->obj = NULL;
+
+       pdf_add_journal_fragment(ctx, doc, num, NULL, NULL, 1);
+
        return num;
 }