/*---------------------------------------------------------------------------* | PDFlib - A library for generating PDF on the fly | +---------------------------------------------------------------------------+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. | +---------------------------------------------------------------------------+ | | | This software is subject to the PDFlib license. It is NOT in the | | public domain. Extended versions and commercial licenses are | | available, please check http://www.pdflib.com. | | | *---------------------------------------------------------------------------*/ /* $Id: p_actions.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ * * PDFlib actions handling routines * */ #define P_ACTIONS_C #include "p_intern.h" #include "p_layer.h" typedef enum { pdf_allact = -1, pdf_goto = (1<<0), pdf_gotor = (1<<1), pdf_launch = (1<<2), pdf_uri = (1<<3), pdf_hide = (1<<4), pdf_named = (1<<5), pdf_submitform = (1<<6), pdf_resetform = (1<<7), pdf_importdata = (1<<8), pdf_javascript = (1<<9), pdf_setocgstate = (1<<10), pdf_trans = (1<<11), pdf_goto3dview = (1<<12) } pdf_actiontype; static const pdc_keyconn pdf_action_pdfkeylist[] = { {"GoTo", pdf_goto}, {"GoToR", pdf_gotor}, {"Launch", pdf_launch}, {"URI", pdf_uri}, {"Hide", pdf_hide}, {"Named", pdf_named}, {"SubmitForm", pdf_submitform}, {"ResetForm", pdf_resetform}, {"ImportData", pdf_importdata}, {"JavaScript", pdf_javascript}, {"SetOCGState", pdf_setocgstate}, {"Trans", pdf_trans}, {"GoTo3DView", pdf_goto3dview}, {NULL, 0} }; typedef enum { /* values are identical with PDF values */ pdf_exp_fdf = (1<<1), pdf_exp_html = (1<<2), pdf_exp_getrequest = (1<<3), pdf_exp_coordinates = (1<<4), pdf_exp_xfdf = (1<<5), pdf_exp_updates = (1<<6), pdf_exp_annotfields = (1<<7), pdf_exp_pdf = (1<<8), pdf_exp_onlyuser = (1<<10), pdf_exp_exclurl = (1<<11) } pdf_exportmethod; /* allowed combinations of exportmethod keywords */ static pdf_exportmethod pdf_allfdf = (pdf_exportmethod) (pdf_exp_fdf | pdf_exp_updates | pdf_exp_exclurl | pdf_exp_annotfields | pdf_exp_onlyuser); static pdf_exportmethod pdf_allhtml = (pdf_exportmethod) (pdf_exp_html | pdf_exp_getrequest | pdf_exp_coordinates); static pdf_exportmethod pdf_allxfdf = pdf_exp_xfdf; static pdf_exportmethod pdf_allpdf = (pdf_exportmethod) (pdf_exp_pdf | pdf_exp_getrequest); static const pdc_keyconn pdf_exportmethod_keylist[] = { {"fdf", pdf_exp_fdf}, {"html", pdf_exp_html}, {"xfdf", pdf_exp_xfdf}, {"pdf", pdf_exp_pdf}, {"getrequest", pdf_exp_getrequest}, {"coordinates", pdf_exp_coordinates}, {"updates", pdf_exp_updates}, {"annotfields", pdf_exp_annotfields}, {"onlyuser", pdf_exp_onlyuser}, {"exclurl", pdf_exp_exclurl}, {NULL, 0} }; static const pdc_keyconn pdf_filename_keylist[] = { {"filename", (pdf_actiontype) (pdf_gotor | pdf_launch | pdf_importdata)}, {"url", (pdf_actiontype) (pdf_uri | pdf_submitform)}, {NULL, 0} }; static const pdc_keyconn pdf_operation_pdfkeylist[] = { {"open", 1}, {"print", 2}, {NULL, 0} }; static const pdc_keyconn pdf_3dview_keylist[] = { {NULL, 0} }; #define PDF_LAYER_FLAG PDC_OPT_UNSUPP #define PDF_JAVASCRIPT_FLAG PDC_OPT_UNSUPP #define PDF_3DVIEW_FLAG PDC_OPT_UNSUPP static const pdc_defopt pdf_create_action_options[] = { /* deprecated */ {"actionwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDF_MAX_NAMESTRING, NULL}, {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_FILENAMELEN, NULL}, {"url", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"parameters", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"operation", pdc_keywordlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, pdf_operation_pdfkeylist}, {"defaultdir", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"menuname", pdc_stringlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"script", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"scriptname", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"namelist", pdc_stringlist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE, 0.0, PDC_USHRT_MAX, NULL}, {"exportmethod", pdc_keywordlist, PDC_OPT_BUILDOR, 1, 10, 0.0, 0.0, pdf_exportmethod_keylist}, {"newwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"ismap", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"hide", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"exclude", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"submitemptyfields", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL}, {"canonicaldate", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, {"layerstate", pdc_stringlist, PDF_LAYER_FLAG | PDC_OPT_EVENNUM, 1, 100, 1.0, 8.0, NULL}, {"preserveradio", pdc_booleanlist, PDF_LAYER_FLAG, 1, 1, 0.0, 0.0, NULL}, {"3dview", pdc_3dviewhandle, PDF_3DVIEW_FLAG, 1, 1, 0.0, 0.0, pdf_3dview_keylist}, {"target", pdc_stringlist, PDF_3DVIEW_FLAG, 1, 1, 0.0, PDC_USHRT_MAX, NULL}, {"transition", pdc_keywordlist, PDC_OPT_PDC_1_5, 1, 1, 0.0, 0.0, pdf_transition_keylist}, {"duration", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1, 0.0, PDC_FLOAT_MAX, NULL}, PDF_ERRORPOLICY_OPTION PDC_OPT_TERMINATE }; typedef struct pdf_action_s { pdc_id obj_id; pdf_actiontype atype; pdf_dest *dest; pdc_encoding hypertextencoding; char *filename; char *parameters; char *operation; char *defaultdir; char *menuname; char *script; char *scriptname; char **namelist; int nsnames; pdc_bool newwindow; pdc_bool ismap; pdc_bool hide; pdc_bool exclude; pdc_bool submitemptyfields; pdc_bool canonicaldate; pdf_exportmethod exportmethod; int transition; double duration; } pdf_action; static void pdf_reclaim_action(void *item) { pdf_action *action = (pdf_action *) item; action->obj_id = PDC_BAD_ID; action->atype = (pdf_actiontype) 0; action->dest = NULL; action->hypertextencoding = pdc_invalidenc; action->filename = NULL; action->parameters = NULL; action->operation = NULL; action->defaultdir = NULL; action->menuname = NULL; action->script = NULL; action->scriptname = NULL; action->namelist = NULL; action->nsnames = 0; action->newwindow = pdc_undef; action->ismap = pdc_false; action->hide = pdc_true; action->exclude = pdc_false; action->submitemptyfields = pdc_false; action->canonicaldate = pdc_false; action->exportmethod = pdf_exp_fdf; action->transition = (int) trans_replace; action->duration = 1; } static void pdf_release_action(void *context, void *item) { PDF *p = (PDF *) context; pdf_action *action = (pdf_action *) item; pdf_cleanup_destination(p, action->dest); if (action->filename) { pdc_free(p->pdc, action->filename); action->filename = NULL; } if (action->parameters) { pdc_free(p->pdc, action->parameters); action->parameters = NULL; } if (action->defaultdir) { pdc_free(p->pdc, action->defaultdir); action->defaultdir = NULL; } if (action->menuname) { pdc_free(p->pdc, action->menuname); action->menuname = NULL; } if (action->script) { pdc_free(p->pdc, action->script); action->script = NULL; } if (action->namelist) { pdc_cleanup_optstringlist(p->pdc, action->namelist, action->nsnames); action->namelist = NULL; } } static pdc_ced pdf_action_ced = { sizeof(pdf_action), pdf_reclaim_action, pdf_release_action, NULL }; static pdc_vtr_parms pdf_action_parms = { 0, 10, 10 }; static pdf_action * pdf_new_action(PDF *p) { pdf_action *result; if (p->actions == NULL) p->actions = pdc_vtr_new(p->pdc, &pdf_action_ced, p, &pdf_action_parms); result = pdc_vtr_incr(p->actions, pdf_action); result->hypertextencoding = p->hypertextencoding; return result; } void pdf_delete_actions(PDF *p) { if (p->actions != NULL) { pdc_vtr_delete(p->actions); p->actions = NULL; } } int pdf_get_max_action(PDF *p) { return (p->actions == NULL) ? -1 : pdc_vtr_size(p->actions) - 1; } static pdc_id pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id); static int pdf_opt_effectless(PDF *p, const char *keyword, pdf_actiontype curratype, pdf_actiontype intendatypes) { if ((pdf_actiontype) !(intendatypes & curratype)) { const char *type = pdc_get_keyword(curratype, pdf_action_pdfkeylist); pdc_warning(p->pdc, PDF_E_ACT_OPTIGNORE_FORTYPE, keyword,type, 0, 0); return 1; } return 0; } int pdf__create_action(PDF *p, const char *type, const char *optlist) { pdc_resopt *resopts = NULL; pdc_clientdata data; pdf_action *action; pdf_actiontype atype; pdf_dest *dest = NULL; pdc_bool verbose = pdc_true; pdc_bool hasdest = pdc_false; pdc_encoding htenc; int htcp; const char *keyword; char **strlist; int i, k, ns; if (type == NULL || *type == '\0') pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); k = pdc_get_keycode_ci(type, pdf_action_pdfkeylist); if (k == PDC_KEY_NOTFOUND) pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0); atype = (pdf_actiontype) k; if (atype == pdf_javascript) pdc_error(p->pdc, PDF_E_UNSUPP_JAVASCRIPT, 0, 0, 0, 0); /* compatibility */ if (p->compatibility < PDC_1_6 && atype == pdf_goto3dview) { pdc_error(p->pdc, PDC_E_PAR_VERSION, type, pdc_get_pdfversion(p->pdc, PDC_1_6), 0, 0); } if (p->compatibility < PDC_1_5 && (atype == pdf_setocgstate || atype == pdf_trans)) { pdc_error(p->pdc, PDC_E_PAR_VERSION, type, pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0); } /* new action */ action = pdf_new_action(p); action->atype = atype; /* Parsing option list */ pdf_set_clientdata(p, &data); resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_action_options, &data, pdc_true); keyword = "actionwarning"; pdc_get_optvalues(keyword, resopts, &verbose, NULL); verbose = pdf_get_errorpolicy(p, resopts, verbose); htenc = pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true); keyword = "destination"; if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) { if (!pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) (pdf_goto | pdf_gotor))) { action->dest = pdf_parse_destination_optlist(p, strlist[0], (atype == pdf_goto) ? 0 : 1, (atype == pdf_goto) ? pdf_locallink : pdf_remotelink); hasdest = pdc_true; } } else { keyword = "destname"; if (atype == pdf_goto || atype == pdf_gotor) dest = pdf_get_option_destname(p, resopts, htenc, htcp); else if (pdc_get_optvalues(keyword, resopts, NULL, NULL)) pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) (pdf_goto | pdf_gotor)); if (dest) { action->dest = dest; hasdest = pdc_true; } } /* filename or url */ for (i = 0; ; i++) { keyword = pdf_filename_keylist[i].word; if (keyword) { if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) { if (!pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) pdf_filename_keylist[i].code)) { action->filename = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); } } } else break; } keyword = "parameters"; if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && !pdf_opt_effectless(p, keyword, atype, pdf_launch)) action->parameters = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); keyword = "operation"; if (pdc_get_optvalues(keyword, resopts, &k, NULL) && !pdf_opt_effectless(p, keyword, atype, pdf_launch)) action->operation = (char *) pdc_get_keyword(k, pdf_operation_pdfkeylist); keyword = "defaultdir"; if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && !pdf_opt_effectless(p, keyword, atype, pdf_launch)) action->defaultdir = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); keyword = "menuname"; if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && !pdf_opt_effectless(p, keyword, atype, pdf_named)) { action->menuname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); } keyword = "namelist"; ns = pdc_get_optvalues(keyword, resopts, NULL, NULL); if (ns && !pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) (pdf_hide | pdf_submitform | pdf_resetform))) { action->namelist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL); action->nsnames = ns; } keyword = "exportmethod"; if (pdc_get_optvalues(keyword, resopts, &k, NULL)) { action->exportmethod = (pdf_exportmethod) k; if (!pdf_opt_effectless(p, keyword, atype, pdf_submitform)) { if ((action->exportmethod & pdf_exp_fdf && (action->exportmethod | pdf_allfdf) != pdf_allfdf) || (action->exportmethod & pdf_exp_html && (action->exportmethod | pdf_allhtml) != pdf_allhtml) || (action->exportmethod & pdf_exp_xfdf && (action->exportmethod | pdf_allxfdf) != pdf_allxfdf) || (action->exportmethod & pdf_exp_pdf && (action->exportmethod | pdf_allpdf) != pdf_allpdf)) { pdc_error(p->pdc, PDC_E_OPT_ILLCOMB, keyword, 0, 0, 0); } if (action->exportmethod & pdf_exp_fdf) action->exportmethod = (pdf_exportmethod) (action->exportmethod & ~pdf_exp_fdf); } } keyword = "newwindow"; if (pdc_get_optvalues(keyword, resopts, &action->newwindow, NULL)) pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) (pdf_gotor | pdf_launch)); keyword = "ismap"; if (pdc_get_optvalues(keyword, resopts, &action->ismap, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_uri); keyword = "hide"; if (pdc_get_optvalues(keyword, resopts, &action->hide, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_hide); keyword = "exclude"; if (pdc_get_optvalues(keyword, resopts, &action->exclude, NULL)) pdf_opt_effectless(p, keyword, atype, (pdf_actiontype) (pdf_submitform | pdf_resetform)); keyword = "submitemptyfields"; if (pdc_get_optvalues(keyword, resopts, &action->submitemptyfields, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_submitform); keyword = "canonicaldate"; if (pdc_get_optvalues(keyword, resopts, &action->canonicaldate, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_submitform); keyword = "transition"; if (pdc_get_optvalues(keyword, resopts, &action->transition, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_trans); keyword = "duration"; if (pdc_get_optvalues(keyword, resopts, &action->duration, NULL)) pdf_opt_effectless(p, keyword, atype, pdf_trans); /* required options */ keyword = NULL; if (!hasdest && (atype == pdf_goto || atype == pdf_gotor)) keyword = "destination"; if (!action->filename && (atype == pdf_gotor || atype == pdf_launch || atype == pdf_importdata)) keyword = "filename"; if (!action->menuname && atype == pdf_named) keyword = "menuname"; if (!action->namelist && atype == pdf_hide) keyword = "namelist"; if (!action->filename && (atype == pdf_uri || atype == pdf_submitform)) keyword = "url"; if (keyword) pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0); return pdf_get_max_action(p); } static pdc_id pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id) { pdc_id ret_id = PDC_BAD_ID; int i, flags = 0; ret_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Action object */ pdc_begin_dict(p->out); /* Action dict */ pdc_puts(p->out, "/Type/Action\n"); pdc_printf(p->out, "/S/%s\n", pdc_get_keyword(action->atype, pdf_action_pdfkeylist)); /* next action */ if (next_id != PDC_BAD_ID) pdc_objref(p->out, "/Next", next_id); else action->obj_id = ret_id; /* destination */ switch (action->atype) { case pdf_goto: case pdf_gotor: pdc_puts(p->out, "/D"); pdf_write_destination(p, action->dest); default: break; } /* file specification */ switch (action->atype) { case pdf_gotor: case pdf_launch: if (action->newwindow != pdc_undef) pdc_printf(p->out, "/NewWindow %s\n", PDC_BOOLSTR(action->newwindow)); case pdf_importdata: if (action->parameters || action->operation || action->defaultdir) { /* Windows-specific launch parameters */ pdc_puts(p->out, "/Win"); pdc_begin_dict(p->out); /* Win dict */ pdc_printf(p->out, "/F"); pdf_put_hypertext(p, action->filename); pdc_puts(p->out, "\n"); if (action->parameters) { pdc_printf(p->out, "/P"); pdf_put_hypertext(p, action->parameters); pdc_puts(p->out, "\n"); pdc_free(p->pdc, action->parameters); action->parameters = NULL; } if (action->operation) { pdc_printf(p->out, "/O"); pdf_put_hypertext(p, action->operation); pdc_puts(p->out, "\n"); action->operation = NULL; } if (action->defaultdir) { pdc_printf(p->out, "/D"); pdf_put_hypertext(p, action->defaultdir); pdc_puts(p->out, "\n"); pdc_free(p->pdc, action->defaultdir); action->defaultdir = NULL; } pdc_end_dict(p->out); /* Win dict */ } else { pdc_puts(p->out, "/F"); pdc_begin_dict(p->out); /* F dict */ pdc_puts(p->out, "/Type/Filespec\n"); pdc_printf(p->out, "/F"); pdf_put_pdffilename(p, action->filename); pdc_puts(p->out, "\n"); pdc_end_dict(p->out); /* F dict */ } default: break; } /* URI */ switch (action->atype) { case pdf_uri: pdc_puts(p->out, "/URI"); pdf_put_hypertext(p, action->filename); pdc_puts(p->out, "\n"); /* IsMap */ if (action->ismap == pdc_true) pdc_puts(p->out, "/IsMap true\n"); default: break; } /* Named */ switch (action->atype) { case pdf_named: pdc_printf(p->out, "/N"); pdf_put_pdfname(p, action->menuname); pdc_puts(p->out, "\n"); default: break; } /* name list */ switch (action->atype) { case pdf_hide: if (action->hide == pdc_false) pdc_puts(p->out, "/H false\n"); case pdf_submitform: case pdf_resetform: if (action->nsnames) { pdc_printf(p->out, "/%s", (action->atype == pdf_hide) ? "T" : "Fields"); pdc_begin_array(p->out); for (i = 0; i < action->nsnames; i++) { pdf_put_hypertext(p, action->namelist[i]); if (i < action->nsnames - 1) pdc_puts(p->out, "\n"); else pdc_end_array(p->out); } } default: break; } /* URL */ switch (action->atype) { case pdf_submitform: pdc_puts(p->out, "/F"); pdc_begin_dict(p->out); /* F dict */ pdc_puts(p->out, "/FS/URL\n"); pdc_printf(p->out, "/F"); pdf_put_hypertext(p, action->filename); pdc_puts(p->out, "\n"); pdc_end_dict(p->out); /* F dict */ default: break; } /* Trans */ switch (action->atype) { case pdf_trans: pdc_puts(p->out, "/Trans"); pdc_begin_dict(p->out); /* Trans dict */ pdc_puts(p->out, "/Type/Trans\n"); if (action->transition != trans_replace) pdc_printf(p->out, "/S/%s", pdc_get_keyword(action->transition, pdf_transition_pdfkeylist)); if (action->duration > 0) pdc_printf(p->out, "/D %f\n", action->duration); pdc_end_dict(p->out); /* Trans dict */ default: break; } /* Flags */ switch (action->atype) { case pdf_submitform: flags = (int) action->exportmethod; if (action->submitemptyfields) flags |= (1<<1); if (action->canonicaldate) flags |= (1<<9); case pdf_resetform: if (action->exclude) flags |= (1<<0); if (flags) pdc_printf(p->out, "/Flags %d\n", flags); default: break; } pdc_end_dict(p->out); /* Action dict */ pdc_end_obj(p->out); /* Action object */ return ret_id; } /* ---- Annotations events ---- */ static const pdc_keyconn pdf_annotevent_keylist[] = { {"activate", 0}, {"enter", 1}, {"exit", 2}, {"down", 3}, {"up", 4}, {"focus", 5}, {"blur", 6}, {NULL, 0} }; static const pdc_keyconn pdf_annotevent_pdfkeylist[] = { {"A", 0}, {"E", 1}, {"X", 2}, {"D", 3}, {"U", 4}, {"Fo", 5}, {"Bl", 6}, {NULL, 0} }; static int pdf_annotevent_beginjava = 99; static const pdc_defopt pdf_annotevent_options[] = { {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"enter", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"exit", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"down", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"up", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"focus", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"blur", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, PDC_OPT_TERMINATE }; /* ---- Bookmark events ---- */ static const pdc_keyconn pdf_bookmarkevent_keylist[] = { {"activate", 0}, {NULL, 0} }; static const pdc_keyconn pdf_bookmarkevent_pdfkeylist[] = { {"A", 0}, {NULL, 0} }; static int pdf_bookmarkevent_beginjava = 99; static const pdc_defopt pdf_bookmarkevent_options[] = { {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, PDC_OPT_TERMINATE }; /* ---- Document events ---- */ static const pdc_keyconn pdf_documentevent_keylist[] = { {"open", 0}, {"didprint", 1}, {"didsave", 2}, {"willclose", 3}, {"willprint", 4}, {"willsave", 5}, {NULL, 0} }; static const pdc_keyconn pdf_documentevent_pdfkeylist[] = { {"OpenAction", 0}, {"DP", 1}, {"DS", 2}, {"WC", 3}, {"WP", 4}, {"WS", 5}, {NULL, 0} }; static int pdf_documentevent_beginjava = 1; static const pdc_defopt pdf_documentevent_options[] = { {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"didprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"didsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"willclose", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"willprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"willsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, PDC_OPT_TERMINATE }; /* ---- Page events ---- */ static const pdc_keyconn pdf_pageevent_keylist[] = { {"", 0}, {"open", 1}, {"close", 2}, {NULL, 0} }; static const pdc_keyconn pdf_pageevent_pdfkeylist[] = { {"", 0}, {"O", 1}, {"C", 2}, {NULL, 0} }; static int pdf_pageevent_beginjava = 99; static const pdc_defopt pdf_pageevent_options[] = { {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, {"close", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, 0.0, 0.0, NULL}, PDC_OPT_TERMINATE }; pdc_bool pdf_parse_and_write_actionlist(PDF *p, pdf_event_object eventobj, pdc_id *act_idlist, const char *optlist) { const pdc_defopt *defopttable = NULL; const pdc_keyconn *keyconntable = NULL; pdc_resopt *resopts = NULL; pdc_clientdata data; pdc_id ret_id = PDC_BAD_ID; pdf_action *action = NULL; pdc_bool calcevent = pdc_false; const char *keyword, *type; char **strlist; int *actlist; int i, code, nsact, beginjava = 0; switch(eventobj) { case event_annotation: defopttable = pdf_annotevent_options; keyconntable = pdf_annotevent_keylist; beginjava = pdf_annotevent_beginjava; break; case event_bookmark: defopttable = pdf_bookmarkevent_options; keyconntable = pdf_bookmarkevent_keylist; beginjava = pdf_bookmarkevent_beginjava; break; case event_document: defopttable = pdf_documentevent_options; keyconntable = pdf_documentevent_keylist; beginjava = pdf_documentevent_beginjava; break; case event_page: defopttable = pdf_pageevent_options; keyconntable = pdf_pageevent_keylist; beginjava = pdf_pageevent_beginjava; break; default: break; } /* parsing option list */ pdf_set_clientdata(p, &data); resopts = pdc_parse_optionlist(p->pdc, optlist, defopttable, &data, pdc_true); /* write actions and saving action ids */ for (code = 0; ; code++) { keyword = pdc_get_keyword(code, keyconntable); if (keyword) { nsact = pdc_get_optvalues(keyword, resopts, NULL, &strlist); actlist = (int *) strlist; /* Not activate event */ if (code && nsact) { /* additional action type check */ for (i = 0; i < nsact; i++) { action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[i], pdf_action); if (code >= beginjava && action->atype != pdf_javascript) { type = pdc_get_keyword(action->atype, pdf_action_pdfkeylist); pdc_error(p->pdc, PDF_E_ACT_BADACTTYPE, type, keyword, 0, 0); } } /* saving calculation event */ if (!strcmp(keyword, "calculate")) calcevent = pdc_true; } /* write action objects */ if (act_idlist != NULL) { if (nsact == 1) { action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[0], pdf_action); if (action->obj_id == PDC_BAD_ID) ret_id = pdf_write_action(p, action, PDC_BAD_ID); else ret_id = action->obj_id; } else if (nsact > 1) { for (i = nsact-1; i >= 0; i--) { action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[i], pdf_action); ret_id = pdf_write_action(p, action, ret_id); } } else ret_id = PDC_BAD_ID; act_idlist[code] = ret_id; } } else break; } return calcevent; } pdc_bool pdf_write_action_entries(PDF *p, pdf_event_object eventobj, pdc_id *act_idlist) { const pdc_keyconn *keyconntable = NULL; const char *keyword; pdc_id act_id = PDC_BAD_ID; pdc_bool adict = pdc_false; pdc_bool aadict = pdc_false; int code; switch(eventobj) { case event_annotation: keyconntable = pdf_annotevent_pdfkeylist; break; case event_bookmark: keyconntable = pdf_bookmarkevent_pdfkeylist; break; case event_document: keyconntable = pdf_documentevent_pdfkeylist; break; case event_page: keyconntable = pdf_pageevent_pdfkeylist; break; default: break; } for (code = 0; ; code++) { keyword = pdc_get_keyword(code, keyconntable); if (keyword) { act_id = act_idlist[code]; if (act_id != PDC_BAD_ID) { if (code && !aadict) { pdc_puts(p->out, "/AA"); pdc_begin_dict(p->out); /* AA dict */ aadict = pdc_true; } else if (!code) adict = pdc_true; pdc_printf(p->out, "/%s", keyword); pdc_objref_c(p->out, act_id); } } else break; } if (aadict) pdc_end_dict(p->out); /* AA dict */ else if (adict) pdc_puts(p->out, "\n"); return adict; }