1 //========================================================================
2 //
3 // Form.cc
4 //
5 // This file is licensed under the GPLv2 or later
6 //
7 // Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
8 // Copyright 2007-2010 Albert Astals Cid <aacid@kde.org>
9 // Copyright 2007-2008 Carlos Garcia Campos <carlosgc@gnome.org>
10 // Copyright 2007 Adrian Johnson <ajohnson@redneon.com>
11 // Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
12 // Copyright 2008 Pino Toscano <pino@kde.org>
13 // Copyright 2008 Michael Vrable <mvrable@cs.ucsd.edu>
14 // Copyright 2009 Matthias Drochner <M.Drochner@fz-juelich.de>
15 // Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
16 // Copyright 2010 Mark Riedesel <mark@klowner.com>
17 //
18 //========================================================================
19
20 #include <config.h>
21
22 #ifdef USE_GCC_PRAGMAS
23 #pragma implementation
24 #endif
25
26 #include <set>
27 #include <stddef.h>
28 #include <string.h>
29 #include "goo/gmem.h"
30 #include "goo/GooString.h"
31 #include "Error.h"
32 #include "Object.h"
33 #include "Array.h"
34 #include "Dict.h"
35 #include "Form.h"
36 #include "XRef.h"
37 #include "PDFDocEncoding.h"
38 #include "Annot.h"
39 #include "Catalog.h"
40
41 //return a newly allocated char* containing an UTF16BE string of size length
pdfDocEncodingToUTF16(GooString * orig,int * length)42 char* pdfDocEncodingToUTF16 (GooString* orig, int* length)
43 {
44 //double size, a unicode char takes 2 char, add 2 for the unicode marker
45 *length = 2+2*orig->getLength();
46 char *result = new char[(*length)];
47 char *cstring = orig->getCString();
48 //unicode marker
49 result[0] = 0xfe;
50 result[1] = 0xff;
51 //convert to utf16
52 for(int i=2,j=0; i<(*length); i+=2,j++) {
53 Unicode u = pdfDocEncoding[(unsigned int)((unsigned char)cstring[j])]&0xffff;
54 result[i] = (u >> 8) & 0xff;
55 result[i+1] = u & 0xff;
56 }
57 return result;
58 }
59
60
61
FormWidget(XRef * xrefA,Object * aobj,unsigned num,Ref aref,FormField * fieldA)62 FormWidget::FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA)
63 {
64 Object obj1, obj2;
65 ref = aref;
66 double t;
67 ID = 0;
68 defaultsLoaded = gFalse;
69 fontSize = 0.0;
70 modified = gFalse;
71 childNum = num;
72 xref = xrefA;
73 aobj->copy(&obj);
74 type = formUndef;
75 field = fieldA;
76 Dict *dict = obj.getDict();
77 fullyQualifiedName = NULL;
78
79 if (dict->lookup("T", &obj1)->isString()) {
80 partialName = obj1.getString()->copy();
81 } else {
82 partialName = NULL;
83 }
84 obj1.free();
85
86 if(dict->lookup("TM", &obj1)->isString()) {
87 mappingName = obj1.getString()->copy();
88 } else {
89 mappingName = NULL;
90 }
91 obj1.free();
92
93 if (!dict->lookup("Rect", &obj1)->isArray()) {
94 error(-1, "Annotation rectangle is wrong type");
95 goto err2;
96 }
97 if (!obj1.arrayGet(0, &obj2)->isNum()) {
98 error(-1, "Bad annotation rectangle");
99 goto err1;
100 }
101 x1 = obj2.getNum();
102 obj2.free();
103 if (!obj1.arrayGet(1, &obj2)->isNum()) {
104 error(-1, "Bad annotation rectangle");
105 goto err1;
106 }
107 y1 = obj2.getNum();
108 obj2.free();
109 if (!obj1.arrayGet(2, &obj2)->isNum()) {
110 error(-1, "Bad annotation rectangle");
111 goto err1;
112 }
113 x2 = obj2.getNum();
114 obj2.free();
115 if (!obj1.arrayGet(3, &obj2)->isNum()) {
116 error(-1, "Bad annotation rectangle");
117 goto err1;
118 }
119 y2 = obj2.getNum();
120 obj2.free();
121 obj1.free();
122 //swap coords if needed
123 if (x1 > x2) {
124 t = x1;
125 x1 = x2;
126 x2 = t;
127 }
128 if (y1 > y2) {
129 t = y1;
130 y1 = y2;
131 y2 = t;
132 }
133
134 err1:
135 obj2.free();
136 err2:
137 obj1.free();
138 }
139
~FormWidget()140 FormWidget::~FormWidget()
141 {
142 delete partialName;
143 delete mappingName;
144 delete fullyQualifiedName;
145 obj.free ();
146 }
147
isReadOnly() const148 bool FormWidget::isReadOnly() const
149 {
150 return field->isReadOnly();
151 }
152
encodeID(unsigned pageNum,unsigned fieldNum)153 int FormWidget::encodeID (unsigned pageNum, unsigned fieldNum)
154 {
155 return (pageNum << 4*sizeof(unsigned)) + fieldNum;
156 }
157
decodeID(unsigned id,unsigned * pageNum,unsigned * fieldNum)158 void FormWidget::decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum)
159 {
160 *pageNum = id >> 4*sizeof(unsigned);
161 *fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
162 }
163
updateField(const char * key,Object * value)164 void FormWidget::updateField (const char *key, Object *value)
165 {
166 Object *obj1;
167 Ref ref1;
168 Object obj2;
169
170 if (obj.getDict()->lookup ("FT", &obj2)->isName ()) {
171 // It's a composed (annot + field) dict
172 obj1 = &obj;
173 ref1 = ref;
174 } else {
175 // It's an annot dict, we have to modify the Field (parent) dict
176 obj1 = field->getObj ();
177 ref1 = field->getRef ();
178 }
179 obj2.free ();
180
181 obj1->getDict ()->set (const_cast<char*>(key), value);
182 //notify the xref about the update
183 xref->setModifiedObject(obj1, ref1);
184 }
185
getFullyQualifiedName()186 GooString* FormWidget::getFullyQualifiedName() {
187 Object obj1, obj2;
188 Object parent;
189 GooString *parent_name;
190 GooString *full_name;
191
192 if (fullyQualifiedName)
193 return fullyQualifiedName;
194
195 full_name = new GooString();
196
197 obj.copy(&obj1);
198 while (obj1.dictLookup("Parent", &parent)->isDict()) {
199 if (parent.dictLookup("T", &obj2)->isString()) {
200 parent_name = obj2.getString();
201
202 if (parent_name->hasUnicodeMarker()) {
203 parent_name->del(0, 2); // Remove the unicode BOM
204 full_name->insert(0, "\0.", 2); // 2-byte unicode period
205 } else {
206 full_name->insert(0, '.'); // 1-byte ascii period
207 }
208
209 full_name->insert(0, parent_name);
210 obj2.free();
211 }
212 obj1.free();
213 parent.copy(&obj1);
214 parent.free();
215 }
216 obj1.free();
217 parent.free();
218
219 if (partialName) {
220 full_name->append(partialName);
221 } else {
222 int len = full_name->getLength();
223 // Remove the last period
224 if (len > 0)
225 full_name->del(len - 1, 1);
226 }
227
228 fullyQualifiedName = full_name;
229 return fullyQualifiedName;
230 }
231
FormWidgetButton(XRef * xrefA,Object * aobj,unsigned num,Ref ref,FormField * p)232 FormWidgetButton::FormWidgetButton (XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
233 FormWidget(xrefA, aobj, num, ref, p)
234 {
235 type = formButton;
236 parent = static_cast<FormFieldButton*>(field);
237 onStr = NULL;
238 state = gFalse;
239 siblingsID = NULL;
240 numSiblingsID = 0;
241 }
242
~FormWidgetButton()243 FormWidgetButton::~FormWidgetButton ()
244 {
245 if (siblingsID)
246 gfree(siblingsID);
247 delete onStr;
248 }
249
getButtonType() const250 FormButtonType FormWidgetButton::getButtonType () const
251 {
252 return parent->getButtonType ();
253 }
254
setState(GBool astate,GBool calledByParent)255 void FormWidgetButton::setState (GBool astate, GBool calledByParent)
256 {
257 //pushButtons don't have state
258 if (parent->getButtonType() == formButtonPush)
259 return;
260 //the state modification may be denied by the parent. e.g we don't want to let the user put all combo boxes to false
261 if (!calledByParent) { //avoid infinite recursion
262 modified = gTrue;
263 if (!parent->setState(childNum, astate)) {
264 return;
265 }
266 }
267 state = astate;
268
269 //update appearance
270 char *offStr = "Off";
271 Object obj1;
272 obj1.initName(state?getOnStr():offStr);
273 updateField ("V", &obj1);
274
275 obj1.initName(state?getOnStr():offStr);
276 //modify the Appearance State entry as well
277 obj.getDict()->set("AS", &obj1);
278 //notify the xref about the update
279 xref->setModifiedObject(&obj, ref);
280 }
281
loadDefaults()282 void FormWidgetButton::loadDefaults ()
283 {
284 if (defaultsLoaded)
285 return;
286
287 defaultsLoaded = gTrue;
288
289 Dict *dict = obj.getDict();
290 Object obj1;
291
292 //pushButtons don't have state
293 if (parent->getButtonType() != formButtonPush ){
294 //find the name of the state in the AP dictionnary (/Yes, /Off)
295 //The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
296 //The "on" state may be stored under any other name
297 if (dict->lookup("AP", &obj1)->isDict()) {
298 Dict *tmpDict = obj1.getDict();
299 int length = tmpDict->getLength();
300 for(int i=0; i<length; i++) {
301 Object obj2;
302 tmpDict->getVal(i, &obj2);
303 if (obj2.isDict()) {
304 Dict *tmpDict2 = obj2.getDict();
305 int length2 = tmpDict2->getLength();
306 for(int j=0; j<length2; j++) {
307 Object obj3;
308 tmpDict2->getVal(j, &obj3);
309 char *key = tmpDict2->getKey(j);
310 if(strcmp(key, "Off")) { //if we don't have Off, we have the name of the "on" state
311 onStr = new GooString (key);
312 }
313 obj3.free();
314 if (onStr)
315 break;
316 }
317 } else if (obj2.isStream()) {
318 // TODO do something with str and obj3
319 Stream *str = obj2.getStream();
320 Dict *tmpDict2 = str->getDict();
321 Object obj3;
322 tmpDict2->lookup("Length", &obj3);
323 onStr = new GooString ("D");
324 obj3.free();
325 }
326 obj2.free();
327 if (onStr)
328 break;
329 }
330 }
331 obj1.free();
332
333 //We didn't found the "on" state for the button
334 if (!onStr) {
335 error(-1, "FormWidgetButton:: unable to find the on state for the button\n");
336 onStr = new GooString(""); // TODO is this the best solution?
337 }
338 }
339
340 if (Form::fieldLookup(dict, "V", &obj1)->isName()) {
341 Object obj2;
342 if (dict->lookup("AS", &obj2)->isName(obj1.getName())) {
343 if (strcmp (obj1.getName(), "Off") != 0) {
344 setState(gTrue);
345 }
346 }
347 obj2.free();
348 } else if (obj1.isArray()) { //handle the case where we have multiple choices
349 error(-1, "FormWidgetButton:: multiple choice isn't supported yet\n");
350 }
351 obj1.free();
352 }
353
getState()354 GBool FormWidgetButton::getState ()
355 {
356 return state;
357 }
358
setNumSiblingsID(int i)359 void FormWidgetButton::setNumSiblingsID (int i)
360 {
361 numSiblingsID = i;
362 siblingsID = (unsigned*)greallocn(siblingsID, numSiblingsID, sizeof(unsigned));
363 }
364
365
FormWidgetText(XRef * xrefA,Object * aobj,unsigned num,Ref ref,FormField * p)366 FormWidgetText::FormWidgetText (XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
367 FormWidget(xrefA, aobj, num, ref, p)
368 {
369 type = formText;
370 parent = static_cast<FormFieldText*>(field);
371 }
372
loadDefaults()373 void FormWidgetText::loadDefaults ()
374 {
375 if (defaultsLoaded)
376 return;
377
378 defaultsLoaded = gTrue;
379
380 Dict *dict = obj.getDict();
381 Object obj1;
382
383 if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
384 if (obj1.getString()->hasUnicodeMarker()) {
385 if (obj1.getString()->getLength() <= 2) {
386 } else {
387 parent->setContentCopy(obj1.getString());
388 }
389 } else {
390 if (obj1.getString()->getLength() > 0) {
391 //non-unicode string -- assume pdfDocEncoding and try to convert to UTF16BE
392 int tmp_length;
393 char* tmp_str = pdfDocEncodingToUTF16(obj1.getString(), &tmp_length);
394 GooString* str1 = new GooString(tmp_str, tmp_length);
395 parent->setContentCopy(str1);
396 delete str1;
397 delete []tmp_str;
398 }
399 }
400 }
401 obj1.free();
402
403 }
404
getContent()405 GooString* FormWidgetText::getContent ()
406 {
407 return parent->getContent();
408 }
409
getContentCopy()410 GooString* FormWidgetText::getContentCopy ()
411 {
412 return parent->getContentCopy();
413 }
414
isMultiline() const415 bool FormWidgetText::isMultiline () const
416 {
417 return parent->isMultiline();
418 }
419
isPassword() const420 bool FormWidgetText::isPassword () const
421 {
422 return parent->isPassword();
423 }
424
isFileSelect() const425 bool FormWidgetText::isFileSelect () const
426 {
427 return parent->isFileSelect();
428 }
429
noSpellCheck() const430 bool FormWidgetText::noSpellCheck () const
431 {
432 return parent->noSpellCheck();
433 }
434
noScroll() const435 bool FormWidgetText::noScroll () const
436 {
437 return parent->noScroll();
438 }
439
isComb() const440 bool FormWidgetText::isComb () const
441 {
442 return parent->isComb();
443 }
444
isRichText() const445 bool FormWidgetText::isRichText () const
446 {
447 return parent->isRichText();
448 }
449
getMaxLen() const450 int FormWidgetText::getMaxLen () const
451 {
452 return parent->getMaxLen ();
453 }
454
setContent(GooString * new_content)455 void FormWidgetText::setContent(GooString* new_content)
456 {
457 if (isReadOnly()) {
458 error(-1, "FormWidgetText::setContentCopy called on a read only field\n");
459 return;
460 }
461
462 modified = gTrue;
463 if (new_content == NULL) {
464 parent->setContentCopy(NULL);
465 } else {
466 //append the unicode marker <FE FF> if needed
467 if (!new_content->hasUnicodeMarker()) {
468 new_content->insert(0, 0xff);
469 new_content->insert(0, 0xfe);
470 }
471
472 GooString *cont = new GooString(new_content);
473 parent->setContentCopy(cont);
474
475 Object obj1;
476 obj1.initString(cont);
477 updateField ("V", &obj1);
478 }
479 }
480
FormWidgetChoice(XRef * xrefA,Object * aobj,unsigned num,Ref ref,FormField * p)481 FormWidgetChoice::FormWidgetChoice(XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
482 FormWidget(xrefA, aobj, num, ref, p)
483 {
484 type = formChoice;
485 parent = static_cast<FormFieldChoice*>(field);
486 }
487
loadDefaults()488 void FormWidgetChoice::loadDefaults ()
489 {
490 if (defaultsLoaded)
491 return;
492
493 defaultsLoaded = gTrue;
494
495 Dict *dict = obj.getDict();
496 Object obj1;
497 if (dict->lookup("Opt", &obj1)->isArray()) {
498 Object obj2;
499 parent->_setNumChoices(obj1.arrayGetLength());
500 parent->_createChoicesTab();
501 for(int i=0; i<parent->getNumChoices(); i++) {
502 obj1.arrayGet(i, &obj2);
503 if(obj2.isString()) {
504 parent->_setChoiceExportVal(i, obj2.getString()->copy());
505 parent->_setChoiceOptionName(i, obj2.getString()->copy());
506 } else if (obj2.isArray()) { // [Export_value, Displayed_text]
507 Object obj3,obj4;
508 if (obj2.arrayGetLength() < 2) {
509 error(-1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
510 parent->_setChoiceExportVal(i, new GooString(""));
511 parent->_setChoiceOptionName(i, new GooString(""));
512 continue;
513 }
514 obj2.arrayGet(0, &obj3);
515 obj2.arrayGet(1, &obj4);
516 parent->_setChoiceExportVal(i, obj3.getString()->copy());
517 parent->_setChoiceOptionName(i, obj4.getString()->copy());
518 obj3.free();
519 obj4.free();
520 } else {
521 error(-1, "FormWidgetChoice:: invalid %d Opt entry\n", i);
522 parent->_setChoiceExportVal(i, new GooString(""));
523 parent->_setChoiceOptionName(i, new GooString(""));
524 }
525 obj2.free();
526 }
527 } else {
528 //empty choice
529 }
530 obj1.free();
531
532 bool* tmpCurrentChoice = new bool[parent->getNumChoices()];
533 memset(tmpCurrentChoice, 0, sizeof(bool)*parent->getNumChoices());
534
535 //find default choice
536 if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
537 for(int i=0; i<parent->getNumChoices(); i++) {
538 if (parent->getChoice(i)->cmp(obj1.getString()) == 0) {
539 tmpCurrentChoice[i] = true;
540 break;
541 }
542 }
543 } else if (obj1.isArray()) {
544 for(int i=0; i<obj1.arrayGetLength(); i++) {
545 Object obj2;
546 obj1.arrayGet(i, &obj2);
547 for(int j=0; j<parent->getNumChoices(); j++) {
548 if (parent->getChoice(j)->cmp(obj2.getString()) == 0) {
549 tmpCurrentChoice[i] = true;
550 }
551 }
552
553 obj2.free();
554 }
555 }
556 obj1.free();
557
558 //convert choice's human readable strings to UTF16
559 //and update the /Opt dict entry to reflect this change
560 #ifdef UPDATE_OPT
561 Object *objOpt = new Object();
562 objOpt->initArray(xref);
563 #endif
564 for(int i=0; i<parent->getNumChoices(); i++) {
565 if (parent->getChoice(i)->hasUnicodeMarker()) { //string already in UTF16, do nothing
566
567 } else { //string in pdfdocencoding, convert to UTF16
568 int len;
569 char* buffer = pdfDocEncodingToUTF16(parent->getChoice(i), &len);
570 parent->getChoice(i)->Set(buffer, len);
571 delete [] buffer;
572 }
573 #ifdef UPDATE_OPT
574 Object *obj2 = new Object();
575 obj2->initString(choices[i]);
576 objOpt->getArray()->add(obj2);
577 #endif
578 }
579 //set default choice now that we have UTF16 strings
580 for (int i=0; i<parent->getNumChoices(); i++) {
581 if (tmpCurrentChoice[i])
582 parent->select(i);
583 }
584 #ifdef UPDATE_OPT
585 updateField ("Opt", objOpt);
586 #endif
587 delete [] tmpCurrentChoice;
588 }
589
~FormWidgetChoice()590 FormWidgetChoice::~FormWidgetChoice()
591 {
592 }
593
_updateV()594 void FormWidgetChoice::_updateV ()
595 {
596 Object obj1;
597 //this is an editable combo-box with user-entered text
598 if (hasEdit() && parent->getEditChoice()) {
599 obj1.initString(new GooString(parent->getEditChoice()));
600 } else {
601 int numSelected = parent->getNumSelected();
602 if (numSelected == 0) {
603 obj1.initString(new GooString(""));
604 } else if (numSelected == 1) {
605 for(int i=0; i<parent->getNumChoices(); i++) {
606 if (parent->isSelected(i)) {
607 obj1.initString(new GooString(parent->getChoice(i)));
608 break;
609 }
610 }
611 } else {
612 obj1.initArray(xref);
613 for(int i=0; i<parent->getNumChoices(); i++) {
614 if (parent->isSelected(i)) {
615 Object obj2;
616 obj2.initString(new GooString(parent->getChoice(i)));
617 obj1.arrayAdd(&obj2);
618 }
619 }
620 }
621 }
622 updateField ("V", &obj1);
623 modified = gTrue;
624 }
625
_checkRange(int i)626 bool FormWidgetChoice::_checkRange (int i)
627 {
628 if (i < 0 || i >= parent->getNumChoices()) {
629 error(-1, "FormWidgetChoice::_checkRange i out of range : %i", i);
630 return false;
631 }
632 return true;
633 }
634
select(int i)635 void FormWidgetChoice::select (int i)
636 {
637 if (isReadOnly()) {
638 error(-1, "FormWidgetChoice::select called on a read only field\n");
639 return;
640 }
641 if (!_checkRange(i)) return;
642 modified = gTrue;
643 parent->select(i);
644 _updateV();
645 }
646
toggle(int i)647 void FormWidgetChoice::toggle (int i)
648 {
649 if (isReadOnly()) {
650 error(-1, "FormWidgetChoice::toggle called on a read only field\n");
651 return;
652 }
653 if (!_checkRange(i)) return;
654 modified = gTrue;
655 parent->toggle(i);
656 _updateV();
657 }
658
deselectAll()659 void FormWidgetChoice::deselectAll ()
660 {
661 if (isReadOnly()) {
662 error(-1, "FormWidgetChoice::deselectAll called on a read only field\n");
663 return;
664 }
665 modified = gTrue;
666 parent->deselectAll();
667 _updateV();
668 }
669
getEditChoice()670 GooString* FormWidgetChoice::getEditChoice ()
671 {
672 if (!hasEdit()) {
673 error(-1, "FormFieldChoice::getEditChoice called on a non-editable choice\n");
674 return NULL;
675 }
676 return parent->getEditChoice();
677 }
678
isSelected(int i)679 bool FormWidgetChoice::isSelected (int i)
680 {
681 if (!_checkRange(i)) return false;
682 return parent->isSelected(i);
683 }
684
setEditChoice(GooString * new_content)685 void FormWidgetChoice::setEditChoice (GooString* new_content)
686 {
687 if (isReadOnly()) {
688 error(-1, "FormWidgetText::setEditChoice called on a read only field\n");
689 return;
690 }
691 if (!hasEdit()) {
692 error(-1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
693 return;
694 }
695
696 modified = gTrue;
697 if (new_content == NULL) {
698 parent->setEditChoice(NULL);
699 } else {
700 //append the unicode marker <FE FF> if needed
701 if (!new_content->hasUnicodeMarker()) {
702 new_content->insert(0, 0xff);
703 new_content->insert(0, 0xfe);
704 }
705 parent->setEditChoice(new_content);
706 }
707 _updateV();
708 }
709
getNumChoices()710 int FormWidgetChoice::getNumChoices()
711 {
712 return parent->getNumChoices();
713 }
714
getChoice(int i)715 GooString* FormWidgetChoice::getChoice(int i)
716 {
717 return parent->getChoice(i);
718 }
719
isCombo() const720 bool FormWidgetChoice::isCombo () const
721 {
722 return parent->isCombo();
723 }
724
hasEdit() const725 bool FormWidgetChoice::hasEdit () const
726 {
727 return parent->hasEdit();
728 }
729
isMultiSelect() const730 bool FormWidgetChoice::isMultiSelect () const
731 {
732 return parent->isMultiSelect();
733 }
734
noSpellCheck() const735 bool FormWidgetChoice::noSpellCheck () const
736 {
737 return parent->noSpellCheck();
738 }
739
commitOnSelChange() const740 bool FormWidgetChoice::commitOnSelChange () const
741 {
742 return parent->commitOnSelChange();
743 }
744
isListBox() const745 bool FormWidgetChoice::isListBox () const
746 {
747 return parent->isListBox();
748 }
749
FormWidgetSignature(XRef * xrefA,Object * aobj,unsigned num,Ref ref,FormField * p)750 FormWidgetSignature::FormWidgetSignature(XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
751 FormWidget(xrefA, aobj, num, ref, p)
752 {
753 type = formSignature;
754 parent = static_cast<FormFieldSignature*>(field);
755 }
756
757
758 //========================================================================
759 // FormField
760 //========================================================================
761
FormField(XRef * xrefA,Object * aobj,const Ref & aref,std::set<int> * usedParents,FormFieldType ty)762 FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, std::set<int> *usedParents, FormFieldType ty)
763 {
764 xref = xrefA;
765 aobj->copy(&obj);
766 Dict* dict = obj.getDict();
767 ref.num = ref.gen = 0;
768 type = ty;
769 numChildren = 0;
770 children = NULL;
771 terminal = false;
772 widgets = NULL;
773 readOnly = false;
774 ref = aref;
775
776 Object obj1;
777 //childs
778 if (dict->lookup("Kids", &obj1)->isArray()) {
779 Array *array = obj1.getArray();
780 int length = array->getLength();
781 // Load children
782 for(int i=0; i<length; i++) {
783 Object obj2,obj3;
784 array->get(i, &obj2);
785 if (!obj2.isDict ()) {
786 error (-1, "Reference to an invalid or non existant object");
787 obj2.free();
788 continue;
789 }
790 Object childRef;
791 array->getNF(i, &childRef);
792 if (childRef.isRef()) {
793 const Ref ref = childRef.getRef();
794 if (usedParents->find(ref.num) == usedParents->end()) {
795 //field child
796 if (dict->lookup ("FT", &obj3)->isName()) {
797 // If I'm not a generic container field and my children
798 // are widgets, create widgets for them
799 Object obj4;
800
801 if (obj2.dictLookup("Subtype",&obj4)->isName()) {
802 _createWidget(&obj2, childRef.getRef());
803 }
804 obj4.free();
805 } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
806 std::set<int> usedParentsAux = *usedParents;
807 usedParentsAux.insert(ref.num);
808 if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
809
810 numChildren++;
811 children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
812
813 obj3.free();
814 children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef(), &usedParentsAux);
815 }
816 // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
817 // as if the annot was in the Kids array of the field
818 else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
819 _createWidget(&obj2, childRef.getRef());
820 }
821 obj3.free();
822 } else {
823 error(-1, "Found loop in FormField creation");
824 }
825 } else {
826 error(-1, "FormField child is not a Ref as expected");
827 }
828 obj2.free();
829 }
830 }
831 obj1.free();
832 // As said in 1, if this is a 'collapsed' field, behave like if we had a
833 // child annot
834 if (dict->lookup("Subtype", &obj1)->isName()) {
835 _createWidget(aobj, ref);
836 }
837 obj1.free();
838
839 //flags
840 if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
841 int flags = obj1.getInt();
842 if (flags & 0x1) { // 1 -> ReadOnly
843 readOnly = true;
844 }
845 if (flags & 0x2) { // 2 -> Required
846 //TODO
847 }
848 if (flags & 0x4) { // 3 -> NoExport
849 //TODO
850 }
851 }
852 obj1.free();
853 }
854
~FormField()855 FormField::~FormField()
856 {
857 if (!terminal) {
858 if(children) {
859 for (int i=0; i<numChildren; i++)
860 delete children[i];
861 gfree(children);
862 }
863 } else {
864 for (int i = 0; i < numChildren; ++i)
865 delete widgets[i];
866 gfree (widgets);
867 }
868 obj.free();
869 }
870
loadChildrenDefaults()871 void FormField::loadChildrenDefaults ()
872 {
873 if(!terminal) {
874 for(int i=0; i<numChildren; i++) {
875 children[i]->loadChildrenDefaults();
876 }
877 } else {
878 for (int i=0; i<numChildren; i++) {
879 widgets[i]->loadDefaults();
880 }
881 }
882 }
883
fillChildrenSiblingsID()884 void FormField::fillChildrenSiblingsID()
885 {
886 if(terminal) return;
887 for (int i=0; i<numChildren; i++) {
888 children[i]->fillChildrenSiblingsID();
889 }
890 }
891
892
_createWidget(Object * obj,Ref aref)893 void FormField::_createWidget (Object *obj, Ref aref)
894 {
895 terminal = true;
896 numChildren++;
897 widgets = (FormWidget**)greallocn(widgets, numChildren, sizeof(FormWidget*));
898 //ID = index in "widgets" table
899 switch (type) {
900 case formButton:
901 widgets[numChildren-1] = new FormWidgetButton(xref, obj, numChildren-1, aref, this);
902 break;
903 case formText:
904 widgets[numChildren-1] = new FormWidgetText(xref, obj, numChildren-1, aref, this);
905 break;
906 case formChoice:
907 widgets[numChildren-1] = new FormWidgetChoice(xref, obj, numChildren-1, aref, this);
908 break;
909 case formSignature:
910 widgets[numChildren-1] = new FormWidgetSignature(xref, obj, numChildren-1, aref, this);
911 break;
912 default:
913 error(-1, "SubType on non-terminal field, invalid document?");
914 numChildren--;
915 terminal = false;
916 }
917 }
918
findWidgetByRef(Ref aref)919 FormWidget* FormField::findWidgetByRef (Ref aref)
920 {
921 if (terminal) {
922 for(int i=0; i<numChildren; i++) {
923 if (widgets[i]->getRef().num == aref.num
924 && widgets[i]->getRef().gen == aref.gen)
925 return widgets[i];
926 }
927 } else {
928 for(int i=0; i<numChildren; i++) {
929 FormWidget* result = children[i]->findWidgetByRef(aref);
930 if(result) return result;
931 }
932 }
933 return NULL;
934 }
935
936
937 //------------------------------------------------------------------------
938 // FormFieldButton
939 //------------------------------------------------------------------------
FormFieldButton(XRef * xrefA,Object * aobj,const Ref & ref,std::set<int> * usedParents)940 FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
941 : FormField(xrefA, aobj, ref, usedParents, formButton)
942 {
943 Dict* dict = obj.getDict();
944 active_child = -1;
945 noAllOff = false;
946
947 Object obj1;
948 btype = formButtonCheck;
949 if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
950 int flags = obj1.getInt();
951
952 if (flags & 0x10000) { // 17 -> push button
953 btype = formButtonPush;
954 } else if (flags & 0x8000) { // 16 -> radio button
955 btype = formButtonRadio;
956 if (flags & 0x4000) { // 15 -> noToggleToOff
957 noAllOff = true;
958 }
959 }
960 if (flags & 0x1000000) { // 26 -> radiosInUnison
961 error(-1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
962 }
963 }
964 }
965
fillChildrenSiblingsID()966 void FormFieldButton::fillChildrenSiblingsID()
967 {
968 if (!terminal) {
969 for(int i=0; i<numChildren; i++) {
970 children[i]->fillChildrenSiblingsID();
971 }
972 } else {
973 for(int i=0; i<numChildren; i++) {
974 FormWidgetButton *btn = static_cast<FormWidgetButton*>(widgets[i]);
975 btn->setNumSiblingsID(numChildren-1);
976 for(int j=0, counter=0; j<numChildren; j++) {
977 if (i == j) continue;
978 btn->setSiblingsID(counter, widgets[j]->getID());
979 counter++;
980 }
981 }
982 }
983 }
984
setState(int num,GBool s)985 GBool FormFieldButton::setState (int num, GBool s)
986 {
987 if (readOnly) {
988 error(-1, "FormFieldButton::setState called on a readOnly field\n");
989 return gFalse;
990 }
991
992 // A check button could behave as a radio button
993 // when it's in a set of more than 1 buttons
994 if (btype == formButtonRadio || btype == formButtonCheck) {
995 if (!s && noAllOff)
996 return gFalse; //don't allow to set all radio to off
997
998 if (s == gTrue) {
999 active_child = num;
1000 for(int i=0; i<numChildren; i++) {
1001 if (i==active_child) continue;
1002 static_cast<FormWidgetButton*>(widgets[i])->setState(gFalse, gTrue);
1003 }
1004
1005 //The parent field's V entry holds a name object corresponding to the ap-
1006 //pearance state of whichever child field is currently in the on state
1007 if (active_child >= 0) {
1008 FormWidgetButton* actChild = static_cast<FormWidgetButton*>(widgets[active_child]);
1009 if (actChild->getOnStr()) {
1010 Object obj1;
1011 obj1.initName(actChild->getOnStr());
1012 obj.getDict()->set("V", &obj1);
1013 xref->setModifiedObject(&obj, ref);
1014 }
1015 }
1016 } else {
1017 active_child = -1;
1018 Object obj1;
1019 obj1.initName("Off");
1020 obj.getDict()->set("V", &obj1);
1021 xref->setModifiedObject(&obj, ref);
1022 }
1023 }
1024 return gTrue;
1025 }
1026
~FormFieldButton()1027 FormFieldButton::~FormFieldButton()
1028 {
1029 }
1030
1031 //------------------------------------------------------------------------
1032 // FormFieldText
1033 //------------------------------------------------------------------------
FormFieldText(XRef * xrefA,Object * aobj,const Ref & ref,std::set<int> * usedParents)1034 FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
1035 : FormField(xrefA, aobj, ref, usedParents, formText)
1036 {
1037 Dict* dict = obj.getDict();
1038 Object obj1;
1039 content = NULL;
1040 multiline = password = fileSelect = doNotSpellCheck = doNotScroll = comb = richText = false;
1041 maxLen = 0;
1042
1043 if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
1044 int flags = obj1.getInt();
1045 if (flags & 0x1000) // 13 -> Multiline
1046 multiline = true;
1047 if (flags & 0x2000) // 14 -> Password
1048 password = true;
1049 if (flags & 0x100000) // 21 -> FileSelect
1050 fileSelect = true;
1051 if (flags & 0x400000)// 23 -> DoNotSpellCheck
1052 doNotSpellCheck = true;
1053 if (flags & 0x800000) // 24 -> DoNotScroll
1054 doNotScroll = true;
1055 if (flags & 0x1000000) // 25 -> Comb
1056 comb = true;
1057 if (flags & 0x2000000)// 26 -> RichText
1058 richText = true;
1059 }
1060 obj1.free();
1061
1062 if (Form::fieldLookup(dict, "MaxLen", &obj1)->isInt()) {
1063 maxLen = obj1.getInt();
1064 }
1065 obj1.free();
1066 }
1067
getContentCopy()1068 GooString* FormFieldText::getContentCopy ()
1069 {
1070 if (!content) return NULL;
1071 return new GooString(content);
1072 }
1073
setContentCopy(GooString * new_content)1074 void FormFieldText::setContentCopy (GooString* new_content)
1075 {
1076 if(content) {
1077 delete content;
1078 }
1079 content = new_content->copy();
1080 }
1081
~FormFieldText()1082 FormFieldText::~FormFieldText()
1083 {
1084 delete content;
1085 }
1086
1087
1088 //------------------------------------------------------------------------
1089 // FormFieldChoice
1090 //------------------------------------------------------------------------
FormFieldChoice(XRef * xrefA,Object * aobj,const Ref & ref,std::set<int> * usedParents)1091 FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
1092 : FormField(xrefA, aobj, ref, usedParents, formChoice)
1093 {
1094 numChoices = 0;
1095 choices = NULL;
1096 editedChoice = NULL;
1097
1098 Dict* dict = obj.getDict();
1099 Object obj1;
1100
1101 combo = edit = multiselect = doNotSpellCheck = doCommitOnSelChange = false;
1102
1103 if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
1104 int flags = obj1.getInt();
1105 if (flags & 0x20000) // 18 -> Combo
1106 combo = true;
1107 if (flags & 0x40000) // 19 -> Edit
1108 edit = true;
1109 if (flags & 0x200000) // 22 -> MultiSelect
1110 multiselect = true;
1111 if (flags & 0x400000) // 23 -> DoNotSpellCheck
1112 doNotSpellCheck = true;
1113 if (flags & 0x4000000) // 27 -> CommitOnSelChange
1114 doCommitOnSelChange = true;
1115 }
1116 obj1.free();
1117
1118 }
1119
~FormFieldChoice()1120 FormFieldChoice::~FormFieldChoice()
1121 {
1122 for (int i=0; i<numChoices; i++) {
1123 delete choices[i].exportVal;
1124 delete choices[i].optionName;
1125 }
1126 delete [] choices;
1127 delete editedChoice;
1128 }
1129
deselectAll()1130 void FormFieldChoice::deselectAll ()
1131 {
1132 for(int i=0; i<numChoices; i++) {
1133 choices[i].selected = false;
1134 }
1135 }
1136
toggle(int i)1137 void FormFieldChoice::toggle (int i)
1138 {
1139 choices[i].selected = !choices[i].selected;
1140 }
1141
select(int i)1142 void FormFieldChoice::select (int i)
1143 {
1144 if (!multiselect)
1145 deselectAll();
1146 choices[i].selected = true;
1147 }
1148
setEditChoice(GooString * new_content)1149 void FormFieldChoice::setEditChoice (GooString* new_content)
1150 {
1151 if (editedChoice)
1152 delete editedChoice;
1153
1154 deselectAll();
1155
1156 editedChoice = new_content->copy();
1157 }
1158
getEditChoice()1159 GooString* FormFieldChoice::getEditChoice ()
1160 {
1161 return editedChoice;
1162 }
1163
getNumSelected()1164 int FormFieldChoice::getNumSelected ()
1165 {
1166 int cnt = 0;
1167 for(int i=0; i<numChoices; i++) {
1168 if (choices[i].selected)
1169 cnt++;
1170 }
1171 return cnt;
1172 }
1173
_createChoicesTab()1174 void FormFieldChoice::_createChoicesTab ()
1175 {
1176 choices = new ChoiceOpt[numChoices];
1177 for(int i=0; i<numChoices; i++) {
1178 choices[i].selected = false;
1179 }
1180 }
1181
1182 //------------------------------------------------------------------------
1183 // FormFieldSignature
1184 //------------------------------------------------------------------------
FormFieldSignature(XRef * xrefA,Object * dict,const Ref & ref,std::set<int> * usedParents)1185 FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents)
1186 : FormField(xrefA, dict, ref, usedParents, formSignature)
1187 {
1188 }
1189
~FormFieldSignature()1190 FormFieldSignature::~FormFieldSignature()
1191 {
1192
1193 }
1194
1195 //------------------------------------------------------------------------
1196 // Form
1197 //------------------------------------------------------------------------
1198
Form(XRef * xrefA,Object * acroFormA)1199 Form::Form(XRef *xrefA, Object* acroFormA)
1200 {
1201 Object obj1;
1202
1203 xref = xrefA;
1204 acroForm = acroFormA;
1205
1206 size = 0;
1207 numFields = 0;
1208 rootFields = NULL;
1209
1210 acroForm->dictLookup("NeedAppearances", &obj1);
1211 needAppearances = (obj1.isBool() && obj1.getBool());
1212 obj1.free();
1213
1214 acroForm->dictLookup("Fields", &obj1);
1215 if (obj1.isArray()) {
1216 Array *array = obj1.getArray();
1217 Object obj2;
1218
1219 for(int i=0; i<array->getLength(); i++) {
1220 Object oref;
1221 array->get(i, &obj2);
1222 array->getNF(i, &oref);
1223 if (!oref.isRef()) {
1224 error(-1, "Direct object in rootFields");
1225 obj2.free();
1226 oref.free();
1227 continue;
1228 }
1229
1230 if (!obj2.isDict()) {
1231 error(-1, "Reference in Fields array to an invalid or non existant object");
1232 obj2.free();
1233 oref.free();
1234 continue;
1235 }
1236
1237 if (numFields >= size) {
1238 size += 16;
1239 rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
1240 }
1241
1242 std::set<int> usedParents;
1243 rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef(), &usedParents);
1244
1245 obj2.free();
1246 oref.free();
1247 }
1248 } else {
1249 error(-1, "Can't get Fields array\n");
1250 }
1251 obj1.free ();
1252 }
1253
~Form()1254 Form::~Form() {
1255 int i;
1256 for(i = 0; i< numFields; ++i)
1257 delete rootFields[i];
1258 gfree (rootFields);
1259 }
1260
1261 // Look up an inheritable field dictionary entry.
fieldLookup(Dict * field,char * key,Object * obj,std::set<int> * usedParents)1262 static Object *fieldLookup(Dict *field, char *key, Object *obj, std::set<int> *usedParents) {
1263 Dict *dict;
1264 Object parent;
1265
1266 dict = field;
1267 if (!dict->lookup(key, obj)->isNull()) {
1268 return obj;
1269 }
1270 obj->free();
1271 dict->lookupNF("Parent", &parent);
1272 if (parent.isRef()) {
1273 const Ref ref = parent.getRef();
1274 if (usedParents->find(ref.num) == usedParents->end()) {
1275 usedParents->insert(ref.num);
1276
1277 Object obj2;
1278 parent.fetch(dict->getXRef(), &obj2);
1279 if (obj2.isDict()) {
1280 fieldLookup(obj2.getDict(), key, obj, usedParents);
1281 } else {
1282 obj->initNull();
1283 }
1284 obj2.free();
1285 }
1286 } else if (parent.isDict()) {
1287 fieldLookup(parent.getDict(), key, obj, usedParents);
1288 } else {
1289 obj->initNull();
1290 }
1291 parent.free();
1292 return obj;
1293 }
1294
fieldLookup(Dict * field,char * key,Object * obj)1295 Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
1296 std::set<int> usedParents;
1297 return ::fieldLookup(field, key, obj, &usedParents);
1298 }
1299
createFieldFromDict(Object * obj,XRef * xrefA,const Ref & pref,std::set<int> * usedParents)1300 FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref, std::set<int> *usedParents)
1301 {
1302 Object obj2;
1303 FormField *field;
1304
1305 if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
1306 field = new FormFieldButton(xrefA, obj, pref, usedParents);
1307 } else if (obj2.isName("Tx")) {
1308 field = new FormFieldText(xrefA, obj, pref, usedParents);
1309 } else if (obj2.isName("Ch")) {
1310 field = new FormFieldChoice(xrefA, obj, pref, usedParents);
1311 } else if (obj2.isName("Sig")) {
1312 field = new FormFieldSignature(xrefA, obj, pref, usedParents);
1313 } else { //we don't have an FT entry => non-terminal field
1314 field = new FormField(xrefA, obj, pref, usedParents);
1315 }
1316 obj2.free();
1317
1318 field->loadChildrenDefaults();
1319
1320 return field;
1321 }
1322
postWidgetsLoad()1323 void Form::postWidgetsLoad ()
1324 {
1325 for(int i=0; i<numFields; i++) {
1326 rootFields[i]->fillChildrenSiblingsID();
1327 }
1328 }
1329
findWidgetByRef(Ref aref)1330 FormWidget* Form::findWidgetByRef (Ref aref)
1331 {
1332 for(int i=0; i<numFields; i++) {
1333 FormWidget *result = rootFields[i]->findWidgetByRef(aref);
1334 if(result) return result;
1335 }
1336 return NULL;
1337 }
1338
1339 //------------------------------------------------------------------------
1340 // FormPageWidgets
1341 //------------------------------------------------------------------------
1342
FormPageWidgets(XRef * xrefA,Object * annots,unsigned int page,Form * form)1343 FormPageWidgets::FormPageWidgets (XRef *xrefA, Object* annots, unsigned int page, Form *form)
1344 {
1345 Object obj1;
1346 numWidgets = 0;
1347 widgets = NULL;
1348 xref = xrefA;
1349 if (annots->isArray() && form) {
1350 size = annots->arrayGetLength();
1351 widgets = (FormWidget**)greallocn(widgets, size, sizeof(FormWidget*));
1352
1353 /* For each entry in the page 'Annots' dict, try to find
1354 a matching form field */
1355 for (int i = 0; i < size; ++i) {
1356 if (!annots->arrayGetNF(i, &obj1)->isRef()) {
1357 /* Since all entry in a form field's kid dict needs to be
1358 indirect references, if this annot isn't indirect, it isn't
1359 related to a form field */
1360 obj1.free();
1361 continue;
1362 }
1363 Ref r = obj1.getRef();
1364
1365 /* Try to find a form field which either has this Annot in its Kids entry
1366 or is merged with this Annot */
1367 FormWidget* tmp = form->findWidgetByRef(r);
1368 if(tmp) {
1369 // We've found a corresponding form field, link it
1370 tmp->setID(FormWidget::encodeID(page, numWidgets));
1371 widgets[numWidgets++] = tmp;
1372 //create a temporary Annot to get the font size
1373 Object obj2;
1374 if (annots->arrayGet(i, &obj2)->isDict()) {
1375 Annot *ann;
1376
1377 ann = new Annot(xref, obj2.getDict(), NULL);
1378 tmp->setFontSize(ann->getFontSize());
1379 delete ann;
1380 }
1381 obj2.free();
1382 }
1383
1384 obj1.free();
1385 }
1386 }
1387 }
1388
~FormPageWidgets()1389 FormPageWidgets::~FormPageWidgets()
1390 {
1391 gfree (widgets);
1392 }
1393