//========================================================================
//
// Form.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
// Copyright 2007-2012, 2015-2017 Albert Astals Cid <aacid@kde.org>
// Copyright 2007-2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright 2007, 2013, 2016 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
// Copyright 2008, 2011 Pino Toscano <pino@kde.org>
// Copyright 2008 Michael Vrable <mvrable@cs.ucsd.edu>
// Copyright 2009 Matthias Drochner <M.Drochner@fz-juelich.de>
// Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
// Copyright 2010, 2012 Mark Riedesel <mark@klowner.com>
// Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
//
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include <set>
#include <stddef.h>
#include <string.h>
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "Error.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Gfx.h"
#include "Form.h"
#include "PDFDoc.h"
#include "DateInfo.h"
#ifdef ENABLE_NSS3
#include "SignatureHandler.h"
#endif
#include "SignatureInfo.h"
#include "XRef.h"
#include "PDFDocEncoding.h"
#include "Annot.h"
#include "Link.h"

//return a newly allocated char* containing an UTF16BE string of size length
char* pdfDocEncodingToUTF16 (GooString* orig, int* length)
{
  //double size, a unicode char takes 2 char, add 2 for the unicode marker
  *length = 2+2*orig->getLength();
  char *result = new char[(*length)];
  char *cstring = orig->getCString();
  //unicode marker
  result[0] = 0xfe;
  result[1] = 0xff;
  //convert to utf16
  for(int i=2,j=0; i<(*length); i+=2,j++) {
    Unicode u = pdfDocEncoding[(unsigned int)((unsigned char)cstring[j])]&0xffff;
    result[i] = (u >> 8) & 0xff;
    result[i+1] = u & 0xff;
  }
  return result;
}

static GooString *convertToUtf16(GooString *pdfDocEncodingString)
{
  int tmp_length;
  char* tmp_str = pdfDocEncodingToUTF16(pdfDocEncodingString, &tmp_length);
  delete pdfDocEncodingString;
  pdfDocEncodingString = new GooString(tmp_str, tmp_length);
  delete [] tmp_str;
  return pdfDocEncodingString;
}


FormWidget::FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA)
{
  ref = aref;
  ID = 0;
  childNum = num;
  doc = docA;
  xref = doc->getXRef();
  aobj->copy(&obj);
  type = formUndef;
  field = fieldA;
  widget = NULL;
}

FormWidget::~FormWidget()
{
  if (widget)
    widget->decRefCnt();
  obj.free ();
}

#ifdef DEBUG_FORMS
void FormWidget::print(int indent) {
  printf ("%*s+ (%d %d): [widget]\n", indent, "", ref.num, ref.gen);
}
#endif

void FormWidget::createWidgetAnnotation() {
  if (widget)
    return;

  Object obj1;
  obj1.initRef(ref.num, ref.gen);
  widget = new AnnotWidget(doc, obj.getDict(), &obj1, field);
  obj1.free();
}

GBool FormWidget::inRect(double x, double y) const {
  return widget ? widget->inRect(x, y) : gFalse;
}

void FormWidget::getRect(double *x1, double *y1, double *x2, double *y2) const {
  if (widget)
    widget->getRect(x1, y1, x2, y2);
}

double FormWidget::getFontSize() const {
  return widget ? widget->getFontSize() : 0.;
}

bool FormWidget::isReadOnly() const
{
  return field->isReadOnly();
}

int FormWidget::encodeID (unsigned pageNum, unsigned fieldNum)
{
  return (pageNum << 4*sizeof(unsigned)) + fieldNum;
}

void FormWidget::decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum)
{
  *pageNum = id >> 4*sizeof(unsigned);
  *fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
}

GooString *FormWidget::getPartialName() const {
  return field->getPartialName();
}

void FormWidget::setPartialName(const GooString &name)
{
  field->setPartialName(name);
}

GooString *FormWidget::getAlternateUiName() const {
  return field->getAlternateUiName();
}

GooString *FormWidget::getMappingName() const {
  return field->getMappingName();
}

GooString *FormWidget::getFullyQualifiedName() {
  return field->getFullyQualifiedName();
}

LinkAction *FormWidget::getActivationAction() {
  return widget ? widget->getAction() : NULL;
}

LinkAction *FormWidget::getAdditionalAction(Annot::FormAdditionalActionsType type) {
  return widget ? widget->getFormAdditionalAction(type) : NULL;
}

