//========================================================================
//
// 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 <limits>
#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();
  obj = aobj->copy();
  type = formUndef;
  field = fieldA;
  widget = NULL;
}

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

#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(ref.num, ref.gen);
  widget = new AnnotWidget(doc, &obj, &obj1, field);
}

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;

  // 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
  Object obj1 = obj.dictLookup("AP");
  if (obj1.isDict()) {
    Object obj2 = obj1.dictLookup("N");
    if (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;
        }
      }
    }
  }
}

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, time_t validationTime)
{
  return static_cast<FormFieldSignature*>(field)->validateSignature(doVerifyCert, forceRevalidation, validationTime);
}

std::vector<Goffset> FormWidgetSignature::getSignedRangeBounds()
{
  Object* obj = static_cast<FormFieldSignature*>(field)->getByteRange();
  std::vector<Goffset> range_vec;
  if (obj->isArray())
  {
    if (obj->arrayGetLength() == 4)
    {
      for (int i = 0; i < 2; ++i)
      {
        Object offsetObj(obj->arrayGet(2*i));
        Object lenObj(obj->arrayGet(2*i+1));
        if (offsetObj.isIntOrInt64() && lenObj.isIntOrInt64())
        {
          Goffset offset = offsetObj.getIntOrInt64();
          Goffset len = lenObj.getIntOrInt64();
          range_vec.push_back(offset);
          range_vec.push_back(offset+len);
        }
      }
    }
  }
  return range_vec;
}

