[poppler] poppler/Form.cc poppler/Form.h
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Tue Mar 8 11:18:16 PST 2011
poppler/Form.cc | 227 +++++++++++++++++++++-----------------------------------
poppler/Form.h | 21 +----
2 files changed, 91 insertions(+), 157 deletions(-)
New commits:
commit 14d145371e86ccb92f09b1ca750ced52171b2885
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Tue Mar 8 20:14:57 2011 +0100
forms: Remove loadDefaults method
Moving the code to initialize form field stuff to form field
constructors and widget stuff to form widget constructors. Clean up an
simplify the code.
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 908b6fa..4698124 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -67,7 +67,6 @@ FormWidget::FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormFi
ref = aref;
double t;
ID = 0;
- defaultsLoaded = gFalse;
fontSize = 0.0;
modified = gFalse;
childNum = num;
@@ -256,9 +255,36 @@ FormWidgetButton::FormWidgetButton (XRef *xrefA, Object *aobj, unsigned num, Ref
type = formButton;
parent = static_cast<FormFieldButton*>(field);
onStr = NULL;
- state = gFalse;
siblingsID = NULL;
numSiblingsID = 0;
+
+ Object obj1, obj2;
+
+ // Find the name of the ON state in the AP dictionnary
+ // The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
+ // The "on" state may be stored under any other name
+ if (obj.dictLookup("AP", &obj1)->isDict()) {
+ if (obj1.dictLookup("N", &obj2)->isDict()) {
+ for (int i = 0; i < obj2.dictGetLength(); i++) {
+ char *key = obj2.dictGetKey(i);
+ if (strcmp (key, "Off") != 0) {
+ onStr = new GooString (key);
+ break;
+ }
+ }
+ }
+ obj2.free();
+ }
+ obj1.free();
+}
+
+char *FormWidgetButton::getOnStr() {
+ if (onStr)
+ return onStr->getCString();
+
+ // 12.7.4.2.3 Check Boxes
+ // Yes should be used as the name for the on state
+ return parent->getButtonType() == formButtonCheck ? (char *)"Yes" : NULL;
}
FormWidgetButton::~FormWidgetButton ()
@@ -273,108 +299,32 @@ FormButtonType FormWidgetButton::getButtonType () const
return parent->getButtonType ();
}
-void FormWidgetButton::setState (GBool astate, GBool calledByParent)
-{
- //pushButtons don't have state
- if (parent->getButtonType() == formButtonPush)
- return;
- //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
- if (!calledByParent) { //avoid infinite recursion
- modified = gTrue;
- if (!parent->setState(childNum, astate)) {
- return;
- }
- }
- state = astate;
-
- //update appearance
- char *offStr = "Off";
- Object obj1;
- obj1.initName(state ? onStr->getCString() : offStr);
- updateField ("V", &obj1);
+void FormWidgetButton::setAppearanceState(char *state) {
+ modified = gTrue;
- obj1.initName(state ? onStr->getCString() : offStr);
- //modify the Appearance State entry as well
+ Object obj1;
+ obj1.initName(state);
obj.getDict()->set("AS", &obj1);
- //notify the xref about the update
xref->setModifiedObject(&obj, ref);
}
-void FormWidgetButton::loadDefaults ()
+void FormWidgetButton::setState (GBool astate, GBool calledByParent)
{
- if (defaultsLoaded)
- return;
-
- defaultsLoaded = gTrue;
-
- Dict *dict = obj.getDict();
- Object obj1;
-
//pushButtons don't have state
- if (parent->getButtonType() != formButtonPush ){
- //find the name of the state in the AP dictionnary (/Yes, /Off)
- //The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
- //The "on" state may be stored under any other name
- if (dict->lookup("AP", &obj1)->isDict()) {
- Dict *tmpDict = obj1.getDict();
- int length = tmpDict->getLength();
- for(int i=0; i<length; i++) {
- Object obj2;
- tmpDict->getVal(i, &obj2);
- if (obj2.isDict()) {
- Dict *tmpDict2 = obj2.getDict();
- int length2 = tmpDict2->getLength();
- for(int j=0; j<length2; j++) {
- Object obj3;
- tmpDict2->getVal(j, &obj3);
- char *key = tmpDict2->getKey(j);
- if(strcmp(key, "Off")) { //if we don't have Off, we have the name of the "on" state
- onStr = new GooString (key);
- }
- obj3.free();
- if (onStr)
- break;
- }
- } else if (obj2.isStream()) {
- // TODO do something with str and obj3
- Stream *str = obj2.getStream();
- Dict *tmpDict2 = str->getDict();
- Object obj3;
- tmpDict2->lookup("Length", &obj3);
- onStr = new GooString ("D");
- obj3.free();
- }
- obj2.free();
- if (onStr)
- break;
- }
- }
- obj1.free();
+ if (parent->getButtonType() == formButtonPush)
+ return;
- //We didn't found the "on" state for the button
- if (!onStr) {
- error(-1, "FormWidgetButton:: unable to find the on state for the button\n");
- onStr = new GooString(""); // TODO is this the best solution?
- }
- }
+ // Silently return if can't set ON state
+ if (astate && !onStr)
+ return;
- if (Form::fieldLookup(dict, "V", &obj1)->isName()) {
- Object obj2;
- if (dict->lookup("AS", &obj2)->isName(obj1.getName())) {
- if (strcmp (obj1.getName(), "Off") != 0) {
- setState(gTrue);
- }
- }
- obj2.free();
- } else if (obj1.isArray()) { //handle the case where we have multiple choices
- error(-1, "FormWidgetButton:: multiple choice isn't supported yet\n");
- }
- obj1.free();
+ parent->setState(astate ? onStr->getCString() : (char *)"Off");
+ // Parent will call setAppearanceState()
}
GBool FormWidgetButton::getState ()
{
- return state;
+ return (onStr && parent->getAppearanceState() && strcmp(parent->getAppearanceState(), onStr->getCString()) == 0);
}
void FormWidgetButton::setNumSiblingsID (int i)
@@ -391,14 +341,6 @@ FormWidgetText::FormWidgetText (XRef *xrefA, Object *aobj, unsigned num, Ref ref
parent = static_cast<FormFieldText*>(field);
}
-void FormWidgetText::loadDefaults ()
-{
- if (defaultsLoaded)
- return;
-
- defaultsLoaded = gTrue;
-}
-
GooString* FormWidgetText::getContent ()
{
return parent->getContent();
@@ -467,14 +409,6 @@ FormWidgetChoice::FormWidgetChoice(XRef *xrefA, Object *aobj, unsigned num, Ref
parent = static_cast<FormFieldChoice*>(field);
}
-void FormWidgetChoice::loadDefaults ()
-{
- if (defaultsLoaded)
- return;
-
- defaultsLoaded = gTrue;
-}
-
FormWidgetChoice::~FormWidgetChoice()
{
}
@@ -658,7 +592,7 @@ FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, std::set<int> *
children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
obj3.free();
- children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef(), &usedParentsAux);
+ children[numChildren-1] = Form::createFieldFromDict (&obj2, xref, childRef.getRef(), &usedParentsAux);
}
// 1 - we will handle 'collapsed' fields (field + annot in the same dict)
// as if the annot was in the Kids array of the field
@@ -679,10 +613,10 @@ FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, std::set<int> *
// As said in 1, if this is a 'collapsed' field, behave like if we had a
// child annot
if (dict->lookup("Subtype", &obj1)->isName()) {
- _createWidget(aobj, ref);
+ _createWidget(&obj, ref);
}
obj1.free();
-
+
//flags
if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
int flags = obj1.getInt();
@@ -728,19 +662,6 @@ FormField::~FormField()
delete defaultAppearance;
}
-void FormField::loadChildrenDefaults ()
-{
- if(!terminal) {
- for(int i=0; i<numChildren; i++) {
- children[i]->loadChildrenDefaults();
- }
- } else {
- for (int i=0; i<numChildren; i++) {
- widgets[i]->loadDefaults();
- }
- }
-}
-
void FormField::fillChildrenSiblingsID()
{
if(terminal) return;
@@ -845,7 +766,7 @@ void FormFieldButton::fillChildrenSiblingsID()
}
}
-GBool FormFieldButton::setState (int num, GBool s)
+GBool FormFieldButton::setState(char *state)
{
if (readOnly) {
error(-1, "FormFieldButton::setState called on a readOnly field\n");
@@ -855,28 +776,54 @@ GBool FormFieldButton::setState (int num, GBool s)
// A check button could behave as a radio button
// when it's in a set of more than 1 buttons
if (btype == formButtonRadio || btype == formButtonCheck) {
- if (!s && noAllOff)
+ GBool isOn = strcmp(state, "Off") != 0;
+
+ if (!isOn && noAllOff)
return gFalse; //don't allow to set all radio to off
- if (s == gTrue) {
- active_child = num;
- for(int i=0; i<numChildren; i++) {
- if (i==active_child) continue;
- static_cast<FormWidgetButton*>(widgets[i])->setState(gFalse, gTrue);
- }
+ char *current = getAppearanceState();
+
+ if (isOn) {
+ char *current = getAppearanceState();
+ GBool currentFound = gFalse, newFound = gFalse;
+
+ for (int i = 0; i < numChildren; i++) {
+ FormWidgetButton *widget = static_cast<FormWidgetButton*>(widgets[i]);
+
+ if (!widget->getOnStr())
+ continue;
+
+ char *onStr = widget->getOnStr();
+ if (current && strcmp(current, onStr) == 0) {
+ widget->setAppearanceState("Off");
+ currentFound = gTrue;
+ }
- //The parent field's V entry holds a name object corresponding to the ap-
- //pearance state of whichever child field is currently in the on state
- if (active_child >= 0) {
- FormWidgetButton* actChild = static_cast<FormWidgetButton*>(widgets[active_child]);
- if (actChild->getOnStr())
- updateState(actChild->getOnStr()->getCString());
+ if (strcmp(state, onStr) == 0) {
+ widget->setAppearanceState(state);
+ newFound = gTrue;
+ }
+
+ if (currentFound && newFound)
+ break;
}
} else {
- active_child = -1;
- updateState("Off");
+ for (int i = 0; i < numChildren; i++) {
+ FormWidgetButton *widget = static_cast<FormWidgetButton*>(widgets[i]);
+
+ if (!widget->getOnStr())
+ continue;
+
+ char *onStr = widget->getOnStr();
+ if (current && strcmp(current, onStr) == 0) {
+ widget->setAppearanceState("Off");
+ break;
+ }
+ }
}
+ updateState(state);
}
+
return gTrue;
}
@@ -1370,8 +1317,6 @@ FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref,
field = new FormField(xrefA, obj, pref, usedParents);
}
obj2.free();
-
- field->loadChildrenDefaults();
return field;
}
diff --git a/poppler/Form.h b/poppler/Form.h
index 8d25e2c..74539ca 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -69,9 +69,6 @@ class FormWidget {
public:
virtual ~FormWidget();
- // see the description of FormField::LoadChildrenDefaults
- virtual void loadDefaults () {}
-
// Check if point is inside the field bounding rect
GBool inRect(double x, double y)
{ return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
@@ -121,7 +118,6 @@ protected:
Object obj;
Ref ref;
XRef *xref;
- GBool defaultsLoaded;
GBool modified;
GooString *partialName; // T field
GooString *alternateUiName; // TU field
@@ -161,9 +157,8 @@ public:
void setState (GBool state, GBool calledByParent=gFalse);
GBool getState ();
- GooString* getOnStr() { return onStr; }
-
- void loadDefaults();
+ char* getOnStr();
+ void setAppearanceState(char *state);
void setNumSiblingsID (int i);
void setSiblingsID (int i, unsigned id) { siblingsID[i] = id; }
@@ -178,7 +173,6 @@ protected:
int numSiblingsID;
GooString *onStr;
FormFieldButton *parent;
- GBool state;
};
//------------------------------------------------------------------------
@@ -196,8 +190,6 @@ public:
//except a UTF16BE string
void setContent(GooString* new_content);
- void loadDefaults ();
-
bool isMultiline () const;
bool isPassword () const;
bool isFileSelect () const;
@@ -219,7 +211,6 @@ public:
FormWidgetChoice(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormField *p);
~FormWidgetChoice();
- void loadDefaults ();
int getNumChoices();
//return the display name of the i-th choice (UTF16BE)
GooString* getChoice(int i);
@@ -288,9 +279,6 @@ public:
VariableTextQuadding getTextQuadding() const { return quadding; }
FormWidget* findWidgetByRef (Ref aref);
- // Since while loading their defaults, children may call parents methods, it's better
- // to do that when parents are completly constructed
- void loadChildrenDefaults();
// only implemented in FormFieldButton
virtual void fillChildrenSiblingsID ();
@@ -298,6 +286,7 @@ public:
protected:
void _createWidget (Object *obj, Ref aref);
+ void createChildren(std::set<int> *usedParents);
FormFieldType type; // field type
Ref ref;
@@ -332,10 +321,10 @@ public:
bool noToggleToOff () const { return noAllOff; }
// returns gTrue if the state modification is accepted
- GBool setState (int num, GBool s);
+ GBool setState (char *state);
char *getAppearanceState() { return appearanceState.isName() ? appearanceState.getName() : NULL; }
-
+
void fillChildrenSiblingsID ();
virtual ~FormFieldButton();
More information about the poppler
mailing list