FormWidgetButton::FormWidgetButton (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formButton;
  onStr = NULL;

  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 ()
{
  delete onStr;
}

FormButtonType FormWidgetButton::getButtonType () const
{
  return parent()->getButtonType ();
}

void FormWidgetButton::setAppearanceState(const char *state) {
  if (!widget)
    return;
  widget->setAppearanceState(state);
}

void FormWidgetButton::updateWidgetAppearance()
{
  // The appearance stream must NOT be regenerated for this widget type
}

void FormWidgetButton::setState (GBool astate)
{
  //pushButtons don't have state
  if (parent()->getButtonType() == formButtonPush)
    return;

  // Silently return if can't set ON state
  if (astate && !onStr)
    return;

  parent()->setState(astate ? onStr->getCString() : (char *)"Off");
  // Parent will call setAppearanceState()
}

GBool FormWidgetButton::getState ()
{
  return onStr ? parent()->getState(onStr->getCString()) : gFalse;
}

FormFieldButton *FormWidgetButton::parent() const
{
  return static_cast<FormFieldButton*>(field);
}


FormWidgetText::FormWidgetText (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formText;
}

GooString* FormWidgetText::getContent ()
{
  return parent()->getContent();
}

GooString* FormWidgetText::getContentCopy ()
{
  return parent()->getContentCopy();
}

void FormWidgetText::updateWidgetAppearance()
{
  if (widget)
    widget->updateAppearanceStream();
}

bool FormWidgetText::isMultiline () const 
{ 
  return parent()->isMultiline();
}

bool FormWidgetText::isPassword () const 
{ 
  return parent()->isPassword();
}

bool FormWidgetText::isFileSelect () const 
{ 
  return parent()->isFileSelect();
}

bool FormWidgetText::noSpellCheck () const 
{ 
  return parent()->noSpellCheck();
}

bool FormWidgetText::noScroll () const 
{ 
  return parent()->noScroll();
}

bool FormWidgetText::isComb () const 
{ 
  return parent()->isComb();
}

bool FormWidgetText::isRichText () const 
{ 
  return parent()->isRichText();
}

int FormWidgetText::getMaxLen () const
{
  return parent()->getMaxLen ();
}

void FormWidgetText::setContent(GooString* new_content)
{
  parent()->setContentCopy(new_content);
}

FormFieldText *FormWidgetText::parent() const
{
  return static_cast<FormFieldText*>(field);
}

FormWidgetChoice::FormWidgetChoice(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formChoice;
}

FormWidgetChoice::~FormWidgetChoice()
{
}

bool FormWidgetChoice::_checkRange (int i)
{
  if (i < 0 || i >= parent()->getNumChoices()) {
    error(errInternal, -1, "FormWidgetChoice::_checkRange i out of range : {0:d}", i);
    return false;
  } 
  return true;
}

void FormWidgetChoice::select (int i)
{
  if (!_checkRange(i)) return;
  parent()->select(i);
}

void FormWidgetChoice::toggle (int i)
{
  if (!_checkRange(i)) return;
  parent()->toggle(i);
}

void FormWidgetChoice::deselectAll ()
{
  parent()->deselectAll();
}

GooString* FormWidgetChoice::getEditChoice ()
{
  if (!hasEdit()) {
    error(errInternal, -1, "FormFieldChoice::getEditChoice called on a non-editable choice\n");
    return NULL;
  }
  return parent()->getEditChoice();
}

void FormWidgetChoice::updateWidgetAppearance()
{
  if (widget)
    widget->updateAppearanceStream();
}

bool FormWidgetChoice::isSelected (int i)
{
  if (!_checkRange(i)) return false;
  return parent()->isSelected(i);
}

void FormWidgetChoice::setEditChoice (GooString* new_content)
{
  if (!hasEdit()) {
    error(errInternal, -1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
    return;
  }

  parent()->setEditChoice(new_content);
}

int FormWidgetChoice::getNumChoices() 
{ 
  return parent()->getNumChoices();
}

GooString* FormWidgetChoice::getChoice(int i) 
{ 
  return parent()->getChoice(i);
}

bool FormWidgetChoice::isCombo () const 
{ 
  return parent()->isCombo();
}

bool FormWidgetChoice::hasEdit () const 
{ 
  return parent()->hasEdit();
}

bool FormWidgetChoice::isMultiSelect () const 
{ 
  return parent()->isMultiSelect();
}

bool FormWidgetChoice::noSpellCheck () const 
{ 
  return parent()->noSpellCheck();
}

bool FormWidgetChoice::commitOnSelChange () const 
{ 
  return parent()->commitOnSelChange();
}

bool FormWidgetChoice::isListBox () const
{
  return parent()->isListBox();
}

FormFieldChoice *FormWidgetChoice::parent() const
{
  return static_cast<FormFieldChoice*>(field);
}

FormWidgetSignature::FormWidgetSignature(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formSignature;
}

SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation)
{
  return static_cast<FormFieldSignature*>(field)->validateSignature(doVerifyCert, forceRevalidation);
}

void FormWidgetSignature::updateWidgetAppearance()
{
  // Unimplemented
}


//========================================================================
// FormField
//========================================================================

FormField::FormField(PDFDoc *docA, Object *aobj, const Ref& aref, FormField *parentA, std::set<int> *usedParents, FormFieldType ty)
{
  doc = docA;
  xref = doc->getXRef();
  aobj->copy(&obj);
  Dict* dict = obj.getDict();
  ref.num = ref.gen = 0;
  type = ty;
  parent = parentA;
  numChildren = 0;
  children = NULL;
  terminal = false;
  widgets = NULL;
  readOnly = false;
  defaultAppearance = NULL;
  fullyQualifiedName = NULL;
  quadding = quaddingLeftJustified;
  hasQuadding = gFalse;

  ref = aref;

  Object obj1;
  //childs
  if (dict->lookup("Kids", &obj1)->isArray()) {
    // Load children
    for (int i = 0 ; i < obj1.arrayGetLength(); i++) {
      Object childRef, childObj;

      if (!obj1.arrayGetNF(i, &childRef)->isRef()) {
        error (errSyntaxError, -1, "Invalid form field renference");
        childRef.free();
        continue;
      }
      if (!obj1.arrayGet(i, &childObj)->isDict()) {
        error (errSyntaxError, -1, "Form field child is not a dictionary");
        childObj.free();
        childRef.free();
        continue;
      }

      const Ref ref = childRef.getRef();
      if (usedParents->find(ref.num) == usedParents->end()) {
        Object obj2, obj3;
        // Field child: it could be a form field or a widget or composed dict
        if (childObj.dictLookupNF("Parent", &obj2)->isRef() || childObj.dictLookup("Parent", &obj3)->isDict()) {
          // Child is a form field or composed dict
          // We create the field, if it's composed
          // it will create the widget as a child
          std::set<int> usedParentsAux = *usedParents;
          usedParentsAux.insert(ref.num);
          obj2.free();
          obj3.free();

          if (terminal) {
            error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
            childObj.free();
            childRef.free();
            continue;
          }

          numChildren++;
          children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
          children[numChildren - 1] = Form::createFieldFromDict(&childObj, doc, ref, this, &usedParentsAux);
        } else if (childObj.dictLookup("Subtype", &obj2)->isName("Widget")) {
          // Child is a widget annotation
          if (!terminal && numChildren > 0) {
            error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
            obj2.free();
            obj3.free();
            childObj.free();
            childRef.free();
            continue;
          }
          _createWidget(&childObj, ref);
        }
        obj2.free();
        obj3.free();
      }
      childObj.free();
      childRef.free();
    }
  } else {
    // No children, if it's a composed dict, create the child widget
    obj1.free();
    if (dict->lookup("Subtype", &obj1)->isName("Widget"))
      _createWidget(&obj, ref);
  }
  obj1.free();

  //flags
  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x1) { // 1 -> ReadOnly
      readOnly = true;
    }
    if (flags & 0x2) { // 2 -> Required
      //TODO
    }
    if (flags & 0x4) { // 3 -> NoExport
      //TODO
    }
  }
  obj1.free();

  // Variable Text
  if (Form::fieldLookup(dict, "DA", &obj1)->isString())
    defaultAppearance = obj1.getString()->copy();
  obj1.free();

  if (Form::fieldLookup(dict, "Q", &obj1)->isInt()) {
    quadding = static_cast<VariableTextQuadding>(obj1.getInt());
    hasQuadding = gTrue;
  }
  obj1.free();

  if (dict->lookup("T", &obj1)->isString()) {
    partialName = obj1.getString()->copy();
  } else {
    partialName = NULL;
  }
  obj1.free();

  if (dict->lookup("TU", &obj1)->isString()) {
    alternateUiName = obj1.getString()->copy();
  } else {
    alternateUiName = NULL;
  }
  obj1.free();

  if(dict->lookup("TM", &obj1)->isString()) {
    mappingName = obj1.getString()->copy();
  } else {
    mappingName = NULL;
  }
  obj1.free();
}

