summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-06-28 14:19:10 +0100
committerPaul Gardiner <paul@glidos.net>2012-06-28 14:20:20 +0100
commitd03b9b3ce5726f9479c35ed2b9c2bee670850a26 (patch)
tree701af10c0ee3ffc8c3e4a2a26c552920789aea08 /pdf
parentc88b0849511b970abe9864993c011af89e0daccc (diff)
downloadmupdf-d03b9b3ce5726f9479c35ed2b9c2bee670850a26.tar.xz
Forms: implement javascript form-field formatting
Consists in adding JS function AFNumber_Format and updating the DOM to include event.value
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h1
-rw-r--r--pdf/pdf_form.c84
-rw-r--r--pdf/pdf_js.c113
-rw-r--r--pdf/pdf_js_none.c5
4 files changed, 173 insertions, 30 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 69702ef3..018565d6 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -601,6 +601,7 @@ fz_widget *pdf_get_focussed_widget(pdf_document *doc);
pdf_js *pdf_new_js(pdf_document *doc);
void pdf_drop_js(pdf_js *js);
void pdf_js_setup_event(pdf_js *js, pdf_obj *target);
+char *pdf_js_getEventValue(pdf_js *js);
void pdf_js_execute(pdf_js *js, char *code);
void pdf_js_execute_count(pdf_js *js, char *code, int count);
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index 56e2e5d8..65f9392f 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -1156,7 +1156,7 @@ static pdf_xobject *load_or_create_form(pdf_document *doc, pdf_obj *obj, fz_rect
return form;
}
-static void update_text_appearance(pdf_document *doc, pdf_obj *obj)
+static void update_text_appearance(pdf_document *doc, pdf_obj *obj, char *eventValue)
{
fz_context *ctx = doc->ctx;
text_widget_info info;
@@ -1175,7 +1175,11 @@ static void update_text_appearance(pdf_document *doc, pdf_obj *obj)
fz_var(text);
fz_try(ctx)
{
- text = pdf_field_getValue(doc, obj);
+ if (eventValue)
+ text = fz_strdup(ctx, eventValue);
+ else
+ text = pdf_field_getValue(doc, obj);
+
get_text_widget_info(doc, obj, &info);
form = load_or_create_form(doc, obj, &rect);
@@ -1348,27 +1352,6 @@ static void update_pushbutton_appearance(pdf_document *doc, pdf_obj *obj)
}
}
-void pdf_update_appearance(pdf_document *doc, pdf_obj *obj)
-{
- if (!pdf_dict_gets(obj, "AP") || pdf_dict_gets(obj, "Dirty"))
- {
- if (!strcmp(pdf_to_name(pdf_dict_gets(obj, "Subtype")), "Widget"))
- {
- switch(get_field_type(doc, obj))
- {
- case FZ_WIDGET_TYPE_TEXT:
- update_text_appearance(doc, obj);
- break;
- case FZ_WIDGET_TYPE_PUSHBUTTON:
- update_pushbutton_appearance(doc, obj);
- break;
- }
- }
-
- pdf_dict_dels(obj, "Dirty");
- }
-}
-
static void reset_field(pdf_document *doc, pdf_obj *obj)
{
fz_context *ctx = doc->ctx;
@@ -1414,13 +1397,10 @@ static void reset_field(pdf_document *doc, pdf_obj *obj)
}
}
-static void execute_action(pdf_document *doc, pdf_obj *obj)
+static void execute_action(pdf_document *doc, pdf_obj *obj, pdf_obj *a)
{
fz_context *ctx = doc->ctx;
- pdf_obj *a;
-
- a = pdf_dict_gets(obj, "A");
- while (a)
+ if (a)
{
char *type = pdf_to_name(pdf_dict_gets(a, "S"));
@@ -1479,7 +1459,53 @@ static void execute_action(pdf_document *doc, pdf_obj *obj)
reset_field(doc, field);
}
}
+ }
+}
+void pdf_update_appearance(pdf_document *doc, pdf_obj *obj)
+{
+ if (!pdf_dict_gets(obj, "AP") || pdf_dict_gets(obj, "Dirty"))
+ {
+ if (!strcmp(pdf_to_name(pdf_dict_gets(obj, "Subtype")), "Widget"))
+ {
+ switch(get_field_type(doc, obj))
+ {
+ case FZ_WIDGET_TYPE_TEXT:
+ {
+ pdf_obj *formatting = pdf_dict_getp(obj, "AA/F");
+ if (formatting)
+ {
+ /* Apply formatting */
+ execute_action(doc, obj, formatting);
+ /* Update appearance from JS event.value */
+ update_text_appearance(doc, obj, pdf_js_getEventValue(doc->js));
+ }
+ else
+ {
+ /* Update appearance from field value */
+ update_text_appearance(doc, obj, NULL);
+ }
+ }
+ break;
+ case FZ_WIDGET_TYPE_PUSHBUTTON:
+ update_pushbutton_appearance(doc, obj);
+ break;
+ }
+ }
+
+ pdf_dict_dels(obj, "Dirty");
+ }
+}
+
+static void execute_action_chain(pdf_document *doc, pdf_obj *obj)
+{
+ fz_context *ctx = doc->ctx;
+ pdf_obj *a;
+
+ a = pdf_dict_gets(obj, "A");
+ while (a)
+ {
+ execute_action(doc, obj, a);
a = pdf_dict_gets(a, "Next");
}
}
@@ -1670,7 +1696,7 @@ int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event)
break;
}
- execute_action(doc, annot->obj);
+ execute_action_chain(doc, annot->obj);
}
break;
}
diff --git a/pdf/pdf_js.c b/pdf/pdf_js.c
index 72111775..d3022bc1 100644
--- a/pdf/pdf_js.c
+++ b/pdf/pdf_js.c
@@ -4,6 +4,7 @@
typedef struct pdf_js_event_s
{
pdf_obj *target;
+ char *value;
} pdf_js_event;
struct pdf_js_s
@@ -170,6 +171,23 @@ static void event_setTarget(void *jsctx, void *obj, pdf_jsimp_obj *val)
fz_warn(js->doc->ctx, "Unexpected call to event_setTarget");
}
+static pdf_jsimp_obj *event_getValue(void *jsctx, void *obj)
+{
+ pdf_js *js = (pdf_js *)jsctx;
+ pdf_js_event *e = (pdf_js_event *)obj;
+
+ return pdf_jsimp_fromString(js->imp, js->event.value);
+}
+
+static void event_setValue(void *jsctx, void *obj, pdf_jsimp_obj *val)
+{
+ pdf_js *js = (pdf_js *)jsctx;
+ fz_context *ctx = js->doc->ctx;
+ fz_free(ctx, js->event.value);
+ js->event.value = NULL;
+ js->event.value = fz_strdup(ctx, pdf_jsimp_toString(js->imp, val));
+}
+
static pdf_jsimp_obj *doc_getEvent(void *jsctx, void *obj)
{
pdf_js *js = (pdf_js *)jsctx;
@@ -222,6 +240,7 @@ static void declare_dom(pdf_js *js)
/* Create the event type */
js->eventtype = pdf_jsimp_new_type(imp, NULL);
pdf_jsimp_addproperty(imp, js->eventtype, "target", event_getTarget, event_setTarget);
+ pdf_jsimp_addproperty(imp, js->eventtype, "value", event_getValue, event_setValue);
/* Create the field type */
js->fieldtype = pdf_jsimp_new_type(imp, NULL);
@@ -256,7 +275,84 @@ static void preload_helpers(pdf_js *js)
"color.yellow = [ \"CMYK\", 0,0,1,0 ];\n"
"color.dkGray = [ \"G\", 0.25];\n"
"color.gray = [ \"G\", 0.5];\n"
- "color.ltGray = [ \"G\", 0.75];\n");
+ "color.ltGray = [ \"G\", 0.75];\n"
+ "\n"
+ "function AFNumber_Format(nDec,sepStyle,negStyle,currStyle,strCurrency,bCurrencyPrepend)\n"
+ "{\n"
+ " var val = event.value;\n"
+ " var fracpart;\n"
+ " var intpart;\n"
+ " var point = sepStyle&2 ? ',' : '.';\n"
+ " var separator = sepStyle&2 ? '.' : ',';\n"
+ "\n"
+ " if (/^\\D*\\./.test(val))\n"
+ " val = '0'+val;\n"
+ "\n"
+ " var groups = val.match(/\\d+/g);\n"
+ "\n"
+ " switch (groups.length)\n"
+ " {\n"
+ " case 0:\n"
+ " return;\n"
+ " case 1:\n"
+ " fracpart = '';\n"
+ " intpart = groups[0];\n"
+ " break;\n"
+ " default:\n"
+ " fracpart = groups.pop();\n"
+ " intpart = groups.join('');\n"
+ " break;\n"
+ " }\n"
+ "\n"
+ " // Remove leading zeros\n"
+ " intpart = intpart.replace(/^0*/,'');\n"
+ " if (!intpart)\n"
+ " intpart = '0';\n"
+ "\n"
+ " if ((sepStyle & 1) == 0)\n"
+ " {\n"
+ " // Add the thousands sepearators: pad to length multiple of 3 with zeros,\n"
+ " // split into 3s, join with separator, and remove the leading zeros\n"
+ " intpart = new Array(2-(intpart.length+2)%3+1).join('0') + intpart;\n"
+ " intpart = intpart.match(/.../g).join(separator).replace(/^0*/,'');\n"
+ " }\n"
+ "\n"
+ " if (!intpart)\n"
+ " intpart = '0';\n"
+ "\n"
+ " // Adjust fractional part to correct number of decimal places\n"
+ " fracpart += new Array(nDec+1).join('0');\n"
+ " fracpart = fracpart.substr(0,nDec);\n"
+ "\n"
+ " if (fracpart)\n"
+ " intpart += point+fracpart;\n"
+ "\n"
+ " if (bCurrencyPrepend)\n"
+ " intpart = strCurrency+intpart;\n"
+ " else\n"
+ " intpart += strCurrency;\n"
+ "\n"
+ " if (/-/.test(val))\n"
+ " {\n"
+ " switch (negStyle)\n"
+ " {\n"
+ " case 0:\n"
+ " intpart = '-'+intpart;\n"
+ " break;\n"
+ " case 1:\n"
+ " break;\n"
+ " case 2:\n"
+ " case 3:\n"
+ " intpart = '('+intpart+')';\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " if (negStyle&1)\n"
+ " event.target.textColor = /-/.text(val) ? color.red : color.black;\n"
+ "\n"
+ " event.value = intpart;\n"
+ "}\n");
}
pdf_js *pdf_new_js(pdf_document *doc)
@@ -338,6 +434,7 @@ void pdf_drop_js(pdf_js *js)
if (js)
{
fz_context *ctx = js->doc->ctx;
+ fz_free(ctx, js->event.value);
pdf_jsimp_drop_type(js->imp, js->fieldtype);
pdf_jsimp_drop_type(js->imp, js->doctype);
pdf_drop_jsimp(js->imp);
@@ -348,7 +445,21 @@ void pdf_drop_js(pdf_js *js)
void pdf_js_setup_event(pdf_js *js, pdf_obj *target)
{
if (js)
+ {
+ fz_context *ctx = js->doc->ctx;
+ char *val = pdf_field_getValue(js->doc, target);
+
js->event.target = target;
+
+ fz_free(ctx, js->event.value);
+ js->event.value = NULL;
+ js->event.value = fz_strdup(ctx, val?val:"");
+ }
+}
+
+char *pdf_js_getEventValue(pdf_js *js)
+{
+ return js ? js->event.value : NULL;
}
void pdf_js_execute(pdf_js *js, char *code)
diff --git a/pdf/pdf_js_none.c b/pdf/pdf_js_none.c
index bc8d2ee7..34c7c491 100644
--- a/pdf/pdf_js_none.c
+++ b/pdf/pdf_js_none.c
@@ -17,6 +17,11 @@ void pdf_js_setup_event(pdf_js *js, pdf_obj *target)
{
}
+char *pdf_js_getEventValue(pdf_js *js)
+{
+ return "";
+}
+
void pdf_js_execute(pdf_js *js, char *code)
{
}