//======================================================================== // // Form.h // // This file is licensed under the GPLv2 or later // // Copyright 2006 Julien Rebetez // Copyright 2007, 2008, 2011 Carlos Garcia Campos // Copyright 2007-2010 Albert Astals Cid // Copyright 2010 Mark Riedesel // Copyright 2011 Pino Toscano // //======================================================================== #ifndef FORM_H #define FORM_H #ifdef USE_GCC_PRAGMAS #pragma interface #endif #include "Object.h" #include class GooString; class Array; class Dict; class Annot; class AnnotWidget; class Annots; class Catalog; class LinkAction; class GfxResources; 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(); // 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(Catalog *catalog); AnnotWidget *getWidgetAnnotation() const { return widget; } #ifdef DEBUG_FORMS void print(int indent = 0); #endif protected: FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA); AnnotWidget *widget; FormField* field; FormFieldType type; Object obj; Ref ref; 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(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); ~FormWidgetButton (); FormButtonType getButtonType() const; void setState (GBool state); GBool getState (); char* getOnStr(); void setAppearanceState(char *state); void setNumSiblingsID (int i); void setSiblingsID (int i, unsigned id) { siblingsID[i] = id; } //For radio buttons, return the IDs of the other radio buttons in the same group unsigned* getSiblingsID () const { return siblingsID; } int getNumSiblingsID () const { return numSiblingsID; } protected: unsigned* siblingsID; // IDs of dependent buttons (each button of a radio field has all the others buttons // of the same field in this array) int numSiblingsID; GooString *onStr; FormFieldButton *parent; }; //------------------------------------------------------------------------ // FormWidgetText //------------------------------------------------------------------------ class FormWidgetText: public FormWidget { public: FormWidgetText(XRef *xrefA, 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); 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(XRef *xrefA, 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 (); 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(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p); 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(XRef* xrefa, Object *aobj, const Ref& aref, FormField *parent, std::set *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; } GBool isModified () const; 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); FormWidget *getWidget(int i) { return terminal ? widgets[i] : NULL; } // only implemented in FormFieldButton virtual void fillChildrenSiblingsID (); void createWidgetAnnotations(Catalog *catalog); #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 *usedParents); FormFieldType type; // field type Ref ref; bool terminal; Object obj; XRef *xref; FormField **children; FormField *parent; int numChildren; FormWidget **widgets; bool readOnly; GBool modified; 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(XRef *xrefA, Object *dict, const Ref& ref, FormField *parent, std::set *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 (); #ifdef DEBUG_FORMS void print(int indent = 0); #endif virtual ~FormFieldButton(); protected: void updateState(char *state); FormButtonType btype; int size; int active_child; //only used for combo box bool noAllOff; Object appearanceState; // V }; //------------------------------------------------------------------------ // FormFieldText //------------------------------------------------------------------------ class FormFieldText: public FormField { public: FormFieldText(XRef *xrefA, Object *dict, const Ref& ref, FormField *parent, std::set *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(XRef *xrefA, Object *aobj, const Ref& ref, FormField *parent, std::set *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(XRef *xrefA, Object *dict, const Ref& ref, FormField *parent, std::set *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(XRef *xrefA, Object* acroForm); ~Form(); // Look up an inheritable field dictionary entry. static Object *fieldLookup(Dict *field, 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, XRef *xref, const Ref& aref, FormField *parent, std::set *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(Catalog *catalog); private: FormField** rootFields; int numFields; int size; 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