void FormField::setPartialName(const GooString &name)
{
  delete partialName;
  partialName = name.copy();

  Object obj1;
  obj1.initString(name.copy());
  obj.getDict()->set("T", &obj1);
  xref->setModifiedObject(&obj, ref);
}

FormField::~FormField()
{
  if (!terminal) {
    if(children) {
      for (int i=0; i<numChildren; i++)
        delete children[i];
      gfree(children);
    }
  } else {
    for (int i = 0; i < numChildren; ++i)
      delete widgets[i];
    gfree (widgets);
  }
  obj.free();

  delete defaultAppearance;
  delete partialName;
  delete alternateUiName;
  delete mappingName;
  delete fullyQualifiedName;
}

#ifdef DEBUG_FORMS
void FormField::print(int indent)
{
  printf ("%*s- (%d %d): [container] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}

void FormField::printTree(int indent)
{
  print(indent);
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->print(indent + 4);
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->printTree(indent + 4);
  }
}
#endif

void FormField::fillChildrenSiblingsID()
{
  if (terminal)
    return;
  for (int i = 0; i < numChildren; i++) {
    children[i]->fillChildrenSiblingsID();
  }
}

void FormField::createWidgetAnnotations() {
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->createWidgetAnnotation();
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->createWidgetAnnotations();
  }
}

void FormField::_createWidget (Object *obj, Ref aref)
{
  terminal = true;
  numChildren++;
  widgets = (FormWidget**)greallocn(widgets, numChildren, sizeof(FormWidget*));
  //ID = index in "widgets" table
  switch (type) {
  case formButton:
    widgets[numChildren-1] = new FormWidgetButton(doc, obj, numChildren-1, aref, this);
    break;
  case formText:
    widgets[numChildren-1] = new FormWidgetText(doc, obj, numChildren-1, aref, this);
    break;
  case formChoice:
    widgets[numChildren-1] = new FormWidgetChoice(doc, obj, numChildren-1, aref, this);
    break;
  case formSignature:
    widgets[numChildren-1] = new FormWidgetSignature(doc, obj, numChildren-1, aref, this);
    break;
  default:
    error(errSyntaxWarning, -1, "SubType on non-terminal field, invalid document?");
    numChildren--;
    terminal = false;
  }
}

FormWidget* FormField::findWidgetByRef (Ref aref)
{
  if (terminal) {
    for(int i=0; i<numChildren; i++) {
      if (widgets[i]->getRef().num == aref.num 
          && widgets[i]->getRef().gen == aref.gen)
        return widgets[i];
    }
  } else {
    for(int i=0; i<numChildren; i++) {
      FormWidget* result = children[i]->findWidgetByRef(aref);
      if(result) return result;
    }
  }
  return NULL;
}

