diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2012-08-31 17:09:05 +0100 |
---|---|---|
committer | Paul Gardiner <paulg.artifex@glidos.net> | 2012-08-31 17:09:05 +0100 |
commit | 769f75087c414d982f33a46c5439ad63b9d4df11 (patch) | |
tree | b660fd9c43db95bd16da2d77d7a807a8b1f936d3 | |
parent | 01ecb79f9bcdeb9280554aff2e26218c07d088dd (diff) | |
download | mupdf-769f75087c414d982f33a46c5439ad63b9d4df11.tar.xz |
Forms: rework form reset action to use new method introduced for JS
-rw-r--r-- | pdf/mupdf-internal.h | 1 | ||||
-rw-r--r-- | pdf/pdf_form.c | 169 | ||||
-rw-r--r-- | pdf/pdf_js.c | 48 |
3 files changed, 110 insertions, 108 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index eec45acd..b3555f9e 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -575,6 +575,7 @@ void pdf_field_setFillColor(pdf_document *doc, pdf_obj *field, pdf_obj *col); void pdf_field_setTextColor(pdf_document *doc, pdf_obj *field, pdf_obj *col); int pdf_field_getDisplay(pdf_document *doc, pdf_obj *field); void pdf_field_setDisplay(pdf_document *doc, pdf_obj *field, int d); +pdf_obj *pdf_get_field(pdf_obj *form, char *name); void pdf_field_reset(pdf_document *doc, pdf_obj *field); /* diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c index 451ba0c0..729baba8 100644 --- a/pdf/pdf_form.c +++ b/pdf/pdf_form.c @@ -1462,6 +1462,50 @@ static void update_pushbutton_appearance(pdf_document *doc, pdf_obj *obj) } } +static pdf_obj *find_field(pdf_obj *dict, char *name, int len) +{ + pdf_obj *field; + + int i, n = pdf_array_len(dict); + + for (i = 0; i < n; i++) + { + char *part; + + field = pdf_array_get(dict, i); + part = pdf_to_str_buf(pdf_dict_gets(field, "T")); + if (strlen(part) == len && !memcmp(part, name, len)) + return field; + } + + return NULL; +} + +pdf_obj *pdf_get_field(pdf_obj *form, char *name) +{ + char *dot; + char *namep; + pdf_obj *dict = NULL; + int len; + + /* Process the fully qualified field name which has + * the partial names delimited by '.'. Pretend there + * was a preceding '.' to simplify the loop */ + dot = name - 1; + + while (dot && form) + { + namep = dot + 1; + dot = strchr(namep, '.'); + len = dot ? dot - namep : strlen(namep); + dict = find_field(form, namep, len); + if (dot) + form = pdf_dict_gets(dict, "Kids"); + } + + return dict; +} + void pdf_field_reset(pdf_document *doc, pdf_obj *field) { fz_context *ctx = doc->ctx; @@ -1475,6 +1519,11 @@ void pdf_field_reset(pdf_document *doc, pdf_obj *field) * dictionaries, and attempts to remove V will be harmless. */ pdf_obj *dv = pdf_dict_gets(field, "DV"); pdf_obj *kids = pdf_dict_gets(field, "Kids"); + pdf_obj *noreset = pdf_dict_gets(field, "NoReset"); + + /* Don't process fields we have marked not to be reset */ + if (noreset) + return; if (dv) pdf_dict_puts(field, "V", dv); @@ -1533,49 +1582,75 @@ void pdf_field_reset(pdf_document *doc, pdf_obj *field) doc->dirty = 1; } -static void reset_field(pdf_document *doc, pdf_obj *obj) + +static void reset_form(pdf_document *doc, pdf_obj *fields, int exclude) { fz_context *ctx = doc->ctx; + pdf_obj *form = pdf_dict_getp(doc->trailer, "Root/AcroForm/Fields"); + int i, n; - doc->dirty = 1; - - switch (pdf_field_getType(doc, obj)) + if (exclude) { - case FZ_WIDGET_TYPE_RADIOBUTTON: - case FZ_WIDGET_TYPE_CHECKBOX: + /* mark the fields we don't want to reset */ + pdf_obj *nil = pdf_new_null(ctx); + + fz_try(ctx) { - pdf_obj *name = NULL; + n = pdf_array_len(fields); - fz_var(name); - fz_try(ctx) - { - name = pdf_new_name(ctx, "Off"); - pdf_dict_puts(obj, "AS", name); - } - fz_always(ctx) - { - pdf_drop_obj(name); - } - fz_catch(ctx) + for (i = 0; i < n; i++) { - fz_rethrow(ctx); + pdf_obj *field = pdf_array_get(fields, i); + + if (pdf_is_string(field)) + field = pdf_get_field(form, pdf_to_str_buf(field)); + + if (field) + pdf_dict_puts(field, "NoReset", nil); } } - break; - default: + fz_always(ctx) { - pdf_obj *def_val = pdf_dict_gets(obj, "DV"); + pdf_drop_obj(nil); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } - if (def_val) - { - pdf_dict_puts(obj, "V", def_val); - } - else - { - pdf_dict_dels(obj, "V"); - } + /* reset all unmarked fields */ + n = pdf_array_len(form); - pdf_field_mark_dirty(ctx, obj); + for (i = 0; i < n; i++) + pdf_field_reset(doc, pdf_array_get(form, i)); + + /* Unmark the marked fields */ + n = pdf_array_len(fields); + + for (i = 0; i < n; i++) + { + pdf_obj *field = pdf_array_get(fields, i); + + if (pdf_is_string(field)) + field = pdf_get_field(form, pdf_to_str_buf(field)); + + if (field) + pdf_dict_dels(field, "NoReset"); + } + } + else + { + n = pdf_array_len(fields); + + for (i = 0; i < n; i++) + { + pdf_obj *field = pdf_array_get(fields, i); + + if (pdf_is_string(field)) + field = pdf_get_field(form, pdf_to_str_buf(field)); + + if (field) + pdf_field_reset(doc, field); } } } @@ -1609,37 +1684,7 @@ static void execute_action(pdf_document *doc, pdf_obj *obj, pdf_obj *a) } else if (!strcmp(type, "ResetForm")) { - int flags = pdf_to_int(pdf_dict_gets(a, "Flags")); - pdf_obj *affected_fields = pdf_dict_gets(a, "Fields"); - pdf_obj *all_fields = pdf_dict_getp(doc->trailer, "Root/AcroForm/Fields"); - int i, n = pdf_array_len(all_fields); - - for (i = 0; i < n; i++) - { - pdf_obj *field = pdf_array_get(all_fields, i); - char *name = pdf_to_str_buf(pdf_dict_gets(field, "T")); - int j, m = pdf_array_len(affected_fields); - int found = 0; - - for (j = 0; j < m && !found; j++) - { - pdf_obj *tfield = pdf_array_get(affected_fields, j); - char *tname; - - /* Elements if the array are either indirect references - * to fields or field names. */ - tname = pdf_to_str_buf(pdf_is_string(tfield) ? tfield : pdf_dict_gets(tfield, "T")); - - if (!strcmp(tname, name)) - found = 1; - } - - if (flags & 1) - found = !found; - - if (found) - reset_field(doc, field); - } + reset_form(doc, pdf_dict_gets(a, "Fields"), pdf_to_int(pdf_dict_gets(a, "Flags")) & 1); } } } diff --git a/pdf/pdf_js.c b/pdf/pdf_js.c index fb2f34cb..28c49186 100644 --- a/pdf/pdf_js.c +++ b/pdf/pdf_js.c @@ -272,25 +272,6 @@ static void doc_setApp(void *jsctx, void *obj, pdf_jsimp_obj *val) fz_warn(js->doc->ctx, "Unexpected call to doc_setApp"); } -static pdf_obj *find_field(pdf_obj *dict, char *name, int len) -{ - pdf_obj *field; - - int i, n = pdf_array_len(dict); - - for (i = 0; i < n; i++) - { - char *part; - - field = pdf_array_get(dict, i); - part = pdf_to_str_buf(pdf_dict_gets(field, "T")); - if (strlen(part) == len && !memcmp(part, name, len)) - break; - } - - return i < n ? field : NULL; -} - static char *utf8_to_pdf(fz_context *ctx, char *utf8) { char *pdf = fz_malloc(ctx, strlen(utf8)+1); @@ -324,31 +305,6 @@ static char *utf8_to_pdf(fz_context *ctx, char *utf8) return pdf; } -static pdf_obj *get_field(pdf_obj *form, char *name) -{ - char *dot; - char *namep; - pdf_obj *dict = NULL; - int len; - - /* Process the fully qualified field name which has - * the partial names delimited by '.'. Pretend there - * was a preceding '.' to simplify the loop */ - dot = name - 1; - - while (dot && form) - { - namep = dot + 1; - dot = strchr(namep, '.'); - len = dot ? dot - namep : strlen(namep); - dict = find_field(form, namep, len); - if (dot) - form = pdf_dict_gets(dict, "Kids"); - } - - return dict; -} - static pdf_jsimp_obj *doc_getField(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[]) { pdf_js *js = (pdf_js *)jsctx; @@ -369,7 +325,7 @@ static pdf_jsimp_obj *doc_getField(void *jsctx, void *obj, int argc, pdf_jsimp_o if (utf8) { name = utf8_to_pdf(ctx, utf8); - dict = get_field(js->form, name); + dict = pdf_get_field(js->form, name); } } fz_always(ctx) @@ -399,7 +355,7 @@ static void reset_field(pdf_js *js, pdf_jsimp_obj *item) fz_try(ctx) { name = utf8_to_pdf(ctx, utf8); - field = get_field(js->form, name); + field = pdf_get_field(js->form, name); if (field) pdf_field_reset(js->doc, field); } |