1 //========================================================================
5 // This file is licensed under the GPLv2 or later
7 // Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
8 // Copyright 2007-2012 Albert Astals Cid <aacid@kde.org>
9 // Copyright 2007-2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
10 // Copyright 2007, 2013 Adrian Johnson <ajohnson@redneon.com>
11 // Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
12 // Copyright 2008, 2011 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, 2012 Mark Riedesel <mark@klowner.com>
17 // Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
19 //========================================================================
23 #ifdef USE_GCC_PRAGMAS
24 #pragma implementation
31 #include "goo/GooString.h"
40 #include "PDFDocEncoding.h"
44 //return a newly allocated char* containing an UTF16BE string of size length
45 char* pdfDocEncodingToUTF16 (GooString
* orig
, int* length
)
47 //double size, a unicode char takes 2 char, add 2 for the unicode marker
48 *length
= 2+2*orig
->getLength();
49 char *result
= new char[(*length
)];
50 char *cstring
= orig
->getCString();
55 for(int i
=2,j
=0; i
<(*length
); i
+=2,j
++) {
56 Unicode u
= pdfDocEncoding
[(unsigned int)((unsigned char)cstring
[j
])]&0xffff;
57 result
[i
] = (u
>> 8) & 0xff;
58 result
[i
+1] = u
& 0xff;
63 static GooString
*convertToUtf16(GooString
*pdfDocEncodingString
)
66 char* tmp_str
= pdfDocEncodingToUTF16(pdfDocEncodingString
, &tmp_length
);
67 delete pdfDocEncodingString
;
68 pdfDocEncodingString
= new GooString(tmp_str
, tmp_length
);
70 return pdfDocEncodingString
;
74 FormWidget::FormWidget(PDFDoc
*docA
, Object
*aobj
, unsigned num
, Ref aref
, FormField
*fieldA
)
80 xref
= doc
->getXRef();
87 FormWidget::~FormWidget()
95 void FormWidget::print(int indent
) {
96 printf ("%*s+ (%d %d): [widget]\n", indent
, "", ref
.num
, ref
.gen
);
100 void FormWidget::createWidgetAnnotation() {
105 obj1
.initRef(ref
.num
, ref
.gen
);
106 widget
= new AnnotWidget(doc
, obj
.getDict(), &obj1
, field
);
110 GBool
FormWidget::inRect(double x
, double y
) const {
111 return widget
? widget
->inRect(x
, y
) : gFalse
;
114 void FormWidget::getRect(double *x1
, double *y1
, double *x2
, double *y2
) const {
116 widget
->getRect(x1
, y1
, x2
, y2
);
119 double FormWidget::getFontSize() const {
120 return widget
? widget
->getFontSize() : 0.;
123 bool FormWidget::isReadOnly() const
125 return field
->isReadOnly();
128 int FormWidget::encodeID (unsigned pageNum
, unsigned fieldNum
)
130 return (pageNum
<< 4*sizeof(unsigned)) + fieldNum
;
133 void FormWidget::decodeID (unsigned id
, unsigned* pageNum
, unsigned* fieldNum
)
135 *pageNum
= id
>> 4*sizeof(unsigned);
136 *fieldNum
= (id
<< 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
139 GooString
*FormWidget::getPartialName() const {
140 return field
->getPartialName();
143 GooString
*FormWidget::getAlternateUiName() const {
144 return field
->getAlternateUiName();
147 GooString
*FormWidget::getMappingName() const {
148 return field
->getMappingName();
151 GooString
*FormWidget::getFullyQualifiedName() {
152 return field
->getFullyQualifiedName();
155 LinkAction
*FormWidget::getActivationAction() {
156 return widget
? widget
->getAction() : NULL
;
159 LinkAction
*FormWidget::getAdditionalAction(Annot::FormAdditionalActionsType type
) {
160 return widget
? widget
->getFormAdditionalAction(type
) : NULL
;
163 FormWidgetButton::FormWidgetButton (PDFDoc
*docA
, Object
*aobj
, unsigned num
, Ref ref
, FormField
*p
) :
164 FormWidget(docA
, aobj
, num
, ref
, p
)
167 parent
= static_cast<FormFieldButton
*>(field
);
172 // Find the name of the ON state in the AP dictionnary
173 // The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
174 // The "on" state may be stored under any other name
175 if (obj
.dictLookup("AP", &obj1
)->isDict()) {
176 if (obj1
.dictLookup("N", &obj2
)->isDict()) {
177 for (int i
= 0; i
< obj2
.dictGetLength(); i
++) {
178 char *key
= obj2
.dictGetKey(i
);
179 if (strcmp (key
, "Off") != 0) {
180 onStr
= new GooString (key
);
190 char *FormWidgetButton::getOnStr() {
192 return onStr
->getCString();
194 // 12.7.4.2.3 Check Boxes
195 // Yes should be used as the name for the on state
196 return parent
->getButtonType() == formButtonCheck
? (char *)"Yes" : NULL
;
199 FormWidgetButton::~FormWidgetButton ()
204 FormButtonType
FormWidgetButton::getButtonType () const
206 return parent
->getButtonType ();
209 void FormWidgetButton::setAppearanceState(const char *state
) {
212 widget
->setAppearanceState(state
);
215 void FormWidgetButton::updateWidgetAppearance()
217 // The appearance stream must NOT be regenerated for this widget type
220 void FormWidgetButton::setState (GBool astate
)
222 //pushButtons don't have state
223 if (parent
->getButtonType() == formButtonPush
)
226 // Silently return if can't set ON state
227 if (astate
&& !onStr
)
230 parent
->setState(astate
? onStr
->getCString() : (char *)"Off");
231 // Parent will call setAppearanceState()
234 GBool
FormWidgetButton::getState ()
236 return onStr
? parent
->getState(onStr
->getCString()) : gFalse
;
240 FormWidgetText::FormWidgetText (PDFDoc
*docA
, Object
*aobj
, unsigned num
, Ref ref
, FormField
*p
) :
241 FormWidget(docA
, aobj
, num
, ref
, p
)
244 parent
= static_cast<FormFieldText
*>(field
);
247 GooString
* FormWidgetText::getContent ()
249 return parent
->getContent();
252 GooString
* FormWidgetText::getContentCopy ()
254 return parent
->getContentCopy();
257 void FormWidgetText::updateWidgetAppearance()
260 widget
->updateAppearanceStream();
263 bool FormWidgetText::isMultiline () const
265 return parent
->isMultiline();
268 bool FormWidgetText::isPassword () const
270 return parent
->isPassword();
273 bool FormWidgetText::isFileSelect () const
275 return parent
->isFileSelect();
278 bool FormWidgetText::noSpellCheck () const
280 return parent
->noSpellCheck();
283 bool FormWidgetText::noScroll () const
285 return parent
->noScroll();
288 bool FormWidgetText::isComb () const
290 return parent
->isComb();
293 bool FormWidgetText::isRichText () const
295 return parent
->isRichText();
298 int FormWidgetText::getMaxLen () const
300 return parent
->getMaxLen ();
303 void FormWidgetText::setContent(GooString
* new_content
)
306 error(errInternal
, -1, "FormWidgetText::setContentCopy called on a read only field\n");
310 parent
->setContentCopy(new_content
);
313 FormWidgetChoice::FormWidgetChoice(PDFDoc
*docA
, Object
*aobj
, unsigned num
, Ref ref
, FormField
*p
) :
314 FormWidget(docA
, aobj
, num
, ref
, p
)
317 parent
= static_cast<FormFieldChoice
*>(field
);
320 FormWidgetChoice::~FormWidgetChoice()
324 bool FormWidgetChoice::_checkRange (int i
)
326 if (i
< 0 || i
>= parent
->getNumChoices()) {
327 error(errInternal
, -1, "FormWidgetChoice::_checkRange i out of range : {0:d}", i
);
333 void FormWidgetChoice::select (int i
)
336 error(errInternal
, -1, "FormWidgetChoice::select called on a read only field\n");
339 if (!_checkRange(i
)) return;
343 void FormWidgetChoice::toggle (int i
)
346 error(errInternal
, -1, "FormWidgetChoice::toggle called on a read only field\n");
349 if (!_checkRange(i
)) return;
353 void FormWidgetChoice::deselectAll ()
356 error(errInternal
, -1, "FormWidgetChoice::deselectAll called on a read only field\n");
359 parent
->deselectAll();
362 GooString
* FormWidgetChoice::getEditChoice ()
365 error(errInternal
, -1, "FormFieldChoice::getEditChoice called on a non-editable choice\n");
368 return parent
->getEditChoice();
371 void FormWidgetChoice::updateWidgetAppearance()
374 widget
->updateAppearanceStream();
377 bool FormWidgetChoice::isSelected (int i
)
379 if (!_checkRange(i
)) return false;
380 return parent
->isSelected(i
);
383 void FormWidgetChoice::setEditChoice (GooString
* new_content
)
386 error(errInternal
, -1, "FormWidgetText::setEditChoice called on a read only field\n");
390 error(errInternal
, -1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
394 parent
->setEditChoice(new_content
);
397 int FormWidgetChoice::getNumChoices()
399 return parent
->getNumChoices();
402 GooString
* FormWidgetChoice::getChoice(int i
)
404 return parent
->getChoice(i
);
407 bool FormWidgetChoice::isCombo () const
409 return parent
->isCombo();
412 bool FormWidgetChoice::hasEdit () const
414 return parent
->hasEdit();
417 bool FormWidgetChoice::isMultiSelect () const
419 return parent
->isMultiSelect();
422 bool FormWidgetChoice::noSpellCheck () const
424 return parent
->noSpellCheck();
427 bool FormWidgetChoice::commitOnSelChange () const
429 return parent
->commitOnSelChange();
432 bool FormWidgetChoice::isListBox () const
434 return parent
->isListBox();
437 FormWidgetSignature::FormWidgetSignature(PDFDoc
*docA
, Object
*aobj
, unsigned num
, Ref ref
, FormField
*p
) :
438 FormWidget(docA
, aobj
, num
, ref
, p
)
440 type
= formSignature
;
441 parent
= static_cast<FormFieldSignature
*>(field
);
444 void FormWidgetSignature::updateWidgetAppearance()
450 //========================================================================
452 //========================================================================
454 FormField::FormField(PDFDoc
*docA
, Object
*aobj
, const Ref
& aref
, FormField
*parentA
, std::set
<int> *usedParents
, FormFieldType ty
)
457 xref
= doc
->getXRef();
459 Dict
* dict
= obj
.getDict();
460 ref
.num
= ref
.gen
= 0;
468 defaultAppearance
= NULL
;
469 fullyQualifiedName
= NULL
;
470 quadding
= quaddingLeftJustified
;
471 hasQuadding
= gFalse
;
477 if (dict
->lookup("Kids", &obj1
)->isArray()) {
479 for (int i
= 0 ; i
< obj1
.arrayGetLength(); i
++) {
480 Object childRef
, childObj
;
482 if (!obj1
.arrayGetNF(i
, &childRef
)->isRef()) {
483 error (errSyntaxError
, -1, "Invalid form field renference");
487 if (!obj1
.arrayGet(i
, &childObj
)->isDict()) {
488 error (errSyntaxError
, -1, "Form field child is not a dictionary");
494 const Ref ref
= childRef
.getRef();
495 if (usedParents
->find(ref
.num
) == usedParents
->end()) {
497 // Field child: it could be a form field or a widget or composed dict
498 if (childObj
.dictLookupNF("Parent", &obj2
)->isRef() || childObj
.dictLookup("Parent", &obj3
)->isDict()) {
499 // Child is a form field or composed dict
500 // We create the field, if it's composed
501 // it will create the widget as a child
502 std::set
<int> usedParentsAux
= *usedParents
;
503 usedParentsAux
.insert(ref
.num
);
508 error(errSyntaxWarning
, -1, "Field can't have both Widget AND Field as kids\n");
513 children
= (FormField
**)greallocn(children
, numChildren
, sizeof(FormField
*));
514 children
[numChildren
- 1] = Form::createFieldFromDict(&childObj
, doc
, ref
, this, &usedParentsAux
);
515 } else if (childObj
.dictLookup("Subtype", &obj2
)->isName("Widget")) {
516 // Child is a widget annotation
517 if (!terminal
&& numChildren
> 0) {
518 error(errSyntaxWarning
, -1, "Field can't have both Widget AND Field as kids\n");
523 _createWidget(&childObj
, ref
);
532 // No children, if it's a composed dict, create the child widget
534 if (dict
->lookup("Subtype", &obj1
)->isName("Widget"))
535 _createWidget(&obj
, ref
);
540 if (Form::fieldLookup(dict
, "Ff", &obj1
)->isInt()) {
541 int flags
= obj1
.getInt();
542 if (flags
& 0x1) { // 1 -> ReadOnly
545 if (flags
& 0x2) { // 2 -> Required
548 if (flags
& 0x4) { // 3 -> NoExport
555 if (Form::fieldLookup(dict
, "DA", &obj1
)->isString())
556 defaultAppearance
= obj1
.getString()->copy();
559 if (Form::fieldLookup(dict
, "Q", &obj1
)->isInt()) {
560 quadding
= static_cast<VariableTextQuadding
>(obj1
.getInt());
565 if (dict
->lookup("T", &obj1
)->isString()) {
566 partialName
= obj1
.getString()->copy();
572 if (dict
->lookup("TU", &obj1
)->isString()) {
573 alternateUiName
= obj1
.getString()->copy();
575 alternateUiName
= NULL
;
579 if(dict
->lookup("TM", &obj1
)->isString()) {
580 mappingName
= obj1
.getString()->copy();
587 FormField::~FormField()
591 for (int i
=0; i
<numChildren
; i
++)
596 for (int i
= 0; i
< numChildren
; ++i
)
602 delete defaultAppearance
;
604 delete alternateUiName
;
606 delete fullyQualifiedName
;
610 void FormField::print(int indent
)
612 printf ("%*s- (%d %d): [container] terminal: %s children: %d\n", indent
, "", ref
.num
, ref
.gen
,
613 terminal
? "Yes" : "No", numChildren
);
616 void FormField::printTree(int indent
)
620 for (int i
= 0; i
< numChildren
; i
++)
621 widgets
[i
]->print(indent
+ 4);
623 for (int i
= 0; i
< numChildren
; i
++)
624 children
[i
]->printTree(indent
+ 4);
629 void FormField::fillChildrenSiblingsID()
633 for (int i
= 0; i
< numChildren
; i
++) {
634 children
[i
]->fillChildrenSiblingsID();
638 void FormField::createWidgetAnnotations() {
640 for (int i
= 0; i
< numChildren
; i
++)
641 widgets
[i
]->createWidgetAnnotation();
643 for (int i
= 0; i
< numChildren
; i
++)
644 children
[i
]->createWidgetAnnotations();
648 void FormField::_createWidget (Object
*obj
, Ref aref
)
652 widgets
= (FormWidget
**)greallocn(widgets
, numChildren
, sizeof(FormWidget
*));
653 //ID = index in "widgets" table
656 widgets
[numChildren
-1] = new FormWidgetButton(doc
, obj
, numChildren
-1, aref
, this);
659 widgets
[numChildren
-1] = new FormWidgetText(doc
, obj
, numChildren
-1, aref
, this);
662 widgets
[numChildren
-1] = new FormWidgetChoice(doc
, obj
, numChildren
-1, aref
, this);
665 widgets
[numChildren
-1] = new FormWidgetSignature(doc
, obj
, numChildren
-1, aref
, this);
668 error(errSyntaxWarning
, -1, "SubType on non-terminal field, invalid document?");
674 FormWidget
* FormField::findWidgetByRef (Ref aref
)
677 for(int i
=0; i
<numChildren
; i
++) {
678 if (widgets
[i
]->getRef().num
== aref
.num
679 && widgets
[i
]->getRef().gen
== aref
.gen
)
683 for(int i
=0; i
<numChildren
; i
++) {
684 FormWidget
* result
= children
[i
]->findWidgetByRef(aref
);
685 if(result
) return result
;
691 GooString
* FormField::getFullyQualifiedName() {
694 GooString
*parent_name
;
695 GooString
*full_name
;
696 GBool unicode_encoded
= gFalse
;
698 if (fullyQualifiedName
)
699 return fullyQualifiedName
;
701 full_name
= new GooString();
704 while (obj1
.dictLookup("Parent", &parent
)->isDict()) {
705 if (parent
.dictLookup("T", &obj2
)->isString()) {
706 parent_name
= obj2
.getString();
708 if (unicode_encoded
) {
709 full_name
->insert(0, "\0.", 2); // 2-byte unicode period
710 if (parent_name
->hasUnicodeMarker()) {
711 full_name
->insert(0, parent_name
->getCString() + 2, parent_name
->getLength() - 2); // Remove the unicode BOM
714 char* tmp_str
= pdfDocEncodingToUTF16(parent_name
, &tmp_length
);
715 full_name
->insert(0, tmp_str
+ 2, tmp_length
- 2); // Remove the unicode BOM
719 full_name
->insert(0, '.'); // 1-byte ascii period
720 if (parent_name
->hasUnicodeMarker()) {
721 unicode_encoded
= gTrue
;
722 full_name
= convertToUtf16(full_name
);
723 full_name
->insert(0, parent_name
->getCString() + 2, parent_name
->getLength() - 2); // Remove the unicode BOM
725 full_name
->insert(0, parent_name
);
738 if (unicode_encoded
) {
739 if (partialName
->hasUnicodeMarker()) {
740 full_name
->append(partialName
->getCString() + 2, partialName
->getLength() - 2); // Remove the unicode BOM
743 char* tmp_str
= pdfDocEncodingToUTF16(partialName
, &tmp_length
);
744 full_name
->append(tmp_str
+ 2, tmp_length
- 2); // Remove the unicode BOM
748 if (partialName
->hasUnicodeMarker()) {
749 unicode_encoded
= gTrue
;
750 full_name
= convertToUtf16(full_name
);
751 full_name
->append(partialName
->getCString() + 2, partialName
->getLength() - 2); // Remove the unicode BOM
753 full_name
->append(partialName
);
757 int len
= full_name
->getLength();
758 // Remove the last period
759 if (unicode_encoded
) {
761 full_name
->del(len
- 2, 2);
765 full_name
->del(len
- 1, 1);
770 if (unicode_encoded
) {
771 full_name
->insert(0, 0xff);
772 full_name
->insert(0, 0xfe);
775 fullyQualifiedName
= full_name
;
776 return fullyQualifiedName
;
779 void FormField::updateChildrenAppearance()
781 // Recursively update each child's appearance
783 for (int i
= 0; i
< numChildren
; i
++)
784 widgets
[i
]->updateWidgetAppearance();
786 for (int i
= 0; i
< numChildren
; i
++)
787 children
[i
]->updateChildrenAppearance();
791 //------------------------------------------------------------------------
793 //------------------------------------------------------------------------
794 FormFieldButton::FormFieldButton(PDFDoc
*docA
, Object
*aobj
, const Ref
& ref
, FormField
*parent
, std::set
<int> *usedParents
)
795 : FormField(docA
, aobj
, ref
, parent
, usedParents
, formButton
)
797 Dict
* dict
= obj
.getDict();
802 appearanceState
.initNull();
805 btype
= formButtonCheck
;
806 if (Form::fieldLookup(dict
, "Ff", &obj1
)->isInt()) {
807 int flags
= obj1
.getInt();
809 if (flags
& 0x10000) { // 17 -> push button
810 btype
= formButtonPush
;
811 } else if (flags
& 0x8000) { // 16 -> radio button
812 btype
= formButtonRadio
;
813 if (flags
& 0x4000) { // 15 -> noToggleToOff
817 if (flags
& 0x1000000) { // 26 -> radiosInUnison
818 error(errUnimplemented
, -1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
822 if (btype
!= formButtonPush
) {
823 // Even though V is inheritable we are interested in the value of this
824 // field, if not present it's probably because it's a button in a set.
825 dict
->lookup("V", &appearanceState
);
830 static char *_getButtonType(FormButtonType type
)
835 case formButtonCheck
:
837 case formButtonRadio
:
845 void FormFieldButton::print(int indent
)
847 printf ("%*s- (%d %d): [%s] terminal: %s children: %d\n", indent
, "", ref
.num
, ref
.gen
,
848 _getButtonType(btype
), terminal
? "Yes" : "No", numChildren
);
852 void FormFieldButton::setNumSiblings (int num
)
855 siblings
= (FormFieldButton
**)greallocn(siblings
, numSiblings
, sizeof(FormFieldButton
*));
858 void FormFieldButton::fillChildrenSiblingsID()
861 for(int i
=0; i
<numChildren
; i
++) {
862 FormFieldButton
*child
= dynamic_cast<FormFieldButton
*>(children
[i
]);
864 // Fill the siblings of this node childs
865 child
->setNumSiblings(numChildren
-1);
866 for(int j
=0, counter
=0; j
<numChildren
; j
++) {
867 FormFieldButton
*otherChild
= dynamic_cast<FormFieldButton
*>(children
[j
]);
868 if (i
== j
) continue;
869 if (child
== otherChild
) continue;
870 child
->setSibling(counter
, otherChild
);
874 // now call ourselves on the child
875 // to fill its children data
876 child
->fillChildrenSiblingsID();
882 GBool
FormFieldButton::setState(char *state
)
885 error(errInternal
, -1, "FormFieldButton::setState called on a readOnly field\n");
889 // A check button could behave as a radio button
890 // when it's in a set of more than 1 buttons
891 if (btype
!= formButtonRadio
&& btype
!= formButtonCheck
)
894 if (terminal
&& parent
&& parent
->getType() == formButton
&& appearanceState
.isNull()) {
895 // It's button in a set, set state on parent
896 if (static_cast<FormFieldButton
*>(parent
)->setState(state
)) {
902 GBool isOn
= strcmp(state
, "Off") != 0;
904 if (!isOn
&& noAllOff
)
905 return gFalse
; // Don't allow to set all radio to off
907 char *current
= getAppearanceState();
908 GBool currentFound
= gFalse
, newFound
= gFalse
;
910 for (int i
= 0; i
< numChildren
; i
++) {
911 FormWidgetButton
*widget
;
913 // If radio button is a terminal field we want the widget at i, but
914 // if it's not terminal, the child widget is a composed dict, so
915 // we want the ony child widget of the children at i
917 widget
= static_cast<FormWidgetButton
*>(widgets
[i
]);
919 widget
= static_cast<FormWidgetButton
*>(children
[i
]->getWidget(0));
921 if (!widget
->getOnStr())
924 char *onStr
= widget
->getOnStr();
925 if (current
&& strcmp(current
, onStr
) == 0) {
926 widget
->setAppearanceState("Off");
929 currentFound
= gTrue
;
932 if (isOn
&& strcmp(state
, onStr
) == 0) {
933 widget
->setAppearanceState(state
);
937 if (currentFound
&& newFound
)
946 GBool
FormFieldButton::getState(char *state
) {
947 if (appearanceState
.isName(state
))
950 return (parent
&& parent
->getType() == formButton
) ? static_cast<FormFieldButton
*>(parent
)->getState(state
) : gFalse
;
953 void FormFieldButton::updateState(char *state
) {
956 appearanceState
.free();
957 appearanceState
.initName(state
);
959 appearanceState
.copy(&obj1
);
960 obj
.getDict()->set("V", &obj1
);
961 xref
->setModifiedObject(&obj
, ref
);
964 FormFieldButton::~FormFieldButton()
966 appearanceState
.free();
971 //------------------------------------------------------------------------
973 //------------------------------------------------------------------------
974 FormFieldText::FormFieldText(PDFDoc
*docA
, Object
*aobj
, const Ref
& ref
, FormField
*parent
, std::set
<int> *usedParents
)
975 : FormField(docA
, aobj
, ref
, parent
, usedParents
, formText
)
977 Dict
* dict
= obj
.getDict();
980 multiline
= password
= fileSelect
= doNotSpellCheck
= doNotScroll
= comb
= richText
= false;
983 if (Form::fieldLookup(dict
, "Ff", &obj1
)->isInt()) {
984 int flags
= obj1
.getInt();
985 if (flags
& 0x1000) // 13 -> Multiline
987 if (flags
& 0x2000) // 14 -> Password
989 if (flags
& 0x100000) // 21 -> FileSelect
991 if (flags
& 0x400000)// 23 -> DoNotSpellCheck
992 doNotSpellCheck
= true;
993 if (flags
& 0x800000) // 24 -> DoNotScroll
995 if (flags
& 0x1000000) // 25 -> Comb
997 if (flags
& 0x2000000)// 26 -> RichText
1002 if (Form::fieldLookup(dict
, "MaxLen", &obj1
)->isInt()) {
1003 maxLen
= obj1
.getInt();
1007 if (Form::fieldLookup(dict
, "V", &obj1
)->isString()) {
1008 if (obj1
.getString()->hasUnicodeMarker()) {
1009 if (obj1
.getString()->getLength() > 2)
1010 content
= obj1
.getString()->copy();
1011 } else if (obj1
.getString()->getLength() > 0) {
1012 //non-unicode string -- assume pdfDocEncoding and try to convert to UTF16BE
1014 char* tmp_str
= pdfDocEncodingToUTF16(obj1
.getString(), &tmp_length
);
1015 content
= new GooString(tmp_str
, tmp_length
);
1023 void FormFieldText::print(int indent
)
1025 printf ("%*s- (%d %d): [text] terminal: %s children: %d\n", indent
, "", ref
.num
, ref
.gen
,
1026 terminal
? "Yes" : "No", numChildren
);
1030 GooString
* FormFieldText::getContentCopy ()
1032 if (!content
) return NULL
;
1033 return new GooString(content
);
1036 void FormFieldText::setContentCopy (GooString
* new_content
)
1042 content
= new_content
->copy();
1044 //append the unicode marker <FE FF> if needed
1045 if (!content
->hasUnicodeMarker()) {
1046 content
->insert(0, 0xff);
1047 content
->insert(0, 0xfe);
1052 obj1
.initString(content
? content
->copy() : new GooString(""));
1053 obj
.getDict()->set("V", &obj1
);
1054 xref
->setModifiedObject(&obj
, ref
);
1055 updateChildrenAppearance();
1058 FormFieldText::~FormFieldText()
1064 //------------------------------------------------------------------------
1066 //------------------------------------------------------------------------
1067 FormFieldChoice::FormFieldChoice(PDFDoc
*docA
, Object
*aobj
, const Ref
& ref
, FormField
*parent
, std::set
<int> *usedParents
)
1068 : FormField(docA
, aobj
, ref
, parent
, usedParents
, formChoice
)
1072 editedChoice
= NULL
;
1075 Dict
* dict
= obj
.getDict();
1078 combo
= edit
= multiselect
= doNotSpellCheck
= doCommitOnSelChange
= false;
1080 if (Form::fieldLookup(dict
, "Ff", &obj1
)->isInt()) {
1081 int flags
= obj1
.getInt();
1082 if (flags
& 0x20000) // 18 -> Combo
1084 if (flags
& 0x40000) // 19 -> Edit
1086 if (flags
& 0x200000) // 22 -> MultiSelect
1088 if (flags
& 0x400000) // 23 -> DoNotSpellCheck
1089 doNotSpellCheck
= true;
1090 if (flags
& 0x4000000) // 27 -> CommitOnSelChange
1091 doCommitOnSelChange
= true;
1095 if (dict
->lookup("TI", &obj1
)->isInt())
1096 topIdx
= obj1
.getInt();
1099 if (dict
->lookup("Opt", &obj1
)->isArray()) {
1102 numChoices
= obj1
.arrayGetLength();
1103 choices
= new ChoiceOpt
[numChoices
];
1104 memset(choices
, 0, sizeof(ChoiceOpt
) * numChoices
);
1106 for (int i
= 0; i
< numChoices
; i
++) {
1107 if (obj1
.arrayGet(i
, &obj2
)->isString()) {
1108 choices
[i
].optionName
= obj2
.getString()->copy();
1109 } else if (obj2
.isArray()) { // [Export_value, Displayed_text]
1112 if (obj2
.arrayGetLength() < 2) {
1113 error(errSyntaxError
, -1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
1116 if (obj2
.arrayGet(0, &obj3
)->isString())
1117 choices
[i
].exportVal
= obj3
.getString()->copy();
1119 error(errSyntaxError
, -1, "FormWidgetChoice:: invalid Opt entry -- exported value not a string\n");
1122 if (obj2
.arrayGet(1, &obj3
)->isString())
1123 choices
[i
].optionName
= obj3
.getString()->copy();
1125 error(errSyntaxError
, -1, "FormWidgetChoice:: invalid Opt entry -- choice name not a string\n");
1128 error(errSyntaxError
, -1, "FormWidgetChoice:: invalid {0:d} Opt entry\n", i
);
1137 // Find selected items
1138 // Note: PDF specs say that /V has precedence over /I, but acroread seems to
1139 // do the opposite. We do the same.
1140 if (Form::fieldLookup(dict
, "I", &obj1
)->isArray()) {
1141 for (int i
= 0; i
< obj1
.arrayGetLength(); i
++) {
1143 if (obj1
.arrayGet(i
, &obj2
)->isInt() && obj2
.getInt() >= 0 && obj2
.getInt() < numChoices
) {
1144 choices
[obj2
.getInt()].selected
= true;
1150 // Note: According to PDF specs, /V should *never* contain the exportVal.
1151 // However, if /Opt is an array of (exportVal,optionName) pairs, acroread
1152 // seems to expect the exportVal instead of the optionName and so we do too.
1153 if (Form::fieldLookup(dict
, "V", &obj1
)->isString()) {
1154 GBool optionFound
= gFalse
;
1156 for (int i
= 0; i
< numChoices
; i
++) {
1157 if (choices
[i
].exportVal
) {
1158 if (choices
[i
].exportVal
->cmp(obj1
.getString()) == 0) {
1159 optionFound
= gTrue
;
1161 } else if (choices
[i
].optionName
) {
1162 if (choices
[i
].optionName
->cmp(obj1
.getString()) == 0) {
1163 optionFound
= gTrue
;
1168 choices
[i
].selected
= true;
1169 break; // We've determined that this option is selected. No need to keep on scanning
1173 // Set custom value if /V doesn't refer to any predefined option and the field is user-editable
1174 if (!optionFound
&& edit
) {
1175 editedChoice
= obj1
.getString()->copy();
1177 } else if (obj1
.isArray()) {
1178 for (int i
= 0; i
< numChoices
; i
++) {
1179 for (int j
= 0; j
< obj1
.arrayGetLength(); j
++) {
1181 obj1
.arrayGet(j
, &obj2
);
1182 GBool matches
= gFalse
;
1184 if (choices
[i
].exportVal
) {
1185 if (choices
[i
].exportVal
->cmp(obj2
.getString()) == 0) {
1188 } else if (choices
[i
].optionName
) {
1189 if (choices
[i
].optionName
->cmp(obj2
.getString()) == 0) {
1197 choices
[i
].selected
= true;
1198 break; // We've determined that this option is selected. No need to keep on scanning
1207 FormFieldChoice::~FormFieldChoice()
1209 for (int i
= 0; i
< numChoices
; i
++) {
1210 delete choices
[i
].exportVal
;
1211 delete choices
[i
].optionName
;
1214 delete editedChoice
;
1218 void FormFieldChoice::print(int indent
)
1220 printf ("%*s- (%d %d): [choice] terminal: %s children: %d\n", indent
, "", ref
.num
, ref
.gen
,
1221 terminal
? "Yes" : "No", numChildren
);
1225 void FormFieldChoice::updateSelection() {
1226 Object objV
, objI
, obj1
;
1229 if (edit
&& editedChoice
) {
1230 // This is an editable combo-box with user-entered text
1231 objV
.initString(editedChoice
->copy());
1233 const int numSelected
= getNumSelected();
1235 // Create /I array only if multiple selection is allowed (as per PDF spec)
1237 objI
.initArray(xref
);
1240 if (numSelected
== 0) {
1241 // No options are selected
1242 objV
.initString(new GooString(""));
1243 } else if (numSelected
== 1) {
1244 // Only one option is selected
1245 for (int i
= 0; i
< numChoices
; i
++) {
1246 if (choices
[i
].selected
) {
1248 objI
.arrayAdd(obj1
.initInt(i
));
1251 if (choices
[i
].exportVal
) {
1252 objV
.initString(choices
[i
].exportVal
->copy());
1253 } else if (choices
[i
].optionName
) {
1254 objV
.initString(choices
[i
].optionName
->copy());
1257 break; // We've just written the selected option. No need to keep on scanning
1261 // More than one option is selected
1262 objV
.initArray(xref
);
1263 for (int i
= 0; i
< numChoices
; i
++) {
1264 if (choices
[i
].selected
) {
1266 objI
.arrayAdd(obj1
.initInt(i
));
1269 if (choices
[i
].exportVal
) {
1270 objV
.arrayAdd(obj1
.initString(choices
[i
].exportVal
->copy()));
1271 } else if (choices
[i
].optionName
) {
1272 objV
.arrayAdd(obj1
.initString(choices
[i
].optionName
->copy()));
1279 obj
.getDict()->set("V", &objV
);
1280 obj
.getDict()->set("I", &objI
);
1281 xref
->setModifiedObject(&obj
, ref
);
1282 updateChildrenAppearance();
1285 void FormFieldChoice::unselectAll ()
1287 for (int i
= 0; i
< numChoices
; i
++) {
1288 choices
[i
].selected
= false;
1292 void FormFieldChoice::deselectAll () {
1293 delete editedChoice
;
1294 editedChoice
= NULL
;
1300 void FormFieldChoice::toggle (int i
)
1302 delete editedChoice
;
1303 editedChoice
= NULL
;
1305 choices
[i
].selected
= !choices
[i
].selected
;
1309 void FormFieldChoice::select (int i
)
1311 delete editedChoice
;
1312 editedChoice
= NULL
;
1317 choices
[i
].selected
= true;
1321 void FormFieldChoice::setEditChoice (GooString
* new_content
)
1323 delete editedChoice
;
1324 editedChoice
= NULL
;
1329 editedChoice
= new_content
->copy();
1331 //append the unicode marker <FE FF> if needed
1332 if (!editedChoice
->hasUnicodeMarker()) {
1333 editedChoice
->insert(0, 0xff);
1334 editedChoice
->insert(0, 0xfe);
1340 GooString
* FormFieldChoice::getEditChoice ()
1342 return editedChoice
;
1345 int FormFieldChoice::getNumSelected ()
1348 for(int i
=0; i
<numChoices
; i
++) {
1349 if (choices
[i
].selected
)
1355 GooString
*FormFieldChoice::getSelectedChoice() {
1356 if (edit
&& editedChoice
)
1357 return editedChoice
;
1359 for (int i
= 0; i
< numChoices
; i
++) {
1360 if (choices
[i
].optionName
&& choices
[i
].selected
)
1361 return choices
[i
].optionName
;
1367 //------------------------------------------------------------------------
1368 // FormFieldSignature
1369 //------------------------------------------------------------------------
1370 FormFieldSignature::FormFieldSignature(PDFDoc
*docA
, Object
*dict
, const Ref
& ref
, FormField
*parent
, std::set
<int> *usedParents
)
1371 : FormField(docA
, dict
, ref
, parent
, usedParents
, formSignature
)
1375 FormFieldSignature::~FormFieldSignature()
1381 void FormFieldSignature::print(int indent
)
1383 printf ("%*s- (%d %d): [signature] terminal: %s children: %d\n", indent
, "", ref
.num
, ref
.gen
,
1384 terminal
? "Yes" : "No", numChildren
);
1388 //------------------------------------------------------------------------
1390 //------------------------------------------------------------------------
1392 Form::Form(PDFDoc
*docA
, Object
* acroFormA
)
1397 xref
= doc
->getXRef();
1398 acroForm
= acroFormA
;
1403 quadding
= quaddingLeftJustified
;
1404 defaultAppearance
= NULL
;
1405 defaultResources
= NULL
;
1407 acroForm
->dictLookup("NeedAppearances", &obj1
);
1408 needAppearances
= (obj1
.isBool() && obj1
.getBool());
1411 if (acroForm
->dictLookup("DA", &obj1
)->isString())
1412 defaultAppearance
= obj1
.getString()->copy();
1415 if (acroForm
->dictLookup("Q", &obj1
)->isInt())
1416 quadding
= static_cast<VariableTextQuadding
>(obj1
.getInt());
1419 acroForm
->dictLookup("DR", &resDict
);
1420 if (resDict
.isDict()) {
1421 // At a minimum, this dictionary shall contain a Font entry
1422 if (resDict
.dictLookup("Font", &obj1
)->isDict())
1423 defaultResources
= new GfxResources(xref
, resDict
.getDict(), NULL
);
1426 if (!defaultResources
) {
1431 acroForm
->dictLookup("Fields", &obj1
);
1432 if (obj1
.isArray()) {
1433 Array
*array
= obj1
.getArray();
1436 for(int i
=0; i
<array
->getLength(); i
++) {
1438 array
->get(i
, &obj2
);
1439 array
->getNF(i
, &oref
);
1440 if (!oref
.isRef()) {
1441 error(errSyntaxWarning
, -1, "Direct object in rootFields");
1447 if (!obj2
.isDict()) {
1448 error(errSyntaxWarning
, -1, "Reference in Fields array to an invalid or non existent object");
1454 if (numFields
>= size
) {
1456 rootFields
= (FormField
**)greallocn(rootFields
,size
,sizeof(FormField
*));
1459 std::set
<int> usedParents
;
1460 rootFields
[numFields
++] = createFieldFromDict (&obj2
, doc
, oref
.getRef(), NULL
, &usedParents
);
1466 error(errSyntaxError
, -1, "Can't get Fields array\n");
1471 for (int i
= 0; i
< numFields
; i
++)
1472 rootFields
[i
]->printTree();
1478 for(i
= 0; i
< numFields
; ++i
)
1479 delete rootFields
[i
];
1481 delete defaultAppearance
;
1482 delete defaultResources
;
1486 // Look up an inheritable field dictionary entry.
1487 static Object
*fieldLookup(Dict
*field
, const char *key
, Object
*obj
, std::set
<int> *usedParents
) {
1492 if (!dict
->lookup(key
, obj
)->isNull()) {
1496 dict
->lookupNF("Parent", &parent
);
1497 if (parent
.isRef()) {
1498 const Ref ref
= parent
.getRef();
1499 if (usedParents
->find(ref
.num
) == usedParents
->end()) {
1500 usedParents
->insert(ref
.num
);
1503 parent
.fetch(dict
->getXRef(), &obj2
);
1504 if (obj2
.isDict()) {
1505 fieldLookup(obj2
.getDict(), key
, obj
, usedParents
);
1511 } else if (parent
.isDict()) {
1512 fieldLookup(parent
.getDict(), key
, obj
, usedParents
);
1520 Object
*Form::fieldLookup(Dict
*field
, const char *key
, Object
*obj
) {
1521 std::set
<int> usedParents
;
1522 return ::fieldLookup(field
, key
, obj
, &usedParents
);
1525 FormField
*Form::createFieldFromDict (Object
* obj
, PDFDoc
*docA
, const Ref
& pref
, FormField
*parent
, std::set
<int> *usedParents
)
1530 if (Form::fieldLookup(obj
->getDict (), "FT", &obj2
)->isName("Btn")) {
1531 field
= new FormFieldButton(docA
, obj
, pref
, parent
, usedParents
);
1532 } else if (obj2
.isName("Tx")) {
1533 field
= new FormFieldText(docA
, obj
, pref
, parent
, usedParents
);
1534 } else if (obj2
.isName("Ch")) {
1535 field
= new FormFieldChoice(docA
, obj
, pref
, parent
, usedParents
);
1536 } else if (obj2
.isName("Sig")) {
1537 field
= new FormFieldSignature(docA
, obj
, pref
, parent
, usedParents
);
1538 } else { //we don't have an FT entry => non-terminal field
1539 field
= new FormField(docA
, obj
, pref
, parent
, usedParents
);
1546 void Form::postWidgetsLoad()
1548 // We create the widget annotations associated to
1549 // every form widget here, because the AnnotWidget constructor
1550 // needs the form object that gets from the catalog. When constructing
1551 // a FormWidget the Catalog is still creating the form object
1552 for (int i
= 0; i
< numFields
; i
++) {
1553 rootFields
[i
]->fillChildrenSiblingsID();
1554 rootFields
[i
]->createWidgetAnnotations();
1558 FormWidget
* Form::findWidgetByRef (Ref aref
)
1560 for(int i
=0; i
<numFields
; i
++) {
1561 FormWidget
*result
= rootFields
[i
]->findWidgetByRef(aref
);
1562 if(result
) return result
;
1567 //------------------------------------------------------------------------
1569 //------------------------------------------------------------------------
1571 FormPageWidgets::FormPageWidgets (Annots
*annots
, unsigned int page
, Form
*form
)
1576 if (annots
&& annots
->getNumAnnots() > 0 && form
) {
1577 size
= annots
->getNumAnnots();
1578 widgets
= (FormWidget
**)greallocn(widgets
, size
, sizeof(FormWidget
*));
1580 /* For each entry in the page 'Annots' dict, try to find
1581 a matching form field */
1582 for (int i
= 0; i
< size
; ++i
) {
1583 Annot
*annot
= annots
->getAnnot(i
);
1585 if (annot
->getType() != Annot::typeWidget
)
1588 if (!annot
->getHasRef()) {
1589 /* Since all entry in a form field's kid dict needs to be
1590 indirect references, if this annot isn't indirect, it isn't
1591 related to a form field */
1595 Ref r
= annot
->getRef();
1597 /* Try to find a form field which either has this Annot in its Kids entry
1598 or is merged with this Annot */
1599 FormWidget
* tmp
= form
->findWidgetByRef(r
);
1601 // We've found a corresponding form field, link it
1602 tmp
->setID(FormWidget::encodeID(page
, numWidgets
));
1603 widgets
[numWidgets
++] = tmp
;
1609 FormPageWidgets::~FormPageWidgets()