GooString* FormField::getFullyQualifiedName() {
  Object obj1, obj2;
  Object parent;
  GooString *parent_name;
  GooString *full_name;
  GBool unicode_encoded = gFalse;

  if (fullyQualifiedName)
    return fullyQualifiedName;

  full_name = new GooString();

  obj.copy(&obj1);
  while (obj1.dictLookup("Parent", &parent)->isDict()) {
    if (parent.dictLookup("T", &obj2)->isString()) {
      parent_name = obj2.getString();

      if (unicode_encoded) {
        full_name->insert(0, "\0.", 2); // 2-byte unicode period
        if (parent_name->hasUnicodeMarker()) {
          full_name->insert(0, parent_name->getCString() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
        } else {
          int tmp_length;
          char* tmp_str = pdfDocEncodingToUTF16(parent_name, &tmp_length);
          full_name->insert(0, tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
          delete [] tmp_str;
        }
      } else {
        full_name->insert(0, '.'); // 1-byte ascii period
        if (parent_name->hasUnicodeMarker()) {          
          unicode_encoded = gTrue;
          full_name = convertToUtf16(full_name);
          full_name->insert(0, parent_name->getCString() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
        } else {
          full_name->insert(0, parent_name);
        }
      }
      obj2.free();
    }
    obj1.free();
    parent.copy(&obj1);
    parent.free();
  }
  obj1.free();
  parent.free();

  if (partialName) {
    if (unicode_encoded) {
      if (partialName->hasUnicodeMarker()) {
        full_name->append(partialName->getCString() + 2, partialName->getLength() - 2); // Remove the unicode BOM
      } else {
        int tmp_length;
        char* tmp_str = pdfDocEncodingToUTF16(partialName, &tmp_length);
        full_name->append(tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
        delete [] tmp_str;
      }
    } else {
      if (partialName->hasUnicodeMarker()) {
          unicode_encoded = gTrue;        
          full_name = convertToUtf16(full_name);
          full_name->append(partialName->getCString() + 2, partialName->getLength() - 2); // Remove the unicode BOM
      } else {
        full_name->append(partialName);
      }
    }
  } else {
    int len = full_name->getLength();
    // Remove the last period
    if (unicode_encoded) {
      if (len > 1) {
        full_name->del(len - 2, 2);
      }
    } else {
      if (len > 0) {
        full_name->del(len - 1, 1);
      }
    }
  }
  
  if (unicode_encoded) {
    full_name->insert(0, 0xff);
    full_name->insert(0, 0xfe);
  }

  fullyQualifiedName = full_name;
  return fullyQualifiedName;
}

void FormField::updateChildrenAppearance()
{
  // Recursively update each child's appearance
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->updateWidgetAppearance();
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->updateChildrenAppearance();
  }
}

//------------------------------------------------------------------------
// FormFieldButton
//------------------------------------------------------------------------
FormFieldButton::FormFieldButton(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, aobj, ref, parent, usedParents, formButton)
{
  Dict* dict = obj.getDict();
  active_child = -1;
  noAllOff = false;
  siblings = NULL;
  numSiblings = 0;
  appearanceState.initNull();

  Object obj1;
  btype = formButtonCheck; 
  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
    int flags = obj1.getInt();
    
    if (flags & 0x10000) { // 17 -> push button
      btype = formButtonPush;
    } else if (flags & 0x8000) { // 16 -> radio button
      btype = formButtonRadio;
      if (flags & 0x4000) { // 15 -> noToggleToOff
        noAllOff = true;
      }
    } 
    if (flags & 0x1000000) { // 26 -> radiosInUnison
      error(errUnimplemented, -1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
    } 
  }

  if (btype != formButtonPush) {
    // Even though V is inheritable we are interested in the value of this
    // field, if not present it's probably because it's a button in a set.
    dict->lookup("V", &appearanceState);
  }
}

#ifdef DEBUG_FORMS
static char *_getButtonType(FormButtonType type)
{
  switch (type) {
  case formButtonPush:
    return "push";
  case formButtonCheck:
    return "check";
  case formButtonRadio:
    return "radio";
  default:
    break;
  }
  return "unknown";
}

void FormFieldButton::print(int indent)
{
  printf ("%*s- (%d %d): [%s] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          _getButtonType(btype), terminal ? "Yes" : "No", numChildren);
}
#endif

void FormFieldButton::setNumSiblings (int num)
{ 
  numSiblings = num; 
  siblings = (FormFieldButton**)greallocn(siblings, numSiblings, sizeof(FormFieldButton*));
}

void FormFieldButton::fillChildrenSiblingsID()
{
  if (!terminal) {
    for(int i=0; i<numChildren; i++) {
      FormFieldButton *child = dynamic_cast<FormFieldButton*>(children[i]);
      if (child != NULL) {
        // Fill the siblings of this node childs
        child->setNumSiblings(numChildren-1);
        for(int j=0, counter=0; j<numChildren; j++) {
          FormFieldButton *otherChild = dynamic_cast<FormFieldButton*>(children[j]);
          if (i == j) continue;
          if (child == otherChild) continue;
          child->setSibling(counter, otherChild);
          counter++;
        }

        // now call ourselves on the child
        // to fill its children data
        child->fillChildrenSiblingsID();
      }
    }
  }
}

GBool FormFieldButton::setState(char *state)
{
  // 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)
    return gFalse;

  if (terminal && parent && parent->getType() == formButton && appearanceState.isNull()) {
    // It's button in a set, set state on parent
    if (static_cast<FormFieldButton*>(parent)->setState(state)) {
      return gTrue;
    }
    return gFalse;
  }

  GBool isOn = strcmp(state, "Off") != 0;

  if (!isOn && noAllOff)
    return gFalse; // Don't allow to set all radio to off

  char *current = getAppearanceState();
  GBool currentFound = gFalse, newFound = gFalse;

  for (int i = 0; i < numChildren; i++) {
    FormWidgetButton *widget;

    // If radio button is a terminal field we want the widget at i, but
    // if it's not terminal, the child widget is a composed dict, so
    // we want the ony child widget of the children at i
    if (terminal)
      widget = static_cast<FormWidgetButton*>(widgets[i]);
    else
      widget = static_cast<FormWidgetButton*>(children[i]->getWidget(0));

    if (!widget->getOnStr())
      continue;

    char *onStr = widget->getOnStr();
    if (current && strcmp(current, onStr) == 0) {
      widget->setAppearanceState("Off");
      if (!isOn)
        break;
      currentFound = gTrue;
    }

    if (isOn && strcmp(state, onStr) == 0) {
      widget->setAppearanceState(state);
      newFound = gTrue;
    }

    if (currentFound && newFound)
      break;
  }

  updateState(state);

  return gTrue;
}

GBool FormFieldButton::getState(char *state) {
  if (appearanceState.isName(state))
    return gTrue;

  return (parent && parent->getType() == formButton) ? static_cast<FormFieldButton*>(parent)->getState(state) : gFalse;
}

void FormFieldButton::updateState(char *state) {
  Object obj1;

  appearanceState.free();
  appearanceState.initName(state);

  appearanceState.copy(&obj1);
  obj.getDict()->set("V", &obj1);
  xref->setModifiedObject(&obj, ref);
}

FormFieldButton::~FormFieldButton()
{
  appearanceState.free();
  if (siblings)
    gfree(siblings);
}

//------------------------------------------------------------------------
// FormFieldText
//------------------------------------------------------------------------
FormFieldText::FormFieldText(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, aobj, ref, parent, usedParents, formText)
{
  Dict* dict = obj.getDict();
  Object obj1;
  content = NULL;
  multiline = password = fileSelect = doNotSpellCheck = doNotScroll = comb = richText = false;
  maxLen = 0;

  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x1000) // 13 -> Multiline
      multiline = true;
    if (flags & 0x2000) // 14 -> Password
      password = true;
    if (flags & 0x100000) // 21 -> FileSelect
      fileSelect = true;
    if (flags & 0x400000)// 23 -> DoNotSpellCheck
      doNotSpellCheck = true;
    if (flags & 0x800000) // 24 -> DoNotScroll
      doNotScroll = true;
    if (flags & 0x1000000) // 25 -> Comb
      comb = true;
    if (flags & 0x2000000)// 26 -> RichText
      richText = true;
  }
  obj1.free();

  if (Form::fieldLookup(dict, "MaxLen", &obj1)->isInt()) {
    maxLen = obj1.getInt();
  }
  obj1.free();

  if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
    if (obj1.getString()->hasUnicodeMarker()) {
      if (obj1.getString()->getLength() > 2)
        content = obj1.getString()->copy();
    } else if (obj1.getString()->getLength() > 0) {
      //non-unicode string -- assume pdfDocEncoding and try to convert to UTF16BE
      int tmp_length;
      char* tmp_str = pdfDocEncodingToUTF16(obj1.getString(), &tmp_length);
      content = new GooString(tmp_str, tmp_length);
      delete [] tmp_str;
    }
  }
  obj1.free();
}

#ifdef DEBUG_FORMS
void FormFieldText::print(int indent)
{
  printf ("%*s- (%d %d): [text] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}
#endif

GooString* FormFieldText::getContentCopy ()
{
  if (!content) return NULL;
  return new GooString(content);
}

void FormFieldText::setContentCopy (GooString* new_content)
{
  delete content;
  content = NULL;

  if (new_content) {
    content = new_content->copy();

    //append the unicode marker <FE FF> if needed
    if (!content->hasUnicodeMarker()) {
      content->insert(0, 0xff);
      content->insert(0, 0xfe);
    }
  }

  Object obj1;
  obj1.initString(content ? content->copy() : new GooString(""));
  obj.getDict()->set("V", &obj1);
  xref->setModifiedObject(&obj, ref);
  updateChildrenAppearance();
}

FormFieldText::~FormFieldText()
{
  delete content;
}


//------------------------------------------------------------------------
// FormFieldChoice
//------------------------------------------------------------------------
FormFieldChoice::FormFieldChoice(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, aobj, ref, parent, usedParents, formChoice)
{
  numChoices = 0;
  choices = NULL;
  editedChoice = NULL;
  topIdx = 0;

  Dict* dict = obj.getDict();
  Object obj1;

  combo = edit = multiselect = doNotSpellCheck = doCommitOnSelChange = false;

  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x20000) // 18 -> Combo
      combo = true; 
    if (flags & 0x40000) // 19 -> Edit
      edit = true;
    if (flags & 0x200000) // 22 -> MultiSelect
      multiselect = true;
    if (flags & 0x400000) // 23 -> DoNotSpellCheck
      doNotSpellCheck = true;
    if (flags & 0x4000000) // 27 -> CommitOnSelChange
      doCommitOnSelChange = true;
  }
  obj1.free();

  if (dict->lookup("TI", &obj1)->isInt())
    topIdx = obj1.getInt();
  obj1.free();

  if (dict->lookup("Opt", &obj1)->isArray()) {
    Object obj2;

    numChoices = obj1.arrayGetLength();
    choices = new ChoiceOpt[numChoices];
    memset(choices, 0, sizeof(ChoiceOpt) * numChoices);

    for (int i = 0; i < numChoices; i++) {
      if (obj1.arrayGet(i, &obj2)->isString()) {
        choices[i].optionName = obj2.getString()->copy();
      } else if (obj2.isArray()) { // [Export_value, Displayed_text]
        Object obj3;

        if (obj2.arrayGetLength() < 2) {
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
          continue;
        }
        if (obj2.arrayGet(0, &obj3)->isString())
          choices[i].exportVal = obj3.getString()->copy();
        else
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- exported value not a string\n");
        obj3.free();

        if (obj2.arrayGet(1, &obj3)->isString())
          choices[i].optionName = obj3.getString()->copy();
        else
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- choice name not a string\n");
        obj3.free();
      } else {
        error(errSyntaxError, -1, "FormWidgetChoice:: invalid {0:d} Opt entry\n", i);
      }
      obj2.free();
    }
  } else {
    //empty choice
  }
  obj1.free();

  // Find selected items
  // Note: PDF specs say that /V has precedence over /I, but acroread seems to
  // do the opposite. We do the same.
  if (Form::fieldLookup(dict, "I", &obj1)->isArray()) {
    for (int i = 0; i < obj1.arrayGetLength(); i++) {
      Object obj2;
      if (obj1.arrayGet(i, &obj2)->isInt() && obj2.getInt() >= 0 && obj2.getInt() < numChoices) {
        choices[obj2.getInt()].selected = true;
      }
      obj2.free();
    }
  } else {
    obj1.free();
    // Note: According to PDF specs, /V should *never* contain the exportVal.
    // However, if /Opt is an array of (exportVal,optionName) pairs, acroread
    // seems to expect the exportVal instead of the optionName and so we do too.
    if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
      GBool optionFound = gFalse;

      for (int i = 0; i < numChoices; i++) {
        if (choices[i].exportVal) {
          if (choices[i].exportVal->cmp(obj1.getString()) == 0) {
            optionFound = gTrue;
          }
        } else if (choices[i].optionName) {
          if (choices[i].optionName->cmp(obj1.getString()) == 0) {
            optionFound = gTrue;
          }
        }

        if (optionFound) {
          choices[i].selected = true;
          break; // We've determined that this option is selected. No need to keep on scanning
        }
      }

      // Set custom value if /V doesn't refer to any predefined option and the field is user-editable
      if (!optionFound && edit) {
        editedChoice = obj1.getString()->copy();
      }
    } else if (obj1.isArray()) {
      for (int i = 0; i < numChoices; i++) {
        for (int j = 0; j < obj1.arrayGetLength(); j++) {
          Object obj2;
          obj1.arrayGet(j, &obj2);
          GBool matches = gFalse;

          if (choices[i].exportVal) {
            if (choices[i].exportVal->cmp(obj2.getString()) == 0) {
              matches = gTrue;
            }
          } else if (choices[i].optionName) {
            if (choices[i].optionName->cmp(obj2.getString()) == 0) {
              matches = gTrue;
            }
          }

          obj2.free();

          if (matches) {
            choices[i].selected = true;
            break; // We've determined that this option is selected. No need to keep on scanning
          }
        }
      }
    }
  }
  obj1.free();
}

