Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "mupdf/pdf.h"
2
3
/* TODO: js->doc -> doc */
4
/* TODO: js->ctx -> ctx */
5
6
struct pdf_js_s
7
{
8
fz_context *ctx;
9
pdf_document *doc;
10
pdf_obj *form;
11
pdf_js_event event;
12
pdf_jsimp *imp;
13
pdf_jsimp_type *doctype;
14
pdf_jsimp_type *eventtype;
15
pdf_jsimp_type *fieldtype;
16
pdf_jsimp_type *apptype;
17
};
18
19
static pdf_jsimp_obj *app_alert(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
20
{
21
pdf_js *js = (pdf_js *)jsctx;
22
fz_context *ctx = js->ctx;
23
pdf_jsimp_obj *cMsg_obj = NULL;
24
pdf_jsimp_obj *nIcon_obj = NULL;
25
pdf_jsimp_obj *nType_obj = NULL;
26
pdf_jsimp_obj *cTitle_obj = NULL;
27
pdf_jsimp_obj *nButton_obj = NULL;
28
pdf_alert_event event;
29
int arg_is_obj = 0;
30
31
if (argc < 1 || argc > 6)
32
return NULL;
33
34
event.message = "";
35
event.icon_type = PDF_ALERT_ICON_ERROR;
36
event.button_group_type = PDF_ALERT_BUTTON_GROUP_OK;
37
event.title = "MuPDF";
38
event.check_box_message = NULL;
39
event.button_pressed = 0;
40
41
fz_var(cMsg_obj);
42
fz_var(nIcon_obj);
43
fz_var(nType_obj);
44
fz_var(cTitle_obj);
45
fz_try(ctx)
46
{
47
arg_is_obj = (argc == 1 && pdf_jsimp_to_type(js->imp, args[0]) != JS_TYPE_STRING);
48
if (arg_is_obj)
49
{
50
cMsg_obj = pdf_jsimp_property(js->imp, args[0], "cMsg");
51
nIcon_obj = pdf_jsimp_property(js->imp, args[0], "nIcon");
52
nType_obj = pdf_jsimp_property(js->imp, args[0], "nType");
53
cTitle_obj = pdf_jsimp_property(js->imp, args[0], "cTitle");
54
}
55
else
56
{
57
switch (argc)
58
{
59
case 6:
60
case 5:
61
case 4:
62
cTitle_obj = args[3];
63
case 3:
64
nType_obj = args[2];
65
case 2:
66
nIcon_obj = args[1];
67
case 1:
68
cMsg_obj = args[0];
69
}
70
}
71
72
if (cMsg_obj)
73
event.message = pdf_jsimp_to_string(js->imp, cMsg_obj);
74
75
if (nIcon_obj)
76
event.icon_type = (int)pdf_jsimp_to_number(js->imp, nIcon_obj);
77
78
if (nType_obj)
79
event.button_group_type = (int)pdf_jsimp_to_number(js->imp, nType_obj);
80
81
if (cTitle_obj)
82
event.title = pdf_jsimp_to_string(js->imp, cTitle_obj);
83
84
pdf_event_issue_alert(ctx, js->doc, &event);
85
nButton_obj = pdf_jsimp_from_number(js->imp, (double)event.button_pressed);
86
}
87
fz_always(ctx)
88
{
89
if (arg_is_obj)
90
{
91
pdf_jsimp_drop_obj(js->imp, cMsg_obj);
92
pdf_jsimp_drop_obj(js->imp, nIcon_obj);
93
pdf_jsimp_drop_obj(js->imp, nType_obj);
94
pdf_jsimp_drop_obj(js->imp, cTitle_obj);
95
}
96
}
97
fz_catch(ctx)
98
{
99
fz_rethrow(ctx);
100
}
101
102
return nButton_obj;
103
}
104
105
static pdf_jsimp_obj *app_execDialog(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
106
{
107
pdf_js *js = (pdf_js *)jsctx;
108
109
pdf_event_issue_exec_dialog(js->ctx, js->doc);
110
111
return NULL;
112
}
113
114
static pdf_jsimp_obj *app_execMenuItem(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
115
{
116
pdf_js *js = (pdf_js *)jsctx;
117
118
if (argc == 1)
119
pdf_event_issue_exec_menu_item(js->ctx, js->doc, pdf_jsimp_to_string(js->imp, args[0]));
120
121
return NULL;
122
}
123
124
static pdf_jsimp_obj *app_launchURL(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
125
{
126
pdf_js *js = (pdf_js *)jsctx;
127
char *cUrl;
128
int bNewFrame = 0;
129
130
switch (argc)
131
{
132
default:
133
return NULL;
134
case 2:
135
bNewFrame = (int)pdf_jsimp_to_number(js->imp, args[1]);
136
case 1:
137
cUrl = pdf_jsimp_to_string(js->imp, args[0]);
138
}
139
140
pdf_event_issue_launch_url(js->ctx, js->doc, cUrl, bNewFrame);
141
142
return NULL;
143
}
144
145
static pdf_obj *load_color(fz_context *ctx, pdf_document *doc, pdf_jsimp *imp, pdf_jsimp_obj *val)
146
{
147
pdf_obj *col = NULL;
148
pdf_obj *comp = NULL;
149
pdf_jsimp_obj *jscomp = NULL;
150
int i;
151
int n;
152
153
n = pdf_jsimp_array_len(imp, val);
154
155
/* The only legitimate color expressed as an array of length 1
156
* is [T], meaning transparent. Return a NULL object to represent
157
* transparent */
158
if (n <= 1)
159
return NULL;
160
161
col = pdf_new_array(ctx, doc, n-1);
162
163
fz_var(comp);
164
fz_var(jscomp);
165
fz_try(ctx)
166
{
167
for (i = 0; i < n-1; i++)
168
{
169
jscomp = pdf_jsimp_array_item(imp, val, i+1);
170
comp = pdf_new_real(ctx, doc, pdf_jsimp_to_number(imp, jscomp));
171
pdf_array_push(ctx, col, comp);
172
pdf_jsimp_drop_obj(imp, jscomp);
173
jscomp = NULL;
174
pdf_drop_obj(ctx, comp);
175
comp = NULL;
176
}
177
}
178
fz_catch(ctx)
179
{
180
pdf_jsimp_drop_obj(imp, jscomp);
181
pdf_drop_obj(ctx, comp);
182
pdf_drop_obj(ctx, col);
183
fz_rethrow(ctx);
184
}
185
186
return col;
187
}
188
189
static pdf_jsimp_obj *field_buttonSetCaption(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
190
{
191
pdf_js *js = (pdf_js *)jsctx;
192
pdf_obj *field = (pdf_obj *)obj;
193
char *name;
194
195
if (argc != 1)
196
return NULL;
197
198
name = pdf_jsimp_to_string(js->imp, args[0]);
199
pdf_field_set_button_caption(js->ctx, js->doc, field, name);
200
201
return NULL;
202
}
203
204
static pdf_jsimp_obj *field_getName(void *jsctx, void *obj)
205
{
206
pdf_js *js = (pdf_js *)jsctx;
207
fz_context *ctx = js->ctx;
208
pdf_obj *field = (pdf_obj *)obj;
209
char *name;
210
pdf_jsimp_obj *oname = NULL;
211
212
if (field == NULL)
213
return NULL;
214
215
name = pdf_field_name(ctx, js->doc, field);
216
fz_try(ctx)
217
{
218
oname = pdf_jsimp_from_string(js->imp, name);
219
}
220
fz_always(ctx)
221
{
222
fz_free(ctx, name);
223
}
224
fz_catch(ctx)
225
{
226
fz_rethrow(ctx);
227
}
228
229
return oname;
230
}
231
232
static void field_setName(void *jsctx, void *obj, pdf_jsimp_obj *val)
233
{
234
pdf_js *js = (pdf_js *)jsctx;
235
fz_warn(js->ctx, "Unexpected call to field_setName");
236
}
237
238
static pdf_jsimp_obj *field_getDisplay(void *jsctx, void *obj)
239
{
240
pdf_js *js = (pdf_js *)jsctx;
241
pdf_obj *field = (pdf_obj *)obj;
242
243
return field ? pdf_jsimp_from_number(js->imp, (double)pdf_field_display(js->ctx, js->doc, field)) : NULL;
244
}
245
246
static void field_setDisplay(void *jsctx, void *obj, pdf_jsimp_obj *val)
247
{
248
pdf_js *js = (pdf_js *)jsctx;
249
pdf_obj *field = (pdf_obj *)obj;
250
if (field)
251
pdf_field_set_display(js->ctx, js->doc, field, (int)pdf_jsimp_to_number(js->imp, val));
252
}
253
254
static pdf_jsimp_obj *field_getFillColor(void *jsctx, void *obj)
255
{
256
return NULL;
257
}
258
259
static void field_setFillColor(void *jsctx, void *obj, pdf_jsimp_obj *val)
260
{
261
pdf_js *js = (pdf_js *)jsctx;
262
fz_context *ctx = js->ctx;
263
pdf_obj *field = (pdf_obj *)obj;
264
pdf_obj *col;
265
266
if (!field)
267
return;
268
269
col = load_color(ctx, js->doc, js->imp, val);
270
fz_try(ctx)
271
{
272
pdf_field_set_fill_color(ctx, js->doc, field, col);
273
}
274
fz_always(ctx)
275
{
276
pdf_drop_obj(ctx, col);
277
}
278
fz_catch(ctx)
279
{
280
fz_rethrow(ctx);
281
}
282
}
283
284
static pdf_jsimp_obj *field_getTextColor(void *jsctx, void *obj)
285
{
286
return NULL;
287
}
288
289
static void field_setTextColor(void *jsctx, void *obj, pdf_jsimp_obj *val)
290
{
291
pdf_js *js = (pdf_js *)jsctx;
292
fz_context *ctx = js->ctx;
293
pdf_obj *field = (pdf_obj *)obj;
294
pdf_obj *col;
295
296
if (!field)
297
return;
298
299
col = load_color(ctx, js->doc, js->imp, val);
300
fz_try(ctx)
301
{
302
pdf_field_set_text_color(ctx, js->doc, field, col);
303
}
304
fz_always(ctx)
305
{
306
pdf_drop_obj(ctx, col);
307
}
308
fz_catch(ctx)
309
{
310
fz_rethrow(ctx);
311
}
312
}
313
314
static pdf_jsimp_obj *field_getBorderStyle(void *jsctx, void *obj)
315
{
316
pdf_js *js = (pdf_js *)jsctx;
317
pdf_obj *field = (pdf_obj *)obj;
318
319
return field ? pdf_jsimp_from_string(js->imp, pdf_field_border_style(js->ctx, js->doc, field)) : NULL;
320
}
321
322
static void field_setBorderStyle(void *jsctx, void *obj, pdf_jsimp_obj *val)
323
{
324
pdf_js *js = (pdf_js *)jsctx;
325
pdf_obj *field = (pdf_obj *)obj;
326
327
if (field)
328
pdf_field_set_border_style(js->ctx, js->doc, field, pdf_jsimp_to_string(js->imp, val));
329
}
330
331
static pdf_jsimp_obj *field_getValue(void *jsctx, void *obj)
332
{
333
pdf_js *js = (pdf_js *)jsctx;
334
pdf_obj *field = (pdf_obj *)obj;
335
char *fval;
336
337
if (!field)
338
return NULL;
339
340
fval = pdf_field_value(js->ctx, js->doc, field);
341
/* TODO: free fval! */
342
return pdf_jsimp_from_string(js->imp, fval?fval:"");
343
}
344
345
static void field_setValue(void *jsctx, void *obj, pdf_jsimp_obj *val)
346
{
347
pdf_js *js = (pdf_js *)jsctx;
348
pdf_obj *field = (pdf_obj *)obj;
349
350
if (field)
351
(void)pdf_field_set_value(js->ctx, js->doc, field, pdf_jsimp_to_string(js->imp, val));
352
}
353
354
static pdf_jsimp_obj *event_getTarget(void *jsctx, void *obj)
355
{
356
pdf_js *js = (pdf_js *)jsctx;
357
358
return pdf_jsimp_new_obj(js->imp, js->fieldtype, js->event.target);
359
}
360
361
static void event_setTarget(void *jsctx, void *obj, pdf_jsimp_obj *val)
362
{
363
pdf_js *js = (pdf_js *)jsctx;
364
fz_warn(js->ctx, "Unexpected call to event_setTarget");
365
}
366
367
static pdf_jsimp_obj *event_getValue(void *jsctx, void *obj)
368
{
369
pdf_js *js = (pdf_js *)jsctx;
370
char *v = js->event.value;
371
372
return pdf_jsimp_from_string(js->imp, v?v:"");
373
}
374
375
static void event_setValue(void *jsctx, void *obj, pdf_jsimp_obj *val)
376
{
377
pdf_js *js = (pdf_js *)jsctx;
378
fz_context *ctx = js->ctx;
379
fz_free(ctx, js->event.value);
380
js->event.value = NULL;
381
js->event.value = fz_strdup(ctx, pdf_jsimp_to_string(js->imp, val));
382
}
383
384
static pdf_jsimp_obj *event_getWillCommit(void *jsctx, void *obj)
385
{
386
pdf_js *js = (pdf_js *)jsctx;
387
388
return pdf_jsimp_from_number(js->imp, 1.0);
389
}
390
391
static void event_setWillCommit(void *jsctx, void *obj, pdf_jsimp_obj *val)
392
{
393
pdf_js *js = (pdf_js *)jsctx;
394
fz_warn(js->ctx, "Unexpected call to event_setWillCommit");
395
}
396
397
static pdf_jsimp_obj *event_getRC(void *jsctx, void *obj)
398
{
399
pdf_js *js = (pdf_js *)jsctx;
400
401
return pdf_jsimp_from_number(js->imp, (double)js->event.rc);
402
}
403
404
static void event_setRC(void *jsctx, void *obj, pdf_jsimp_obj *val)
405
{
406
pdf_js *js = (pdf_js *)jsctx;
407
408
js->event.rc = (int)pdf_jsimp_to_number(js->imp, val);
409
}
410
411
static pdf_jsimp_obj *doc_getEvent(void *jsctx, void *obj)
412
{
413
pdf_js *js = (pdf_js *)jsctx;
414
415
return pdf_jsimp_new_obj(js->imp, js->eventtype, &js->event);
416
}
417
418
static void doc_setEvent(void *jsctx, void *obj, pdf_jsimp_obj *val)
419
{
420
pdf_js *js = (pdf_js *)jsctx;
421
fz_warn(js->ctx, "Unexpected call to doc_setEvent");
422
}
423
424
static pdf_jsimp_obj *doc_getApp(void *jsctx, void *obj)
425
{
426
pdf_js *js = (pdf_js *)jsctx;
427
428
return pdf_jsimp_new_obj(js->imp, js->apptype, NULL);
429
}
430
431
static void doc_setApp(void *jsctx, void *obj, pdf_jsimp_obj *val)
432
{
433
pdf_js *js = (pdf_js *)jsctx;
434
fz_warn(js->ctx, "Unexpected call to doc_setApp");
435
}
436
437
static char *utf8_to_pdf(fz_context *ctx, char *utf8)
438
{
439
char *pdf = fz_malloc(ctx, strlen(utf8)+1);
440
int i = 0;
441
unsigned char c;
442
443
while ((c = *utf8) != 0)
444
{
445
if ((c & 0x80) == 0 && pdf_doc_encoding[c] == c)
446
{
447
pdf[i++] = c;
448
utf8++ ;
449
}
450
else
451
{
452
int rune;
453
int j;
454
455
utf8 += fz_chartorune(&rune, utf8);
456
457
for (j = 0; j < sizeof(pdf_doc_encoding) && pdf_doc_encoding[j] != rune; j++)
458
;
459
460
if (j < sizeof(pdf_doc_encoding))
461
pdf[i++] = j;
462
}
463
}
464
465
pdf[i] = 0;
466
467
return pdf;
468
}
469
470
static pdf_jsimp_obj *doc_getField(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
471
{
472
pdf_js *js = (pdf_js *)jsctx;
473
fz_context *ctx = js->ctx;
474
pdf_obj *dict = NULL;
475
char *utf8;
476
char *name = NULL;
477
478
if (argc != 1)
479
return NULL;
480
481
fz_var(dict);
482
fz_var(name);
483
fz_try(ctx)
484
{
485
utf8 = pdf_jsimp_to_string(js->imp, args[0]);
486
487
if (utf8)
488
{
489
name = utf8_to_pdf(ctx, utf8);
490
dict = pdf_lookup_field(js->ctx, js->form, name);
491
}
492
}
493
fz_always(ctx)
494
{
495
fz_free(ctx, name);
496
}
497
fz_catch(ctx)
498
{
499
fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
500
fz_warn(ctx, "doc_getField failed: %s", fz_caught_message(ctx));
501
dict = NULL;
502
}
503
504
return dict ? pdf_jsimp_new_obj(js->imp, js->fieldtype, dict) : NULL;
505
}
506
507
static void reset_field(pdf_js *js, pdf_jsimp_obj *item)
508
{
509
fz_context *ctx = js->ctx;
510
char *name = NULL;
511
char *utf8 = pdf_jsimp_to_string(js->imp, item);
512
513
if (utf8)
514
{
515
pdf_obj *field;
516
517
fz_var(name);
518
fz_try(ctx)
519
{
520
name = utf8_to_pdf(ctx, utf8);
521
field = pdf_lookup_field(js->ctx, js->form, name);
522
if (field)
523
pdf_field_reset(js->ctx, js->doc, field);
524
}
525
fz_always(ctx)
526
{
527
fz_free(ctx, name);
528
}
529
fz_catch(ctx)
530
{
531
fz_rethrow(ctx);
532
}
533
}
534
}
535
536
static pdf_jsimp_obj *doc_resetForm(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
537
{
538
pdf_js *js = (pdf_js *)jsctx;
539
fz_context *ctx = js->ctx;
540
pdf_jsimp_obj *arr = NULL;
541
pdf_jsimp_obj *elem = NULL;
542
543
switch (argc)
544
{
545
case 0:
546
break;
547
case 1:
548
switch (pdf_jsimp_to_type(js->imp, args[0]))
549
{
550
case JS_TYPE_NULL:
551
break;
552
case JS_TYPE_ARRAY:
553
arr = args[0];
554
break;
555
case JS_TYPE_STRING:
556
elem = args[0];
557
break;
558
default:
559
return NULL;
560
}
561
break;
562
default:
563
return NULL;
564
}
565
566
fz_try(ctx)
567
{
568
if(arr)
569
{
570
/* An array of fields has been passed in. Call
571
* pdf_reset_field on each */
572
int i, n = pdf_jsimp_array_len(js->imp, arr);
573
574
for (i = 0; i < n; i++)
575
{
576
pdf_jsimp_obj *item = pdf_jsimp_array_item(js->imp, arr, i);
577
578
if (item)
579
reset_field(js, item);
580
581
}
582
}
583
else if (elem)
584
{
585
reset_field(js, elem);
586
}
587
else
588
{
589
/* No argument or null passed in means reset all. */
590
int i, n = pdf_array_len(ctx, js->form);
591
592
for (i = 0; i < n; i++)
593
pdf_field_reset(js->ctx, js->doc, pdf_array_get(ctx, js->form, i));
594
}
595
}
596
fz_catch(ctx)
597
{
598
fz_warn(ctx, "doc_resetForm failed: %s", fz_caught_message(ctx));
599
}
600
601
return NULL;
602
}
603
604
static pdf_jsimp_obj *doc_print(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
605
{
606
pdf_js *js = (pdf_js *)jsctx;
607
608
pdf_event_issue_print(js->ctx, js->doc);
609
610
return NULL;
611
}
612
613
static pdf_jsimp_obj *doc_mailDoc(void *jsctx, void *obj, int argc, pdf_jsimp_obj *args[])
614
{
615
pdf_js *js = (pdf_js *)jsctx;
616
fz_context *ctx = js->ctx;
617
pdf_jsimp_obj *bUI_obj = NULL;
618
pdf_jsimp_obj *cTo_obj = NULL;
619
pdf_jsimp_obj *cCc_obj = NULL;
620
pdf_jsimp_obj *cBcc_obj = NULL;
621
pdf_jsimp_obj *cSubject_obj = NULL;
622
pdf_jsimp_obj *cMessage_obj = NULL;
623
pdf_mail_doc_event event;
624
int arg_is_obj = 0;
625
626
if (argc < 1 || argc > 6)
627
return NULL;
628
629
event.ask_user = 1;
630
event.to = "";
631
event.cc = "";
632
event.bcc = "";
633
event.subject = "";
634
event.message = "";
635
636
fz_var(bUI_obj);
637
fz_var(cTo_obj);
638
fz_var(cCc_obj);
639
fz_var(cBcc_obj);
640
fz_var(cSubject_obj);
641
fz_var(cMessage_obj);
642
fz_try(ctx)
643
{
644
arg_is_obj = (argc == 1 && pdf_jsimp_to_type(js->imp, args[0]) != JS_TYPE_BOOLEAN);
645
if (arg_is_obj)
646
{
647
bUI_obj = pdf_jsimp_property(js->imp, args[0], "bUI");
648
cTo_obj = pdf_jsimp_property(js->imp, args[0], "cTo");
649
cCc_obj = pdf_jsimp_property(js->imp, args[0], "cCc");
650
cBcc_obj = pdf_jsimp_property(js->imp, args[0], "cBcc");
651
cSubject_obj = pdf_jsimp_property(js->imp, args[0], "cSubject");
652
cMessage_obj = pdf_jsimp_property(js->imp, args[0], "cMessage");
653
}
654
else
655
{
656
switch (argc)
657
{
658
case 6:
659
cMessage_obj = args[5];
660
case 5:
661
cSubject_obj = args[4];
662
case 4:
663
cBcc_obj = args[3];
664
case 3:
665
cCc_obj = args[2];
666
case 2:
667
cTo_obj = args[1];
668
case 1:
669
bUI_obj = args[0];
670
}
671
}
672
673
if (bUI_obj)
674
event.ask_user = (int)pdf_jsimp_to_number(js->imp, bUI_obj);
675
676
if (cTo_obj)
677
event.to = pdf_jsimp_to_string(js->imp, cTo_obj);
678
679
if (cCc_obj)
680
event.cc = pdf_jsimp_to_string(js->imp, cCc_obj);
681
682
if (cBcc_obj)
683
event.bcc = pdf_jsimp_to_string(js->imp, cBcc_obj);
684
685
if (cSubject_obj)
686
event.subject = pdf_jsimp_to_string(js->imp, cSubject_obj);
687
688
if (cMessage_obj)
689
event.message = pdf_jsimp_to_string(js->imp, cMessage_obj);
690
691
pdf_event_issue_mail_doc(js->ctx, js->doc, &event);
692
}
693
fz_always(ctx)
694
{
695
if (arg_is_obj)
696
{
697
pdf_jsimp_drop_obj(js->imp, bUI_obj);
698
pdf_jsimp_drop_obj(js->imp, cTo_obj);
699
pdf_jsimp_drop_obj(js->imp, cCc_obj);
700
pdf_jsimp_drop_obj(js->imp, cBcc_obj);
701
pdf_jsimp_drop_obj(js->imp, cSubject_obj);
702
pdf_jsimp_drop_obj(js->imp, cMessage_obj);
703
}
704
}
705
fz_catch(ctx)
706
{
707
fz_rethrow(ctx);
708
}
709
710
return NULL;
711
}
712
713
static void declare_dom(pdf_js *js)
714
{
715
pdf_jsimp *imp = js->imp;
716
717
/* Create the document type */
718
js->doctype = pdf_jsimp_new_type(imp, NULL, "Document");
719
pdf_jsimp_addmethod(imp, js->doctype, "getField", doc_getField);
720
pdf_jsimp_addmethod(imp, js->doctype, "resetForm", doc_resetForm);
721
pdf_jsimp_addmethod(imp, js->doctype, "print", doc_print);
722
pdf_jsimp_addmethod(imp, js->doctype, "mailDoc", doc_mailDoc);
723
pdf_jsimp_addproperty(imp, js->doctype, "event", doc_getEvent, doc_setEvent);
724
pdf_jsimp_addproperty(imp, js->doctype, "app", doc_getApp, doc_setApp);
725
726
/* Create the event type */
727
js->eventtype = pdf_jsimp_new_type(imp, NULL, "Event");
728
pdf_jsimp_addproperty(imp, js->eventtype, "target", event_getTarget, event_setTarget);
729
pdf_jsimp_addproperty(imp, js->eventtype, "value", event_getValue, event_setValue);
730
pdf_jsimp_addproperty(imp, js->eventtype, "willCommit", event_getWillCommit, event_setWillCommit);
731
pdf_jsimp_addproperty(imp, js->eventtype, "rc", event_getRC, event_setRC);
732
733
/* Create the field type */
734
js->fieldtype = pdf_jsimp_new_type(imp, NULL, "Field");
735
pdf_jsimp_addproperty(imp, js->fieldtype, "value", field_getValue, field_setValue);
736
pdf_jsimp_addproperty(imp, js->fieldtype, "borderStyle", field_getBorderStyle, field_setBorderStyle);
737
pdf_jsimp_addproperty(imp, js->fieldtype, "textColor", field_getTextColor, field_setTextColor);
738
pdf_jsimp_addproperty(imp, js->fieldtype, "fillColor", field_getFillColor, field_setFillColor);
739
pdf_jsimp_addproperty(imp, js->fieldtype, "display", field_getDisplay, field_setDisplay);
740
pdf_jsimp_addproperty(imp, js->fieldtype, "name", field_getName, field_setName);
741
pdf_jsimp_addmethod(imp, js->fieldtype, "buttonSetCaption", field_buttonSetCaption);
742
743
/* Create the app type */
744
js->apptype = pdf_jsimp_new_type(imp, NULL, "Application");
745
pdf_jsimp_addmethod(imp, js->apptype, "alert", app_alert);
746
pdf_jsimp_addmethod(imp, js->apptype, "execDialog", app_execDialog);
747
pdf_jsimp_addmethod(imp, js->apptype, "execMenuItem", app_execMenuItem);
748
pdf_jsimp_addmethod(imp, js->apptype, "launchURL", app_launchURL);
749
750
/* Create the document object and tell the engine to use */
751
pdf_jsimp_set_global_type(js->imp, js->doctype);
752
}
753
754
static void preload_helpers(pdf_js *js)
755
{
756
/* When testing on the cluster:
757
* Use a fixed date for "new Date" and Date.now().
758
* Sadly, this breaks uses of the Date function without the new keyword.
759
* Return a fixed number from Math.random().
760
*/
761
#ifdef CLUSTER
762
pdf_jsimp_execute(js->imp,
763
"var MuPDFOldDate = Date\n"
764
"Date = function() { return new MuPDFOldDate(298252800000); }\n"
765
"Date.now = function() { return 298252800000; }\n"
766
"Date.UTC = function() { return 298252800000; }\n"
767
"Date.parse = MuPDFOldDate.parse;\n"
768
"Math.random = function() { return 1/4; }\n"
769
);
770
#endif
771
772
pdf_jsimp_execute(js->imp,
773
#include "gen_js_util.h"
774
);
775
}
776
777
static void pdf_drop_js(pdf_js *js)
778
{
779
if (js)
780
{
781
fz_context *ctx = js->ctx;
782
fz_free(ctx, js->event.value);
783
pdf_jsimp_drop_type(js->imp, js->apptype);
784
pdf_jsimp_drop_type(js->imp, js->eventtype);
785
pdf_jsimp_drop_type(js->imp, js->fieldtype);
786
pdf_jsimp_drop_type(js->imp, js->doctype);
787
pdf_drop_jsimp(js->imp);
788
fz_free(ctx, js);
789
}
790
}
791
792
static pdf_js *pdf_new_js(fz_context *ctx, pdf_document *doc)
793
{
794
pdf_js *js = NULL;
795
796
fz_var(js);
797
fz_try(ctx)
798
{
799
pdf_obj *root, *acroform;
800
801
js = fz_malloc_struct(ctx, pdf_js);
802
js->ctx = ctx;
803
js->doc = doc;
804
805
/* Find the form array */
806
root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root);
807
acroform = pdf_dict_get(ctx, root, PDF_NAME_AcroForm);
808
js->form = pdf_dict_get(ctx, acroform, PDF_NAME_Fields);
809
810
/* Initialise the javascript engine, passing the main context
811
* for use in memory allocation and exception handling. Also
812
* pass our js context, for it to pass back to us. */
813
js->imp = pdf_new_jsimp(ctx, js);
814
declare_dom(js);
815
816
preload_helpers(js);
817
}
818
fz_catch(ctx)
819
{
820
pdf_drop_js(js);
821
js = NULL;
822
}
823
824
return js;
825
}
826
827
static void pdf_js_load_document_level(pdf_js *js)
828
{
829
pdf_document *doc = js->doc;
830
fz_context *ctx = js->ctx;
831
pdf_obj *javascript = NULL;
832
char *codebuf = NULL;
833
834
fz_var(javascript);
835
fz_var(codebuf);
836
fz_try(ctx)
837
{
838
int len, i;
839
840
javascript = pdf_load_name_tree(ctx, doc, PDF_NAME_JavaScript);
841
len = pdf_dict_len(ctx, javascript);
842
843
for (i = 0; i < len; i++)
844
{
845
pdf_obj *fragment = pdf_dict_get_val(ctx, javascript, i);
846
pdf_obj *code = pdf_dict_get(ctx, fragment, PDF_NAME_JS);
847
848
fz_var(codebuf);
849
fz_try(ctx)
850
{
851
codebuf = pdf_to_utf8(ctx, doc, code);
852
pdf_jsimp_execute(js->imp, codebuf);
853
}
854
fz_always(ctx)
855
{
856
fz_free(ctx, codebuf);
857
codebuf = NULL;
858
}
859
fz_catch(ctx)
860
{
861
fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
862
fz_warn(ctx, "Warning: %s", fz_caught_message(ctx));
863
}
864
}
865
}
866
fz_always(ctx)
867
{
868
pdf_drop_obj(ctx, javascript);
869
}
870
fz_catch(ctx)
871
{
872
fz_rethrow(ctx);
873
}
874
}
875
876
void pdf_js_setup_event(pdf_js *js, pdf_js_event *e)
877
{
878
if (js)
879
{
880
fz_context *ctx = js->ctx;
881
char *ev = e->value ? e->value : "";
882
char *v = fz_strdup(ctx, ev);
883
884
fz_free(ctx, js->event.value);
885
js->event.value = v;
886
887
js->event.target = e->target;
888
js->event.rc = 1;
889
}
890
}
891
892
pdf_js_event *pdf_js_get_event(pdf_js *js)
893
{
894
return js ? &js->event : NULL;
895
}
896
897
void pdf_js_execute(pdf_js *js, char *code)
898
{
899
if (js)
900
{
901
fz_context *ctx = js->ctx;
902
fz_try(ctx)
903
{
904
pdf_jsimp_execute(js->imp, code);
905
}
906
fz_catch(ctx)
907
{
908
}
909
}
910
}
911
912
void pdf_js_execute_count(pdf_js *js, char *code, int count)
913
{
914
if (js)
915
{
916
fz_context *ctx = js->ctx;
917
fz_try(ctx)
918
{
919
pdf_jsimp_execute_count(js->imp, code, count);
920
}
921
fz_catch(ctx)
922
{
923
}
924
}
925
}
926
927
void pdf_enable_js(fz_context *ctx, pdf_document *doc)
928
{
929
if (!doc->js) {
930
doc->js = pdf_new_js(ctx, doc);
931
doc->drop_js = pdf_drop_js;
932
pdf_js_load_document_level(doc->js);
933
}
934
}
935
936
void pdf_disable_js(fz_context *ctx, pdf_document *doc)
937
{
938
if (doc->js)
939
doc->drop_js(doc->js);
940
doc->js = NULL;
941
}
942
943
int pdf_js_supported(fz_context *ctx, pdf_document *doc)
944
{
945
return doc->js != NULL;
946
}
947
948