GooString* FormWidgetSignature::getCheckedSignature(Goffset *checkedFileSize)
{
  Goffset start = 0;
  Goffset end = 0;
  const std::vector<Goffset> ranges = getSignedRangeBounds();
  if (ranges.size() == 4)
  {
    start = ranges[1];
    end = ranges[2];
  }
  if (end >= start+6)
  {
    BaseStream* stream = doc->getBaseStream();
    *checkedFileSize = stream->getLength();
    Goffset len = end-start;
    stream->setPos(end-1);
    int c2 = stream->lookChar();
    stream->setPos(start);
    int c1 = stream->getChar();
    // PDF signatures are first ASN1 DER, then hex encoded PKCS#7 structures,
    // possibly padded with 0 characters and enclosed in '<' and '>'.
    // The ASN1 DER encoding of a PKCS#7 structure must start with the tag 0x30
    // for SEQUENCE. The next byte must be 0x80 for ASN1 DER indefinite length
    // encoding or (0x80 + n) for ASN1 DER definite length encoding
    // where n is the number of subsequent "length bytes" which big-endian
    // encode the length of the content of the SEQUENCE following them.
    if (len <= std::numeric_limits<int>::max() && *checkedFileSize > end && c1 == '<' && c2 == '>')
    {
      GooString gstr;
      ++start;
      --end;
      len = end-start;
      Goffset pos = 0;
      do
      {
        c1 = stream->getChar();
        if (c1 == EOF)
          return nullptr;
        gstr.append(static_cast<char>(c1));
      } while (++pos < len);
      if (gstr.getChar(0) == '3' && gstr.getChar(1) == '0')
      {
        if (gstr.getChar(2) == '8' && gstr.getChar(3) == '0')
        {
          // ASN1 DER indefinite length encoding:
          // We only check that all characters up to the enclosing '>'
          // are hex characters and that there are two hex encoded 0 bytes
          // just before the enclosing '>' marking the end of the indefinite
          // length encoding.
          int paddingCount = 0;
          while (gstr.getChar(len-1) == '0' && gstr.getChar(len-2) == '0')
          {
            ++paddingCount;
            len -= 2;
          }
          if (paddingCount < 2 || len%2 == 1)
            len = 0;
        }
        else if (gstr.getChar(2) == '8')
        {
          // ASN1 DER definite length encoding:
          // We calculate the length of the following bytes from the length bytes and
          // check that after the length bytes and the following calculated number of
          // bytes all bytes up to the enclosing '>' character are hex encoded 0 bytes.
          int lenBytes = gstr.getChar(3) - '0';
          if (lenBytes > 0 && lenBytes <= 4)
          {
            int sigLen = 0;
            for (int i = 0; i < 2*lenBytes; ++i)
            {
              sigLen <<= 4;
              char c = gstr.getChar(i+4);
              if (isdigit(c))
                sigLen += c - '0';
              else if (isxdigit(c) && c >= 'a')
                sigLen += c - 'a' + 10;
              else if (isxdigit(c) && c >= 'A')
                sigLen += c - 'A' + 10;
              else
              {
                len = 0;
                break;
              }
            }
            if (sigLen > 0 && 2*(sigLen+lenBytes) <= len-4)
            {
              for (int i = 2*(sigLen+lenBytes)+4; i < len; ++i)
              {
                if (gstr.getChar(i) != '0')
                {
                  len = 0;
                  break;
                }
              }
            }
            else
              len = 0;
          }
        }
        for (int i = 0; i < len; ++i)
        {
          if (!isxdigit(gstr.getChar(i)))
            len = 0;
        }
        if (len > 0)
        {
          return new GooString(&gstr, 0, len);
        }
      }
    }
  }
  return nullptr;
}

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();
  obj = aobj->copy();
  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;

  //childs
  Object obj1 = dict->lookup("Kids");
  if (obj1.isArray()) {
    // Load children
    for (int i = 0 ; i < obj1.arrayGetLength(); i++) {
      Object childRef = obj1.arrayGetNF(i);
      if (!childRef.isRef()) {
        error (errSyntaxError, -1, "Invalid form field renference");
        continue;
      }
      Object childObj = obj1.arrayGet(i);
      if (!childObj.isDict()) {
        error (errSyntaxError, -1, "Form field child is not a dictionary");
        continue;
      }

      const Ref ref = childRef.getRef();
      if (usedParents->find(ref.num) == usedParents->end()) {
        // Field child: it could be a form field or a widget or composed dict
        Object obj2 = childObj.dictLookupNF("Parent");
	Object obj3 = childObj.dictLookup("Parent");
        if (obj2.isRef() || 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);

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

          numChildren++;
          children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
          children[numChildren - 1] = Form::createFieldFromDict(&childObj, doc, ref, this, &usedParentsAux);
        } else {
	  obj2 = childObj.dictLookup("Subtype");
	  if (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");
	      continue;
	    }
	    _createWidget(&childObj, ref);
	  }
	}
      }
    }
  } else {
    // No children, if it's a composed dict, create the child widget
    obj1 = dict->lookup("Subtype");
    if (obj1.isName("Widget"))
      _createWidget(&obj, ref);
  }

  //flags
  obj1 = Form::fieldLookup(dict, "Ff");
  if (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
    }
  }

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

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

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

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

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

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

  obj.getDict()->set("T", Object(name.copy()));
  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);
  }

  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--;
  }
}

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;
  Object parent;
  GooString *parent_name;
  GooString *full_name;
  GBool unicode_encoded = gFalse;

  if (fullyQualifiedName)
    return fullyQualifiedName;

  full_name = new GooString();

  obj1 = obj.copy();
  while (parent = obj1.dictLookup("Parent"), parent.isDict()) {
    Object obj2 = parent.dictLookup("T");
    if (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);
        }
      }
    }
    obj1 = parent.copy();
  }

  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.setToNull();

  btype = formButtonCheck;
  Object obj1 = Form::fieldLookup(dict, "Ff");
  if (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.
    appearanceState = dict->lookup("V");
  }
}

#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) {
  appearanceState = Object(objName, state);
  obj.getDict()->set("V", appearanceState.copy());
  xref->setModifiedObject(&obj, ref);
}

FormFieldButton::~FormFieldButton()
{
  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;

  obj1 = Form::fieldLookup(dict, "Ff");
  if (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 = Form::fieldLookup(dict, "MaxLen");
  if (obj1.isInt()) {
    maxLen = obj1.getInt();
  }

  obj1 = Form::fieldLookup(dict, "V");
  if (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;
    }
  }
}