FormFieldChoice::~FormFieldChoice()
{
  for (int i = 0; i < numChoices; i++) {
    delete choices[i].exportVal;
    delete choices[i].optionName;
  }
  delete [] choices;
  delete editedChoice;
}

#ifdef DEBUG_FORMS
void FormFieldChoice::print(int indent)
{
  printf ("%*s- (%d %d): [choice] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}
#endif

void FormFieldChoice::updateSelection() {
  Object objV, objI, obj1;
  objI.initNull();

  if (edit && editedChoice) {
    // This is an editable combo-box with user-entered text
    objV.initString(editedChoice->copy());
  } else {
    const int numSelected = getNumSelected();

    // Create /I array only if multiple selection is allowed (as per PDF spec)
    if (multiselect) {
      objI.initArray(xref);
    }

    if (numSelected == 0) {
      // No options are selected
      objV.initString(new GooString(""));
    } else if (numSelected == 1) {
      // Only one option is selected
      for (int i = 0; i < numChoices; i++) {
        if (choices[i].selected) {
          if (multiselect) {
            objI.arrayAdd(obj1.initInt(i));
          }

          if (choices[i].exportVal) {
            objV.initString(choices[i].exportVal->copy());
          } else if (choices[i].optionName) {
            objV.initString(choices[i].optionName->copy());
          }

          break; // We've just written the selected option. No need to keep on scanning
        }
      }
    } else {
      // More than one option is selected
      objV.initArray(xref);
      for (int i = 0; i < numChoices; i++) {
        if (choices[i].selected) {
          if (multiselect) {
            objI.arrayAdd(obj1.initInt(i));
          }

          if (choices[i].exportVal) {
            objV.arrayAdd(obj1.initString(choices[i].exportVal->copy()));
          } else if (choices[i].optionName) {
            objV.arrayAdd(obj1.initString(choices[i].optionName->copy()));
          }
        }
      }
    }
  }

  obj.getDict()->set("V", &objV);
  obj.getDict()->set("I", &objI);
  xref->setModifiedObject(&obj, ref);
  updateChildrenAppearance();
}

void FormFieldChoice::unselectAll ()
{
  for (int i = 0; i < numChoices; i++) {
    choices[i].selected = false;
  }
}

void FormFieldChoice::deselectAll () {
  delete editedChoice;
  editedChoice = NULL;

  unselectAll();
  updateSelection();
}

void FormFieldChoice::toggle (int i)
{
  delete editedChoice;
  editedChoice = NULL;

  choices[i].selected = !choices[i].selected;
  updateSelection();
}

void FormFieldChoice::select (int i)
{
  delete editedChoice;
  editedChoice = NULL;

  if (!multiselect)
    unselectAll();

  choices[i].selected = true;
  updateSelection();
}

void FormFieldChoice::setEditChoice (GooString* new_content)
{
  delete editedChoice;
  editedChoice = NULL;

  unselectAll();

  if (new_content) {
    editedChoice = new_content->copy();

    //append the unicode marker <FE FF> if needed
    if (!editedChoice->hasUnicodeMarker()) {
      editedChoice->insert(0, 0xff);
      editedChoice->insert(0, 0xfe);
    }
  }
  updateSelection();
}

GooString* FormFieldChoice::getEditChoice ()
{
  return editedChoice;
}

int FormFieldChoice::getNumSelected ()
{
  int cnt = 0;
  for(int i=0; i<numChoices; i++) {
    if (choices[i].selected)
      cnt++;
  }
  return cnt;
}

GooString *FormFieldChoice::getSelectedChoice() {
  if (edit && editedChoice)
    return editedChoice;

  for (int i = 0; i < numChoices; i++) {
    if (choices[i].optionName && choices[i].selected)
      return choices[i].optionName;
  }

  return NULL;
}

//------------------------------------------------------------------------
// FormFieldSignature
//------------------------------------------------------------------------
FormFieldSignature::FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, dict, ref, parent, usedParents, formSignature)
{
  signature = NULL;

  signature_info = new SignatureInfo();
  parseInfo();
}

FormFieldSignature::~FormFieldSignature()
{
  byte_range.free();
  delete signature_info;
  delete signature;
}

void FormFieldSignature::parseInfo()
{
  if (!obj.isDict())
    return;

  Object sig_dict, contents_obj, time_of_signing, subfilterName;

  // retrieve PKCS#7
  obj.dictLookup("V", &sig_dict);
  if (!sig_dict.isDict()) {
    sig_dict.free();
    return;
  }

  sig_dict.dictLookup("Contents", &contents_obj);
  if (contents_obj.isString()) {
    signature = contents_obj.getString()->copy();
  }
  contents_obj.free();

  sig_dict.dictLookup("ByteRange", &byte_range);

  // retrieve SigningTime
  sig_dict.dictLookup("M", &time_of_signing);
  if (time_of_signing.isString()) {
    GooString *time_str = time_of_signing.getString();
    signature_info->setSigningTime(dateStringToTime(time_str)); // Put this information directly in SignatureInfo object
    time_of_signing.free();
  }

  // check if subfilter is supported for signature validation, only detached signatures work for now
  sig_dict.dictLookup("SubFilter", &subfilterName);
  if (subfilterName.isName("adbe.pkcs7.detached") || subfilterName.isName("adbe.pkcs7.sha1")) {
    signature_info->setSubFilterSupport(true);
  }

  subfilterName.free();
  sig_dict.free();
}

void FormFieldSignature::hashSignedDataBlock(SignatureHandler *handler, Goffset block_len)
{
#ifdef ENABLE_NSS3
  const int BLOCK_SIZE = 4096;
  unsigned char signed_data_buffer[BLOCK_SIZE];

  Goffset i = 0;
  while(i < block_len)
  {
    Goffset bytes_left = block_len - i;
    if (bytes_left < BLOCK_SIZE)
    {
      doc->getBaseStream()->doGetChars(bytes_left, signed_data_buffer);
      handler->updateHash(signed_data_buffer, bytes_left);
      i = block_len;
    }
    else
    {
      doc->getBaseStream()->doGetChars(BLOCK_SIZE, signed_data_buffer);
      handler->updateHash(signed_data_buffer, BLOCK_SIZE);
      i += BLOCK_SIZE;
    }
  }
#endif
}


SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation)
{
#ifdef ENABLE_NSS3
  if (!signature_info->isSubfilterSupported()) {
    error(errUnimplemented, 0, "Unable to validate this type of signature");
    return signature_info;
  }

  if (signature_info->getSignatureValStatus() != SIGNATURE_NOT_VERIFIED && !forceRevalidation) {
    return signature_info;
  }

  if (signature == NULL) {
    error(errSyntaxError, 0, "Invalid or missing Signature string");
    return signature_info;
  }

  if (!byte_range.isArray()) {
    error(errSyntaxError, 0, "Invalid or missing ByteRange array");
    return signature_info;
  }

  int arrayLen = byte_range.arrayGetLength();
  if (arrayLen < 2) {
    error(errSyntaxError, 0, "Too few elements in ByteRange array");
    return signature_info;
  }

  NSSCMSVerificationStatus sig_val_state;
  SECErrorCodes cert_val_state;
  const int signature_len = signature->getLength();
  unsigned char *signatureuchar = (unsigned char *)gmalloc(signature_len);
  memcpy(signatureuchar, signature->getCString(), signature_len);
  SignatureHandler signature_handler(signatureuchar, signature_len);

  Goffset fileLength = doc->getBaseStream()->getLength();
  for (int i = 0; i < arrayLen/2; i++) {
    Object offsetObj, lenObj;
    byte_range.arrayGet(i*2, &offsetObj);
    byte_range.arrayGet(i*2+1, &lenObj);

    if (!offsetObj.isIntOrInt64() || !lenObj.isIntOrInt64()) {
      error(errSyntaxError, 0, "Illegal values in ByteRange array");
      return signature_info;
    }

    Goffset offset = offsetObj.getIntOrInt64();
    Goffset len = lenObj.getIntOrInt64();

    if (offset < 0 || offset >= fileLength || len < 0 || len > fileLength || offset + len > fileLength) {
      error(errSyntaxError, 0, "Illegal values in ByteRange array");
      return signature_info;
    }

    doc->getBaseStream()->setPos(offset);
    hashSignedDataBlock(&signature_handler, len);
  }

  sig_val_state = signature_handler.validateSignature();
  signature_info->setSignatureValStatus(SignatureHandler::NSS_SigTranslate(sig_val_state));
  signature_info->setSignerName(signature_handler.getSignerName());

  // verify if signature contains a 'signing time' attribute
  if (signature_handler.getSigningTime() != 0) {
    signature_info->setSigningTime(signature_handler.getSigningTime());
  }

  if (sig_val_state != NSSCMSVS_GoodSignature || !doVerifyCert) {
    return signature_info;
  }

  cert_val_state = signature_handler.validateCertificate();
  signature_info->setCertificateValStatus(SignatureHandler::NSS_CertTranslate(cert_val_state));

#endif
  return signature_info;
}

