| //======================================================================== |
| // |
| // Form.h |
| // |
| // This file is licensed under the GPLv2 or later |
| // |
| // Copyright 2006 Julien Rebetez <julienr@svn.gnome.org> |
| // Copyright 2007, 2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org> |
| // Copyright 2007-2010, 2012 Albert Astals Cid <aacid@kde.org> |
| // Copyright 2010 Mark Riedesel <mark@klowner.com> |
| // Copyright 2011 Pino Toscano <pino@kde.org> |
| // Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it> |
| // Copyright 2013 Adrian Johnson <ajohnson@redneon.com> |
| // |
| //======================================================================== |
| |
| #ifndef FORM_H |
| #define FORM_H |
| |
| #ifdef USE_GCC_PRAGMAS |
| #pragma interface |
| #endif |
| |
| #include "Object.h" |
| #include "Annot.h" |
| |
| #include <set> |
| |
| class GooString; |
| class Array; |
| class Dict; |
| class Annot; |
| class AnnotWidget; |
| class Annots; |
| class LinkAction; |
| class GfxResources; |
| class PDFDoc; |
| |
| enum FormFieldType { |
| formButton, |
| formText, |
| formChoice, |
| formSignature, |
| formUndef |
| }; |
| |
| enum FormButtonType { |
| formButtonCheck, |
| formButtonPush, |
| formButtonRadio |
| }; |
| |
| enum VariableTextQuadding { |
| quaddingLeftJustified, |
| quaddingCentered, |
| quaddingRightJustified |
| }; |
| |
| class Form; |
| class FormField; |
| class FormFieldButton; |
| class FormFieldText; |
| class FormFieldSignature; |
| class FormFieldChoice; |
| |
| //------------------------------------------------------------------------ |
| // FormWidget |
| // A FormWidget represents the graphical part of a field and is "attached" |
| // to a page. |
| //------------------------------------------------------------------------ |
| |
| class FormWidget { |
| public: |
| virtual ~FormWidget(); |
| |
| // Check if point is inside the field bounding rect |
| GBool inRect(double x, double y) const; |
| |
| // Get the field bounding rect |
| void getRect(double *x1, double *y1, double *x2, double *y2) const; |
| |
| unsigned getID () { return ID; } |
| void setID (unsigned int i) { ID=i; } |
| |
| FormField *getField () { return field; } |
| FormFieldType getType() { return type; } |
| |
| Object* getObj() { return &obj; } |
| Ref getRef() { return ref; } |
| |
| void setChildNum (unsigned i) { childNum = i; } |
| unsigned getChildNum () { return childNum; } |
| |
| double getFontSize() const; |
| |
| GooString *getPartialName() const; |
| GooString *getAlternateUiName() const; |
| GooString *getMappingName() const; |
| GooString *getFullyQualifiedName(); |
| |
| GBool isModified () const; |
| |
| bool isReadOnly() const; |
| |
| LinkAction *getActivationAction(); |
| LinkAction *getAdditionalAction(Annot::FormAdditionalActionsType type); |
| |
| // return the unique ID corresponding to pageNum/fieldNum |
| static int encodeID (unsigned pageNum, unsigned fieldNum); |
| // decode id and retrieve pageNum and fieldNum |
| static void decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum); |
| |
| void createWidgetAnnotation(); |
| AnnotWidget *getWidgetAnnotation() const { return widget; } |
| |
| virtual void updateWidgetAppearance() = 0; |
| |
| #ifdef DEBUG_FORMS |
| void print(int indent = 0); |
| #endif |
| |
| protected: |
| FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA); |
| |
| AnnotWidget *widget; |
| FormField* field; |
| FormFieldType type; |
| Object obj; |
| Ref ref; |
| PDFDoc *doc; |
| XRef *xref; |
| |
| //index of this field in the parent's child list |
| unsigned childNum; |
| |
| /* |
| Field ID is an (unsigned) integer, calculated as follow : |
| the first sizeof/2 bits are the field number, relative to the page |
| the last sizeof/2 bits are the page number |
| [page number | field number] |
| (encoding) id = (pageNum << 4*sizeof(unsigned)) + fieldNum; |
| (decoding) pageNum = id >> 4*sizeof(unsigned); fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned); |
| */ |
| unsigned ID; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormWidgetButton |
| //------------------------------------------------------------------------ |
| |
| class FormWidgetButton: public FormWidget { |
| public: |
| FormWidgetButton(PDFDoc *docA, Object *dict, unsigned num, Ref ref, FormField *p); |
| ~FormWidgetButton (); |
| |
| FormButtonType getButtonType() const; |
| |
| void setState (GBool state); |
| GBool getState (); |
| |
| char* getOnStr(); |
| void setAppearanceState(const char *state); |
| void updateWidgetAppearance(); |
| |
| protected: |
| GooString *onStr; |
| FormFieldButton *parent; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormWidgetText |
| //------------------------------------------------------------------------ |
| |
| class FormWidgetText: public FormWidget { |
| public: |
| FormWidgetText(PDFDoc *docA, Object *dict, unsigned num, Ref ref, FormField *p); |
| //return the field's content (UTF16BE) |
| GooString* getContent() ; |
| //return a copy of the field's content (UTF16BE) |
| GooString* getContentCopy(); |
| |
| //except a UTF16BE string |
| void setContent(GooString* new_content); |
| |
| void updateWidgetAppearance(); |
| |
| bool isMultiline () const; |
| bool isPassword () const; |
| bool isFileSelect () const; |
| bool noSpellCheck () const; |
| bool noScroll () const; |
| bool isComb () const; |
| bool isRichText () const; |
| int getMaxLen () const; |
| protected: |
| FormFieldText *parent; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormWidgetChoice |
| //------------------------------------------------------------------------ |
| |
| class FormWidgetChoice: public FormWidget { |
| public: |
| FormWidgetChoice(PDFDoc *docA, Object *dict, unsigned num, Ref ref, FormField *p); |
| ~FormWidgetChoice(); |
| |
| int getNumChoices(); |
| //return the display name of the i-th choice (UTF16BE) |
| GooString* getChoice(int i); |
| //select the i-th choice |
| void select (int i); |
| |
| //toggle selection of the i-th choice |
| void toggle (int i); |
| |
| //deselect everything |
| void deselectAll (); |
| |
| //except a UTF16BE string |
| //only work for editable combo box, set the user-entered text as the current choice |
| void setEditChoice(GooString* new_content); |
| |
| GooString* getEditChoice (); |
| |
| void updateWidgetAppearance(); |
| bool isSelected (int i); |
| |
| bool isCombo () const; |
| bool hasEdit () const; |
| bool isMultiSelect () const; |
| bool noSpellCheck () const; |
| bool commitOnSelChange () const; |
| bool isListBox () const; |
| protected: |
| bool _checkRange (int i); |
| FormFieldChoice *parent; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormWidgetSignature |
| //------------------------------------------------------------------------ |
| |
| class FormWidgetSignature: public FormWidget { |
| public: |
| FormWidgetSignature(PDFDoc *docA, Object *dict, unsigned num, Ref ref, FormField *p); |
| void updateWidgetAppearance(); |
| protected: |
| FormFieldSignature *parent; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormField |
| // A FormField implements the logical side of a field and is "attached" to |
| // the Catalog. This is an internal class and client applications should |
| // only interact with FormWidgets. |
| //------------------------------------------------------------------------ |
| |
| class FormField { |
| public: |
| FormField(PDFDoc *docA, Object *aobj, const Ref& aref, FormField *parent, std::set<int> *usedParents, FormFieldType t=formUndef); |
| |
| virtual ~FormField(); |
| |
| // Accessors. |
| FormFieldType getType() { return type; } |
| Object* getObj() { return &obj; } |
| Ref getRef() { return ref; } |
| |
| void setReadOnly (bool b) { readOnly = b; } |
| bool isReadOnly () const { return readOnly; } |
| |
| GooString* getDefaultAppearance() const { return defaultAppearance; } |
| GBool hasTextQuadding() const { return hasQuadding; } |
| VariableTextQuadding getTextQuadding() const { return quadding; } |
| |
| GooString *getPartialName() const { return partialName; } |
| GooString *getAlternateUiName() const { return alternateUiName; } |
| GooString *getMappingName() const { return mappingName; } |
| GooString *getFullyQualifiedName(); |
| |
| FormWidget* findWidgetByRef (Ref aref); |
| int getNumWidgets() { return terminal ? numChildren : 0; } |
| FormWidget *getWidget(int i) { return terminal ? widgets[i] : NULL; } |
| |
| // only implemented in FormFieldButton |
| virtual void fillChildrenSiblingsID (); |
| |
| void createWidgetAnnotations(); |
| |
| #ifdef DEBUG_FORMS |
| void printTree(int indent = 0); |
| virtual void print(int indent = 0); |
| #endif |
| |
| |
| protected: |
| void _createWidget (Object *obj, Ref aref); |
| void createChildren(std::set<int> *usedParents); |
| void updateChildrenAppearance(); |
| |
| FormFieldType type; // field type |
| Ref ref; |
| bool terminal; |
| Object obj; |
| PDFDoc *doc; |
| XRef *xref; |
| FormField **children; |
| FormField *parent; |
| int numChildren; |
| FormWidget **widgets; |
| bool readOnly; |
| |
| GooString *partialName; // T field |
| GooString *alternateUiName; // TU field |
| GooString *mappingName; // TM field |
| GooString *fullyQualifiedName; |
| |
| // Variable Text |
| GooString *defaultAppearance; |
| GBool hasQuadding; |
| VariableTextQuadding quadding; |
| |
| private: |
| FormField() {} |
| }; |
| |
| |
| //------------------------------------------------------------------------ |
| // FormFieldButton |
| //------------------------------------------------------------------------ |
| |
| class FormFieldButton: public FormField { |
| public: |
| FormFieldButton(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents); |
| |
| FormButtonType getButtonType () { return btype; } |
| |
| bool noToggleToOff () const { return noAllOff; } |
| |
| // returns gTrue if the state modification is accepted |
| GBool setState (char *state); |
| GBool getState(char *state); |
| |
| char *getAppearanceState() { return appearanceState.isName() ? appearanceState.getName() : NULL; } |
| |
| void fillChildrenSiblingsID (); |
| |
| void setNumSiblings (int num); |
| void setSibling (int i, FormFieldButton *id) { siblings[i] = id; } |
| |
| //For radio buttons, return the fields of the other radio buttons in the same group |
| FormFieldButton* getSibling (int i) const { return siblings[i]; } |
| int getNumSiblings () const { return numSiblings; } |
| |
| #ifdef DEBUG_FORMS |
| void print(int indent = 0); |
| #endif |
| |
| virtual ~FormFieldButton(); |
| protected: |
| void updateState(char *state); |
| |
| FormFieldButton** siblings; // IDs of dependent buttons (each button of a radio field has all the others buttons |
| // of the same field in this array) |
| int numSiblings; |
| |
| FormButtonType btype; |
| int size; |
| int active_child; //only used for combo box |
| bool noAllOff; |
| Object appearanceState; // V |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormFieldText |
| //------------------------------------------------------------------------ |
| |
| class FormFieldText: public FormField { |
| public: |
| FormFieldText(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents); |
| |
| GooString* getContent () { return content; } |
| GooString* getContentCopy (); |
| void setContentCopy (GooString* new_content); |
| virtual ~FormFieldText(); |
| |
| bool isMultiline () const { return multiline; } |
| bool isPassword () const { return password; } |
| bool isFileSelect () const { return fileSelect; } |
| bool noSpellCheck () const { return doNotSpellCheck; } |
| bool noScroll () const { return doNotScroll; } |
| bool isComb () const { return comb; } |
| bool isRichText () const { return richText; } |
| |
| int getMaxLen () const { return maxLen; } |
| |
| #ifdef DEBUG_FORMS |
| void print(int indent = 0); |
| #endif |
| protected: |
| GooString* content; |
| bool multiline; |
| bool password; |
| bool fileSelect; |
| bool doNotSpellCheck; |
| bool doNotScroll; |
| bool comb; |
| bool richText; |
| int maxLen; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormFieldChoice |
| //------------------------------------------------------------------------ |
| |
| class FormFieldChoice: public FormField { |
| public: |
| FormFieldChoice(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents); |
| |
| virtual ~FormFieldChoice(); |
| |
| int getNumChoices() { return numChoices; } |
| GooString* getChoice(int i) { return choices ? choices[i].optionName : NULL; } |
| GooString* getExportVal (int i) { return choices ? choices[i].exportVal : NULL; } |
| // For multi-select choices it returns the first one |
| GooString* getSelectedChoice(); |
| |
| //select the i-th choice |
| void select (int i); |
| |
| //toggle selection of the i-th choice |
| void toggle (int i); |
| |
| //deselect everything |
| void deselectAll (); |
| |
| //only work for editable combo box, set the user-entered text as the current choice |
| void setEditChoice(GooString* new_content); |
| |
| GooString* getEditChoice (); |
| |
| bool isSelected (int i) { return choices[i].selected; } |
| |
| int getNumSelected (); |
| |
| bool isCombo () const { return combo; } |
| bool hasEdit () const { return edit; } |
| bool isMultiSelect () const { return multiselect; } |
| bool noSpellCheck () const { return doNotSpellCheck; } |
| bool commitOnSelChange () const { return doCommitOnSelChange; } |
| bool isListBox () const { return !combo; } |
| |
| int getTopIndex() const { return topIdx; } |
| |
| #ifdef DEBUG_FORMS |
| void print(int indent = 0); |
| #endif |
| |
| protected: |
| void unselectAll(); |
| void updateSelection(); |
| |
| bool combo; |
| bool edit; |
| bool multiselect; |
| bool doNotSpellCheck; |
| bool doCommitOnSelChange; |
| |
| struct ChoiceOpt { |
| GooString* exportVal; //the export value ("internal" name) |
| GooString* optionName; //displayed name |
| bool selected; //if this choice is selected |
| }; |
| |
| int numChoices; |
| ChoiceOpt* choices; |
| GooString* editedChoice; |
| int topIdx; // TI |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormFieldSignature |
| //------------------------------------------------------------------------ |
| |
| class FormFieldSignature: public FormField { |
| public: |
| FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents); |
| |
| virtual ~FormFieldSignature(); |
| |
| #ifdef DEBUG_FORMS |
| void print(int indent = 0); |
| #endif |
| }; |
| |
| //------------------------------------------------------------------------ |
| // Form |
| // This class handle the document-wide part of Form (things in the acroForm |
| // Catalog entry). |
| //------------------------------------------------------------------------ |
| |
| class Form { |
| public: |
| Form(PDFDoc *docA, Object* acroForm); |
| |
| ~Form(); |
| |
| // Look up an inheritable field dictionary entry. |
| static Object *fieldLookup(Dict *field, const char *key, Object *obj); |
| |
| /* Creates a new Field of the type specified in obj's dict. |
| used in Form::Form and FormField::FormField */ |
| static FormField *createFieldFromDict (Object* obj, PDFDoc *docA, const Ref& aref, FormField *parent, std::set<int> *usedParents); |
| |
| Object *getObj () const { return acroForm; } |
| GBool getNeedAppearances () const { return needAppearances; } |
| int getNumFields() const { return numFields; } |
| FormField* getRootField(int i) const { return rootFields[i]; } |
| GooString* getDefaultAppearance() const { return defaultAppearance; } |
| VariableTextQuadding getTextQuadding() const { return quadding; } |
| GfxResources* getDefaultResources() const { return defaultResources; } |
| Object* getDefaultResourcesObj() { return &resDict; } |
| |
| FormWidget* findWidgetByRef (Ref aref); |
| |
| void postWidgetsLoad(); |
| private: |
| FormField** rootFields; |
| int numFields; |
| int size; |
| PDFDoc *doc; |
| XRef* xref; |
| Object *acroForm; |
| GBool needAppearances; |
| GfxResources *defaultResources; |
| Object resDict; |
| |
| // Variable Text |
| GooString *defaultAppearance; |
| VariableTextQuadding quadding; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // FormPageWidgets |
| //------------------------------------------------------------------------ |
| |
| class FormPageWidgets { |
| public: |
| FormPageWidgets (Annots* annots, unsigned int page, Form *form); |
| ~FormPageWidgets(); |
| |
| int getNumWidgets() const { return numWidgets; } |
| FormWidget* getWidget(int i) const { return widgets[i]; } |
| |
| private: |
| FormWidget** widgets; |
| int numWidgets; |
| int size; |
| }; |
| |
| #endif |
| |