summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2012-09-18 12:02:33 +0100
committerPaul Gardiner <paulg.artifex@glidos.net>2012-09-18 15:00:00 +0100
commit415ae3908a392363b2196ce8c0c913c78e2f0320 (patch)
tree3558eb4d6722991c15e225b2c15e3a977ccf1f6a
parente6ed164c3935160d3d42aa15017abe2863bbdaac (diff)
downloadmupdf-415ae3908a392363b2196ce8c0c913c78e2f0320.tar.xz
Forms: add event handling api and specifically support for javascript alert
-rw-r--r--android/jni/Core.mk1
-rw-r--r--apps/jstest_main.c16
-rw-r--r--apps/pdfapp.c22
-rw-r--r--apps/pdfapp.h1
-rw-r--r--apps/win_main.c56
-rw-r--r--apps/x11_main.c16
-rw-r--r--fitz/doc_interactive.c5
-rw-r--r--fitz/fitz.h3
-rw-r--r--pdf/mupdf-internal.h6
-rw-r--r--pdf/pdf_event.c34
-rw-r--r--pdf/pdf_js.c87
-rw-r--r--win32/libmupdf-v8.vcproj4
-rw-r--r--win32/libmupdf.vcproj4
13 files changed, 254 insertions, 1 deletions
diff --git a/android/jni/Core.mk b/android/jni/Core.mk
index a156fbf8..fcfc3412 100644
--- a/android/jni/Core.mk
+++ b/android/jni/Core.mk
@@ -86,6 +86,7 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/pdf/pdf_colorspace.c \
$(MY_ROOT)/pdf/pdf_crypt.c \
$(MY_ROOT)/pdf/pdf_encoding.c \
+ $(MY_ROOT)/pdf/pdf_event.c \
$(MY_ROOT)/pdf/pdf_font.c \
$(MY_ROOT)/pdf/pdf_fontfile.c \
$(MY_ROOT)/pdf/pdf_form.c \
diff --git a/apps/jstest_main.c b/apps/jstest_main.c
index bb2f4afd..a6ff06d1 100644
--- a/apps/jstest_main.c
+++ b/apps/jstest_main.c
@@ -37,6 +37,22 @@ void winerror(pdfapp_t *app, char *msg)
exit(1);
}
+void winalert(pdfapp_t *app, fz_alert_event *alert)
+{
+ fprintf(stderr, "Alert %s: %s", alert->title, alert->message);
+ switch (alert->button_group_type)
+ {
+ case FZ_ALERT_BUTTON_GROUP_OK:
+ case FZ_ALERT_BUTTON_GROUP_OK_CANCEL:
+ alert->button_pressed = FZ_ALERT_BUTTON_OK;
+ break;
+ case FZ_ALERT_BUTTON_GROUP_YES_NO:
+ case FZ_ALERT_BUTTON_GROUP_YES_NO_CANCEL:
+ alert->button_pressed = FZ_ALERT_BUTTON_YES;
+ break;
+ }
+}
+
static char pd_password[256] = "";
static char td_textinput[LONGLINE] = "";
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index 3468e07d..0a87565a 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -101,6 +101,21 @@ void pdfapp_invert(pdfapp_t *app, fz_bbox rect)
fz_invert_pixmap_rect(app->image, rect);
}
+static void event_cb(fz_doc_event *event, void *data)
+{
+ pdfapp_t *app = (pdfapp_t *)data;
+
+ switch (event->type)
+ {
+ case FZ_DOCUMENT_EVENT_ALERT:
+ {
+ fz_alert_event *alert = fz_access_alert_event(event);
+ winalert(app, alert);
+ }
+ break;
+ }
+}
+
void pdfapp_open(pdfapp_t *app, char *filename, int reload)
{
fz_context *ctx = app->ctx;
@@ -108,8 +123,15 @@ void pdfapp_open(pdfapp_t *app, char *filename, int reload)
fz_try(ctx)
{
+ fz_interactive *idoc;
+
app->doc = fz_open_document(ctx, filename);
+ idoc = fz_interact(app->doc);
+
+ if (idoc)
+ fz_set_doc_event_callback(idoc, event_cb, app);
+
if (fz_needs_password(app->doc))
{
int okay = fz_authenticate_password(app->doc, password);
diff --git a/apps/pdfapp.h b/apps/pdfapp.h
index 43bc7b3b..46dcf291 100644
--- a/apps/pdfapp.h
+++ b/apps/pdfapp.h
@@ -37,6 +37,7 @@ extern void winhelp(pdfapp_t*);
extern void winfullscreen(pdfapp_t*, int state);
extern int winsavequery(pdfapp_t*);
extern int wingetsavepath(pdfapp_t*, char *buf, int len);
+extern void winalert(pdfapp_t *, fz_alert_event *alert);
struct pdfapp_s
{
diff --git a/apps/win_main.c b/apps/win_main.c
index 025e38db..97f927f2 100644
--- a/apps/win_main.c
+++ b/apps/win_main.c
@@ -99,6 +99,62 @@ void winerror(pdfapp_t *app, char *msg)
exit(1);
}
+void winalert(pdfapp_t *app, fz_alert_event *alert)
+{
+ int buttons = MB_OK;
+ int icon = MB_ICONWARNING;
+ int pressed = FZ_ALERT_BUTTON_NONE;
+
+ switch (alert->icon_type)
+ {
+ case FZ_ALERT_ICON_ERROR:
+ icon = MB_ICONERROR;
+ break;
+ case FZ_ALERT_ICON_WARNING:
+ icon = MB_ICONWARNING;
+ break;
+ case FZ_ALERT_ICON_QUESTION:
+ icon = MB_ICONQUESTION;
+ break;
+ case FZ_ALERT_ICON_STATUS:
+ icon = MB_ICONINFORMATION;
+ break;
+ }
+
+ switch (alert->button_group_type)
+ {
+ case FZ_ALERT_BUTTON_GROUP_OK:
+ buttons = MB_OK;
+ break;
+ case FZ_ALERT_BUTTON_GROUP_OK_CANCEL:
+ buttons = MB_OKCANCEL;
+ break;
+ case FZ_ALERT_BUTTON_GROUP_YES_NO:
+ buttons = MB_YESNO;
+ break;
+ case FZ_ALERT_BUTTON_GROUP_YES_NO_CANCEL:
+ buttons = MB_YESNOCANCEL;
+ break;
+ }
+
+ pressed = MessageBoxA(hwndframe, alert->message, alert->title, icon|buttons);
+
+ switch (pressed)
+ {
+ case IDOK:
+ alert->button_pressed = FZ_ALERT_BUTTON_OK;
+ break;
+ case IDCANCEL:
+ alert->button_pressed = FZ_ALERT_BUTTON_CANCEL;
+ break;
+ case IDNO:
+ alert->button_pressed = FZ_ALERT_BUTTON_NO;
+ break;
+ case IDYES:
+ alert->button_pressed = FZ_ALERT_BUTTON_YES;
+ }
+}
+
int winsavequery(pdfapp_t *app)
{
switch(MessageBoxA(hwndframe, "File has unsaved changes. Do you want to save", "MuPDF", MB_YESNOCANCEL))
diff --git a/apps/x11_main.c b/apps/x11_main.c
index 623187fa..182aadb4 100644
--- a/apps/x11_main.c
+++ b/apps/x11_main.c
@@ -110,6 +110,22 @@ void winwarn(pdfapp_t *app, char *msg)
fprintf(stderr, "mupdf: warning: %s\n", msg);
}
+void winalert(pdfapp_t *app, fz_alert_event *alert)
+{
+ fprintf(stderr, "Alert %s: %s", alert->title, alert->message);
+ switch (alert->button_group_type)
+ {
+ case FZ_ALERT_BUTTON_GROUP_OK:
+ case FZ_ALERT_BUTTON_GROUP_OK_CANCEL:
+ alert->button_pressed = FZ_ALERT_BUTTON_OK;
+ break;
+ case FZ_ALERT_BUTTON_GROUP_YES_NO:
+ case FZ_ALERT_BUTTON_GROUP_YES_NO_CANCEL:
+ alert->button_pressed = FZ_ALERT_BUTTON_YES;
+ break;
+ }
+}
+
char *winpassword(pdfapp_t *app, char *filename)
{
char *r = password;
diff --git a/fitz/doc_interactive.c b/fitz/doc_interactive.c
index b5d54549..f0a4f2ba 100644
--- a/fitz/doc_interactive.c
+++ b/fitz/doc_interactive.c
@@ -75,3 +75,8 @@ void fz_choice_widget_set_value(fz_interactive *idoc, fz_widget *tw, int n, char
{
pdf_choice_widget_set_value((pdf_document *)idoc, tw, n, opts);
}
+
+void fz_set_doc_event_callback(fz_interactive *idoc, fz_doc_event_cb *event_cb, void *data)
+{
+ pdf_set_doc_event_callback((pdf_document *)idoc, event_cb, data);
+}
diff --git a/fitz/fitz.h b/fitz/fitz.h
index cfd2db9f..4e5607f3 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -2602,6 +2602,7 @@ void fz_set_doc_event_callback(fz_interactive *idoc, fz_doc_event_cb *fn, void *
*/
typedef struct
{
+ char *message;
int icon_type;
int button_group_type;
char *title;
@@ -2645,7 +2646,7 @@ enum
structire are owned by mupdf and need not be freed by the
caller.
*/
-fz_alert_event *fz_access_alert_event(fz_interactive *idoc);
+fz_alert_event *fz_access_alert_event(fz_doc_event *event);
/*
fz_submit_event: details of a submit event. The app should submit
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 1d1fd4e7..7fd287dd 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -228,6 +228,9 @@ struct pdf_document_s
pdf_js *js;
int recalculating;
int dirty;
+
+ fz_doc_event_cb *event_cb;
+ void *event_cb_data;
};
pdf_document *pdf_open_document_no_run(fz_context *ctx, const char *filename);
@@ -627,6 +630,9 @@ int pdf_choice_widget_options(pdf_document *doc, fz_widget *tw, char *opts[]);
int pdf_choice_widget_is_multiselect(pdf_document *doc, fz_widget *tw);
int pdf_choice_widget_value(pdf_document *doc, fz_widget *tw, char *opts[]);
void pdf_choice_widget_set_value(pdf_document *doc, fz_widget *tw, int n, char *opts[]);
+void pdf_set_doc_event_callback(pdf_document *doc, fz_doc_event_cb *event_cb, void *data);
+
+void pdf_event_issue_alert(pdf_document *doc, fz_alert_event *event);
/*
* Javascript handler
diff --git a/pdf/pdf_event.c b/pdf/pdf_event.c
new file mode 100644
index 00000000..37f88b20
--- /dev/null
+++ b/pdf/pdf_event.c
@@ -0,0 +1,34 @@
+#include "fitz.h"
+#include "mupdf-internal.h"
+
+typedef struct
+{
+ fz_doc_event base;
+ fz_alert_event alert;
+} fz_alert_event_internal;
+
+fz_alert_event *fz_access_alert_event(fz_doc_event *event)
+{
+ fz_alert_event *alert = NULL;
+
+ if (event->type == FZ_DOCUMENT_EVENT_ALERT)
+ alert = &((fz_alert_event_internal *)event)->alert;
+
+ return alert;
+}
+
+void pdf_event_issue_alert(pdf_document *doc, fz_alert_event *alert)
+{
+ fz_alert_event_internal ievent;
+ ievent.base.type = FZ_DOCUMENT_EVENT_ALERT;
+ ievent.alert = *alert;
+
+ if (doc->event_cb)
+ doc->event_cb((fz_doc_event *)&ievent, doc->event_cb_data);
+}
+
+void pdf_set_doc_event_callback(pdf_document *doc, fz_doc_event_cb *fn, void *data)
+{
+ doc->event_cb = fn;
+ doc->event_cb_data = data;
+}
diff --git a/pdf/pdf_js.c b/pdf/pdf_js.c
index fa33c44c..2a3c865c 100644
--- a/pdf/pdf_js.c
+++ b/pdf/pdf_js.c
@@ -13,6 +13,92 @@ struct pdf_js_s
pdf_jsimp_type *apptype;
};
+static pdf_jsimp_obj *app_alert(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
+{
+ pdf_js *js = (pdf_js *)jsctx;
+ fz_context *ctx = js->doc->ctx;
+ pdf_jsimp_obj *cMsg_obj = NULL;
+ pdf_jsimp_obj *nIcon_obj = NULL;
+ pdf_jsimp_obj *nType_obj = NULL;
+ pdf_jsimp_obj *cTitle_obj = NULL;
+ pdf_jsimp_obj *nButton_obj = NULL;
+ fz_alert_event event;
+ int arg_is_obj = 0;
+
+ if (argc < 1 || argc > 6)
+ return NULL;
+
+ event.message = "";
+ event.icon_type = FZ_ALERT_ICON_ERROR;
+ event.button_group_type = FZ_ALERT_BUTTON_GROUP_OK;
+ event.title = "MuPDF";
+ event.check_box_message = NULL;
+ event.button_pressed = 0;
+
+ fz_var(cMsg_obj);
+ fz_var(nIcon_obj);
+ fz_var(nType_obj);
+ fz_var(cTitle_obj);
+ fz_try(ctx)
+ {
+ arg_is_obj = (argc == 1 && pdf_jsimp_to_type(js->imp, args[0]) != JS_TYPE_STRING);
+ if (arg_is_obj)
+ {
+ cMsg_obj = pdf_jsimp_property(js->imp, args[0], "cMsg");
+ nIcon_obj = pdf_jsimp_property(js->imp, args[0], "nIcon");
+ nType_obj = pdf_jsimp_property(js->imp, args[0], "nType");
+ cTitle_obj = pdf_jsimp_property(js->imp, args[0], "cTitle");
+ }
+ else
+ {
+ switch (argc)
+ {
+ case 6:
+ case 5:
+ case 4:
+ cTitle_obj = args[3];
+ case 3:
+ nType_obj = args[2];
+ case 2:
+ nIcon_obj = args[1];
+ case 1:
+ cMsg_obj = args[0];
+ }
+ }
+
+ if (cMsg_obj)
+ event.message = pdf_jsimp_to_string(js->imp, cMsg_obj);
+
+ if (nIcon_obj)
+ event.icon_type = (int)pdf_jsimp_to_number(js->imp, nIcon_obj);
+
+ if (nType_obj)
+ event.button_group_type = (int)pdf_jsimp_to_number(js->imp, nType_obj);
+
+ if (cTitle_obj)
+ event.title = pdf_jsimp_to_string(js->imp, cTitle_obj);
+
+ pdf_event_issue_alert(js->doc, &event);
+ nButton_obj = pdf_jsimp_from_number(js->imp, (double)event.button_pressed);
+ }
+ fz_always(ctx)
+ {
+ if (arg_is_obj)
+ {
+ pdf_jsimp_drop_obj(js->imp, cMsg_obj);
+ pdf_jsimp_drop_obj(js->imp, nIcon_obj);
+ pdf_jsimp_drop_obj(js->imp, nType_obj);
+ pdf_jsimp_drop_obj(js->imp, cTitle_obj);
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+
+ return nButton_obj;
+}
+
static pdf_obj *load_color(fz_context *ctx, pdf_jsimp *imp, pdf_jsimp_obj *val)
{
pdf_obj *col = NULL;
@@ -462,6 +548,7 @@ static void declare_dom(pdf_js *js)
/* Create the app type */
js->apptype = pdf_jsimp_new_type(imp, NULL);
+ pdf_jsimp_addmethod(imp, js->apptype, "alert", app_alert);
/* Create the document object and tell the engine to use */
pdf_jsimp_set_global_type(js->imp, js->doctype);
diff --git a/win32/libmupdf-v8.vcproj b/win32/libmupdf-v8.vcproj
index e1a5a97f..45f7f7b9 100644
--- a/win32/libmupdf-v8.vcproj
+++ b/win32/libmupdf-v8.vcproj
@@ -259,6 +259,10 @@
>
</File>
<File
+ RelativePath="..\pdf\pdf_event.c"
+ >
+ </File>
+ <File
RelativePath="..\pdf\pdf_font.c"
>
</File>
diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj
index 2715588d..f8f14908 100644
--- a/win32/libmupdf.vcproj
+++ b/win32/libmupdf.vcproj
@@ -258,6 +258,10 @@
>
</File>
<File
+ RelativePath="..\pdf\pdf_event.c"
+ >
+ </File>
+ <File
RelativePath="..\pdf\pdf_font.c"
>
</File>