#ifdef DEBUG_FORMS
void FormFieldSignature::print(int indent)
{
  printf ("%*s- (%d %d): [signature] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}
#endif

//------------------------------------------------------------------------
// Form
//------------------------------------------------------------------------

Form::Form(PDFDoc *docA, Object* acroFormA)
{
  Object obj1;

  doc = docA;
  xref = doc->getXRef();
  acroForm = acroFormA;
  
  size = 0;
  numFields = 0;
  rootFields = NULL;
  quadding = quaddingLeftJustified;
  defaultAppearance = NULL;
  defaultResources = NULL;

  acroForm->dictLookup("NeedAppearances", &obj1);
  needAppearances = (obj1.isBool() && obj1.getBool());
  obj1.free();

  if (acroForm->dictLookup("DA", &obj1)->isString())
    defaultAppearance = obj1.getString()->copy();
  obj1.free();

  if (acroForm->dictLookup("Q", &obj1)->isInt())
    quadding = static_cast<VariableTextQuadding>(obj1.getInt());
  obj1.free();

  acroForm->dictLookup("DR", &resDict);
  if (resDict.isDict()) {
    // At a minimum, this dictionary shall contain a Font entry
    if (resDict.dictLookup("Font", &obj1)->isDict())
      defaultResources = new GfxResources(xref, resDict.getDict(), NULL);
    obj1.free();
  }
  if (!defaultResources) {
    resDict.free();
    resDict.initNull();
  }

  acroForm->dictLookup("Fields", &obj1);
  if (obj1.isArray()) {
    Array *array = obj1.getArray();
    Object obj2;
    
    for(int i=0; i<array->getLength(); i++) {
      Object oref;
      array->get(i, &obj2);
      array->getNF(i, &oref);
      if (!oref.isRef()) {
        error(errSyntaxWarning, -1, "Direct object in rootFields");
	obj2.free();
	oref.free();
        continue;
      }

      if (!obj2.isDict()) {
        error(errSyntaxWarning, -1, "Reference in Fields array to an invalid or non existent object");
	obj2.free();
	oref.free();
	continue;
      }

      if (numFields >= size) {
        size += 16;
        rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
      }

      std::set<int> usedParents;
      rootFields[numFields++] = createFieldFromDict (&obj2, doc, oref.getRef(), NULL, &usedParents);

      obj2.free();
      oref.free();
    }
  } else {
    error(errSyntaxError, -1, "Can't get Fields array\n");
  }
  obj1.free ();

  acroForm->dictLookup("CO", &obj1);
  if (obj1.isArray()) {
    Array *array = obj1.getArray();
    calculateOrder.reserve(array->getLength());
    for(int i=0; i<array->getLength(); i++) {
      Object oref;
      array->getNF(i, &oref);
      if (!oref.isRef()) {
        error(errSyntaxWarning, -1, "Direct object in CO");
        oref.free();
        continue;
      }
      calculateOrder.push_back(oref.getRef());

      oref.free();
    }
  }
  obj1.free ();

#ifdef DEBUG_FORMS
  for (int i = 0; i < numFields; i++)
    rootFields[i]->printTree();
#endif
}

Form::~Form() {
  int i;
  for(i = 0; i < numFields; ++i)
    delete rootFields[i];
  gfree (rootFields);
  delete defaultAppearance;
  delete defaultResources;
  resDict.free();
}

// Look up an inheritable field dictionary entry.
static Object *fieldLookup(Dict *field, const char *key, Object *obj, std::set<int> *usedParents) {
  Dict *dict;
  Object parent;

  dict = field;
  if (!dict->lookup(key, obj)->isNull()) {
    return obj;
  }
  obj->free();
  dict->lookupNF("Parent", &parent);
  if (parent.isRef()) {
    const Ref ref = parent.getRef();
    if (usedParents->find(ref.num) == usedParents->end()) {
      usedParents->insert(ref.num);

      Object obj2;
      parent.fetch(dict->getXRef(), &obj2);
      if (obj2.isDict()) {
        fieldLookup(obj2.getDict(), key, obj, usedParents);
      } else {
        obj->initNull();
      }
      obj2.free();
    }
  } else if (parent.isDict()) {
    fieldLookup(parent.getDict(), key, obj, usedParents);
  } else {
    obj->initNull();
  }
  parent.free();
  return obj;
}

Object *Form::fieldLookup(Dict *field, const char *key, Object *obj) {
  std::set<int> usedParents;
  return ::fieldLookup(field, key, obj, &usedParents);
}

FormField *Form::createFieldFromDict (Object* obj, PDFDoc *docA, const Ref& pref, FormField *parent, std::set<int> *usedParents)
{
    Object obj2;
    FormField *field;

    if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
      field = new FormFieldButton(docA, obj, pref, parent, usedParents);
    } else if (obj2.isName("Tx")) {
      field = new FormFieldText(docA, obj, pref, parent, usedParents);
    } else if (obj2.isName("Ch")) {
      field = new FormFieldChoice(docA, obj, pref, parent, usedParents);
    } else if (obj2.isName("Sig")) {
      field = new FormFieldSignature(docA, obj, pref, parent, usedParents);
    } else { //we don't have an FT entry => non-terminal field
      field = new FormField(docA, obj, pref, parent, usedParents);
    }
    obj2.free();

    return field;
}

void Form::postWidgetsLoad()
{
  // We create the widget annotations associated to
  // every form widget here, because the AnnotWidget constructor
  // needs the form object that gets from the catalog. When constructing
  // a FormWidget the Catalog is still creating the form object
  for (int i = 0; i < numFields; i++) {
    rootFields[i]->fillChildrenSiblingsID();
    rootFields[i]->createWidgetAnnotations();
  }
}

FormWidget* Form::findWidgetByRef (Ref aref)
{
  for(int i=0; i<numFields; i++) {
    FormWidget *result = rootFields[i]->findWidgetByRef(aref);
    if(result) return result;
  }
  return NULL;
}

//------------------------------------------------------------------------
// FormPageWidgets
//------------------------------------------------------------------------

FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
{
  numWidgets = 0;
  widgets = NULL;

  if (annots && annots->getNumAnnots() > 0 && form) {
    size = annots->getNumAnnots();
    widgets = (FormWidget**)greallocn(widgets, size, sizeof(FormWidget*));

    /* For each entry in the page 'Annots' dict, try to find
       a matching form field */
    for (int i = 0; i < size; ++i) {
      Annot *annot = annots->getAnnot(i);

      if (annot->getType() != Annot::typeWidget)
        continue;

      if (!annot->getHasRef()) {
        /* Since all entry in a form field's kid dict needs to be
           indirect references, if this annot isn't indirect, it isn't 
           related to a form field */
        continue;
      }

      Ref r = annot->getRef();

      /* Try to find a form field which either has this Annot in its Kids entry
          or  is merged with this Annot */
      FormWidget* tmp = form->findWidgetByRef(r);
      if (tmp) {
        // We've found a corresponding form field, link it
        tmp->setID(FormWidget::encodeID(page, numWidgets));
        widgets[numWidgets++] = tmp;
      }
    }
  }
}

FormPageWidgets::~FormPageWidgets()
{
  gfree (widgets);
}