#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);
    }
  }

  obj.getDict()->set("V", Object(content ? content->copy() : new GooString("")));
  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;

  obj1 = Form::fieldLookup(dict, "Ff");
  if (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 = dict->lookup("TI");
  if (obj1.isInt())
    topIdx = obj1.getInt();

  obj1 = dict->lookup("Opt");
  if (obj1.isArray()) {
    numChoices = obj1.arrayGetLength();
    choices = new ChoiceOpt[numChoices];
    memset(choices, 0, sizeof(ChoiceOpt) * numChoices);

    for (int i = 0; i < numChoices; i++) {
      Object obj2 = obj1.arrayGet(i);
      if (obj2.isString()) {
        choices[i].optionName = obj2.getString()->copy();
      } else if (obj2.isArray()) { // [Export_value, Displayed_text]
        if (obj2.arrayGetLength() < 2) {
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
          continue;
        }
        Object obj3 = obj2.arrayGet(0);
        if (obj3.isString())
          choices[i].exportVal = obj3.getString()->copy();
        else
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- exported value not a string\n");

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

  // Find selected items
  // Note: PDF specs say that /V has precedence over /I, but acroread seems to
  // do the opposite. We do the same.
  obj1 = Form::fieldLookup(dict, "I");
  if (obj1.isArray()) {
    for (int i = 0; i < obj1.arrayGetLength(); i++) {
      Object obj2 = obj1.arrayGet(i);
      if (obj2.isInt() && obj2.getInt() >= 0 && obj2.getInt() < numChoices) {
        choices[obj2.getInt()].selected = true;
      }
    }
  } else {
    // 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.
    obj1 = Form::fieldLookup(dict, "V");
    if (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);
          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;
            }
          }

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

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, obj1;
  Object objI(objNull);

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

    // Create /I array only if multiple selection is allowed (as per PDF spec)
    if (multiselect) {
      objI = Object(new Array(xref));
    }

    if (numSelected == 0) {
      // No options are selected
      objV = Object(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(Object(i));
          }

          if (choices[i].exportVal) {
            objV = Object(choices[i].exportVal->copy());
          } else if (choices[i].optionName) {
            objV = Object(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 = Object(new Array(xref));
      for (int i = 0; i < numChoices; i++) {
        if (choices[i].selected) {
          if (multiselect) {
            objI.arrayAdd(Object(i));
          }

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

  obj.getDict()->set("V", std::move(objV));
  obj.getDict()->set("I", std::move(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_type(adbe_pkcs7_detached),
    signature(nullptr), signature_info(nullptr)
{
  signature = NULL;

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

FormFieldSignature::~FormFieldSignature()
{
  delete signature_info;
  delete signature;
}

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

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

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

  byte_range = sig_dict.dictLookup("ByteRange");

  // retrieve SigningTime
  Object time_of_signing = sig_dict.dictLookup("M");
  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
  }

  // check if subfilter is supported for signature validation, only detached signatures work for now
  Object subfilterName = sig_dict.dictLookup("SubFilter");
  if (subfilterName.isName("adbe.pkcs7.sha1")) {
    signature_type = adbe_pkcs7_sha1;
    signature_info->setSubFilterSupport(true);
  }
  else if (subfilterName.isName("adbe.pkcs7.detached")) {
    signature_type = adbe_pkcs7_detached;
    signature_info->setSubFilterSupport(true);
  }
  else if (subfilterName.isName("ETSI.CAdES.detached")) {
    signature_type = ETSI_CAdES_detached;
    signature_info->setSubFilterSupport(true);
  }
}

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
}

FormSignatureType FormWidgetSignature::signatureType()
{
  return static_cast<FormFieldSignature*>(field)->signature_type;
}

SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime)
{
#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 = byte_range.arrayGet(i*2);
    Object lenObj = byte_range.arrayGet(i*2+1);

    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());
  signature_info->setSubjectDN(signature_handler.getSignerSubjectDN());
  signature_info->setHashAlgorithm(signature_handler.getHashAlgorithm());

  // 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(validationTime);
  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;

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

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

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

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

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

      if (!obj2.isDict()) {
        error(errSyntaxWarning, -1, "Reference in Fields array to an invalid or non existent object");
	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);

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

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

#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;
}

// Look up an inheritable field dictionary entry.
static Object fieldLookup(Dict *field, const char *key, std::set<int> *usedParents) {
  Dict *dict = field;
  Object obj = dict->lookup(key);
  if (!obj.isNull()) {
    return obj;
  }
  Object parent = dict->lookupNF("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());
      if (obj2.isDict()) {
        return fieldLookup(obj2.getDict(), key, usedParents);
      }
    }
  } else if (parent.isDict()) {
    return fieldLookup(parent.getDict(), key, usedParents);
  }
  return Object(objNull);
}

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

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

    Object obj2 = Form::fieldLookup(obj->getDict (), "FT");
    if (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);
    }

    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);
}
