//========================================================================
//
// Form.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
// Copyright 2007-2010 Albert Astals Cid <aacid@kde.org>
// Copyright 2007-2008 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright 2007 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
// Copyright 2008 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>
// 
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#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 "Form.h"
#include "XRef.h"
#include "PDFDocEncoding.h"
#include "Annot.h"
#include "Catalog.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;
}



FormWidget::FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA) 
{
  Object obj1, obj2;
  ref = aref;
  double t;
  ID = 0;
  defaultsLoaded = gFalse;
  fontSize = 0.0;
  modified = gFalse;
  childNum = num;
  xref = xrefA;
  aobj->copy(&obj);
  type = formUndef;
  field = fieldA;
  Dict *dict = obj.getDict();

  if (!dict->lookup("Rect", &obj1)->isArray()) {
    error(-1, "Annotation rectangle is wrong type");
    goto err2;
  }
  if (!obj1.arrayGet(0, &obj2)->isNum()) {
    error(-1, "Bad annotation rectangle");
    goto err1;
  }
  x1 = obj2.getNum();
  obj2.free();
  if (!obj1.arrayGet(1, &obj2)->isNum()) {
    error(-1, "Bad annotation rectangle");
    goto err1;
  }
  y1 = obj2.getNum();
  obj2.free();
  if (!obj1.arrayGet(2, &obj2)->isNum()) {
    error(-1, "Bad annotation rectangle");
    goto err1;
  }
  x2 = obj2.getNum();
  obj2.free();
  if (!obj1.arrayGet(3, &obj2)->isNum()) {
    error(-1, "Bad annotation rectangle");
    goto err1;
  }
  y2 = obj2.getNum();
  obj2.free();
  obj1.free();
  //swap coords if needed
  if (x1 > x2) {
    t = x1;
    x1 = x2;
    x2 = t;
  }
  if (y1 > y2) {
    t = y1;
    y1 = y2;
    y2 = t;
  }
  
  err1:
    obj2.free();  
  err2:
    obj1.free();
}

FormWidget::~FormWidget()
{
  obj.free ();
}

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

void FormWidget::updateField (const char *key, Object *value)
{
  Object *obj1;
  Ref ref1;
  Object obj2;

  if (obj.getDict()->lookup ("FT", &obj2)->isName ()) {
    // It's a composed (annot + field) dict
    obj1 = &obj;
    ref1 = ref;
  } else {
    // It's an annot dict, we have to modify the Field (parent) dict
    obj1 = field->getObj ();
    ref1 = field->getRef ();
  }
  obj2.free ();

  obj1->getDict ()->set (const_cast<char*>(key), value);
  //notify the xref about the update
  xref->setModifiedObject(obj1, ref1);
}

FormWidgetButton::FormWidgetButton (XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(xrefA, aobj, num, ref, p)
{
  type = formButton;
  parent = static_cast<FormFieldButton*>(field);
  onStr = NULL;
  state = gFalse;
  siblingsID = NULL;
  numSiblingsID = 0;
}

FormWidgetButton::~FormWidgetButton ()
{
  if (siblingsID)
    gfree(siblingsID);
  delete onStr;
}

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

void FormWidgetButton::setState (GBool astate, GBool calledByParent)
{
  //pushButtons don't have state
  if (parent->getButtonType() == formButtonPush)
    return;
  //the state modification may be denied by the parent. e.g we don't want to let the user put all combo boxes to false
  if (!calledByParent) { //avoid infinite recursion
    modified = gTrue;
    if (!parent->setState(childNum, astate)) {
      return;
    }
  }
  state = astate;
  
  //update appearance
  char *offStr = "Off";
  Object obj1;
  obj1.initName(state?getOnStr():offStr);
  updateField ("V", &obj1);

  obj1.initName(state?getOnStr():offStr);
  //modify the Appearance State entry as well
  obj.getDict()->set("AS", &obj1);
  //notify the xref about the update
  xref->setModifiedObject(&obj, ref);
}

void FormWidgetButton::loadDefaults ()
{
  if (defaultsLoaded)
    return;

  defaultsLoaded = gTrue;

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

  //pushButtons don't have state
  if (parent->getButtonType() != formButtonPush ){
    //find the name of the state in the AP dictionnary (/Yes, /Off)
    //The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
    //The "on" state may be stored under any other name
    if (dict->lookup("AP", &obj1)->isDict()) {
      Dict *tmpDict = obj1.getDict();
      int length = tmpDict->getLength();
      for(int i=0; i<length; i++) {
        Object obj2;
        tmpDict->getVal(i, &obj2);
        if (obj2.isDict()) {
          Dict *tmpDict2 = obj2.getDict();
          int length2 = tmpDict2->getLength();
          for(int j=0; j<length2; j++) {
            Object obj3;
            tmpDict2->getVal(j, &obj3);
            char *key = tmpDict2->getKey(j);
            if(strcmp(key, "Off")) { //if we don't have Off, we have the name of the "on" state
	      onStr = new GooString (key);
            }
            obj3.free();
	    if (onStr)
	      break;
          }
        } else if (obj2.isStream()) {
          // TODO do something with str and obj3
          Stream *str = obj2.getStream();
          Dict *tmpDict2 = str->getDict();
          Object obj3;
          tmpDict2->lookup("Length", &obj3);
          onStr = new GooString ("D");
          obj3.free();
        }
        obj2.free();
	if (onStr)
	  break;
      }
    }
    obj1.free();

    //We didn't found the "on" state for the button
    if (!onStr) {
      error(-1, "FormWidgetButton:: unable to find the on state for the button\n");
      onStr = new GooString(""); // TODO is this the best solution?
    }
  }

  if (Form::fieldLookup(dict, "V", &obj1)->isName()) {
    Object obj2;
    if (dict->lookup("AS", &obj2)->isName(obj1.getName())) {
      if (strcmp (obj1.getName(), "Off") != 0) {
        setState(gTrue);
      }
    }
    obj2.free();
  } else if (obj1.isArray()) { //handle the case where we have multiple choices
    error(-1, "FormWidgetButton:: multiple choice isn't supported yet\n");
  }
  obj1.free();
}

GBool FormWidgetButton::getState ()
{
  return state;
}

void FormWidgetButton::setNumSiblingsID (int i)
{ 
  numSiblingsID = i; 
  siblingsID = (unsigned*)greallocn(siblingsID, numSiblingsID, sizeof(unsigned));
}


FormWidgetText::FormWidgetText (XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(xrefA, aobj, num, ref, p)
{
  type = formText;
  parent = static_cast<FormFieldText*>(field);
}

void FormWidgetText::loadDefaults ()
{
  if (defaultsLoaded)
    return;

  defaultsLoaded = gTrue;

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

  if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
    if (obj1.getString()->hasUnicodeMarker()) {
      if (obj1.getString()->getLength() <= 2) {
      } else {
        parent->setContentCopy(obj1.getString());
      }
    } 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);
        GooString* str1 = new GooString(tmp_str, tmp_length);
        parent->setContentCopy(str1);
        delete str1;
	delete []tmp_str;
      }
    }
  }
  obj1.free();

}

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

GooString* FormWidgetText::getContentCopy ()
{
  return parent->getContentCopy();
}
  
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)
{
  if (isReadOnly()) {
    error(-1, "FormWidgetText::setContentCopy called on a read only field\n");
    return;
  }

  modified = gTrue;
  if (new_content == NULL) {
    parent->setContentCopy(NULL);
  } else {
    //append the unicode marker <FE FF> if needed
    if (!new_content->hasUnicodeMarker()) {
      new_content->insert(0, 0xff);
      new_content->insert(0, 0xfe);
    }
    
    GooString *cont = new GooString(new_content);
    parent->setContentCopy(cont);
    
    Object obj1;
    obj1.initString(cont);
    updateField ("V", &obj1);
  }
}

FormWidgetChoice::FormWidgetChoice(XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(xrefA, aobj, num, ref, p)
{
  type = formChoice;
  parent = static_cast<FormFieldChoice*>(field);
}

void FormWidgetChoice::loadDefaults ()
{
  if (defaultsLoaded)
    return;

  defaultsLoaded = gTrue;

  Dict *dict = obj.getDict();
  Object obj1;
  if (dict->lookup("Opt", &obj1)->isArray()) {
    Object obj2;
    parent->_setNumChoices(obj1.arrayGetLength());
    parent->_createChoicesTab();
    for(int i=0; i<parent->getNumChoices(); i++) {
      obj1.arrayGet(i, &obj2);
      if(obj2.isString()) {
        parent->_setChoiceExportVal(i, obj2.getString()->copy());
        parent->_setChoiceOptionName(i, obj2.getString()->copy());
      } else if (obj2.isArray()) { // [Export_value, Displayed_text]
        Object obj3,obj4;
        if (obj2.arrayGetLength() < 2) {
          error(-1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
          parent->_setChoiceExportVal(i, new GooString(""));
          parent->_setChoiceOptionName(i, new GooString(""));
          continue;
        }
        obj2.arrayGet(0, &obj3);
        obj2.arrayGet(1, &obj4);
        parent->_setChoiceExportVal(i, obj3.getString()->copy());
        parent->_setChoiceOptionName(i, obj4.getString()->copy());
        obj3.free();
        obj4.free();
      } else {
        error(-1, "FormWidgetChoice:: invalid %d Opt entry\n", i);
        parent->_setChoiceExportVal(i, new GooString(""));
        parent->_setChoiceOptionName(i, new GooString(""));
      }
      obj2.free();
    }
  } else {
    //empty choice
  }
  obj1.free();

  bool* tmpCurrentChoice = new bool[parent->getNumChoices()];
  memset(tmpCurrentChoice, 0, sizeof(bool)*parent->getNumChoices());

  //find default choice
  if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
    for(int i=0; i<parent->getNumChoices(); i++) {
      if (parent->getChoice(i)->cmp(obj1.getString()) == 0) {
        tmpCurrentChoice[i] = true;
        break;
      }
    }
  } else if (obj1.isArray()) {
    for(int i=0; i<obj1.arrayGetLength(); i++) {
      Object obj2;
      obj1.arrayGet(i, &obj2);
      for(int j=0; j<parent->getNumChoices(); j++) {
        if (parent->getChoice(j)->cmp(obj2.getString()) == 0) {
          tmpCurrentChoice[i] = true;
        }
      }

      obj2.free();
    }
  }
  obj1.free();

  //convert choice's human readable strings to UTF16
  //and update the /Opt dict entry to reflect this change
#ifdef UPDATE_OPT
  Object *objOpt = new Object();
  objOpt->initArray(xref);
#endif
  for(int i=0; i<parent->getNumChoices(); i++) {
        if (parent->getChoice(i)->hasUnicodeMarker()) { //string already in UTF16, do nothing

        } else { //string in pdfdocencoding, convert to UTF16
          int len;
          char* buffer = pdfDocEncodingToUTF16(parent->getChoice(i), &len);
          parent->getChoice(i)->Set(buffer, len);
          delete [] buffer;
        }
        #ifdef UPDATE_OPT
        Object *obj2 = new Object();
        obj2->initString(choices[i]);
        objOpt->getArray()->add(obj2);  
        #endif
  }
  //set default choice now that we have UTF16 strings
  for (int i=0; i<parent->getNumChoices(); i++) {
    if (tmpCurrentChoice[i])
      parent->select(i);
  }
#ifdef UPDATE_OPT
  updateField ("Opt", objOpt);
#endif
  delete [] tmpCurrentChoice;
}

FormWidgetChoice::~FormWidgetChoice()
{
}

void FormWidgetChoice::_updateV ()
{
  Object obj1;
  //this is an editable combo-box with user-entered text
  if (hasEdit() && parent->getEditChoice()) { 
    obj1.initString(new GooString(parent->getEditChoice()));
  } else {
    int numSelected = parent->getNumSelected();
    if (numSelected == 0) {
      obj1.initString(new GooString(""));
    } else if (numSelected == 1) {
      for(int i=0; i<parent->getNumChoices(); i++) {
        if (parent->isSelected(i)) {
          obj1.initString(new GooString(parent->getChoice(i)));
          break;
        }
      }
    } else {
      obj1.initArray(xref);
      for(int i=0; i<parent->getNumChoices(); i++) {
        if (parent->isSelected(i)) {
          Object obj2;
          obj2.initString(new GooString(parent->getChoice(i)));
          obj1.arrayAdd(&obj2);
        }
      }
    }
  }
  updateField ("V", &obj1);
  modified = gTrue;
}

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

void FormWidgetChoice::select (int i)
{
  if (isReadOnly()) {
    error(-1, "FormWidgetChoice::select called on a read only field\n");
    return;
  }
  if (!_checkRange(i)) return;
  modified = gTrue;
  parent->select(i);
  _updateV();
}

void FormWidgetChoice::toggle (int i)
{
  if (isReadOnly()) {
    error(-1, "FormWidgetChoice::toggle called on a read only field\n");
    return;
  }
  if (!_checkRange(i)) return;
  modified = gTrue;
  parent->toggle(i);
  _updateV();
}

void FormWidgetChoice::deselectAll ()
{
  if (isReadOnly()) {
    error(-1, "FormWidgetChoice::deselectAll called on a read only field\n");
    return;
  }
  modified = gTrue;
  parent->deselectAll();
  _updateV();
}

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

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

void FormWidgetChoice::setEditChoice (GooString* new_content)
{
  if (isReadOnly()) {
    error(-1, "FormWidgetText::setEditChoice called on a read only field\n");
    return;
  }
  if (!hasEdit()) {
    error(-1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
    return;
  }

  modified = gTrue;
  if (new_content == NULL) {
    parent->setEditChoice(NULL);
  } else {
    //append the unicode marker <FE FF> if needed
    if (!new_content->hasUnicodeMarker()) {
      new_content->insert(0, 0xff);
      new_content->insert(0, 0xfe);
    }
    parent->setEditChoice(new_content);
  }
  _updateV();
}

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

FormWidgetSignature::FormWidgetSignature(XRef *xrefA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(xrefA, aobj, num, ref, p)
{
  type = formSignature;
  parent = static_cast<FormFieldSignature*>(field);
}


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

FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, FormFieldType ty) 
{
  xref = xrefA;
  aobj->copy(&obj);
  Dict* dict = obj.getDict();
  ref.num = ref.gen = 0;
  type = ty;
  numChildren = 0;
  children = NULL;
  terminal = false;
  widgets = NULL;
  readOnly = false;
  ref = aref;

  Object obj1;
  //childs
  if (dict->lookup("Kids", &obj1)->isArray()) {
    Array *array = obj1.getArray();
    int length = array->getLength();
    // Load children
    for(int i=0; i<length; i++) { 
      Object obj2,obj3;
      Object childRef;
      array->get(i, &obj2);
      array->getNF(i, &childRef);
      if (!obj2.isDict ()) {
	      error (-1, "Reference to an invalid or non existant object");
	      continue;
      }
      //field child
      if (dict->lookup ("FT", &obj3)->isName()) {
        // If I'm not a generic container field and my children
        // are widgets, create widgets for them
        Object obj4;

	if (obj2.dictLookup("Subtype",&obj4)->isName()) {
	  _createWidget(&obj2, childRef.getRef());
	}
        obj4.free();
      } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
        if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");

        numChildren++;
        children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));

        obj3.free();
	children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef());
      }
      // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
      // as if the annot was in the Kids array of the field
      else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
        _createWidget(&obj2, childRef.getRef());
      }
      obj2.free();
      obj3.free();
    }
  }
  obj1.free();
  // As said in 1, if this is a 'collapsed' field, behave like if we had a
  // child annot
  if (dict->lookup("Subtype", &obj1)->isName()) {
    _createWidget(aobj, ref);
  }
  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();
}

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

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

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


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(xref, obj, numChildren-1, aref, this);
    break;
  case formText:
    widgets[numChildren-1] = new FormWidgetText(xref, obj, numChildren-1, aref, this);
    break;
  case formChoice:
    widgets[numChildren-1] = new FormWidgetChoice(xref, obj, numChildren-1, aref, this);
    break;
  case formSignature:
    widgets[numChildren-1] = new FormWidgetSignature(xref, obj, numChildren-1, aref, this);
    break;
  default:
    error(-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;
}


//------------------------------------------------------------------------
// FormFieldButton
//------------------------------------------------------------------------
FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref) 
	: FormField(xrefA, aobj, ref, formButton)
{
  Dict* dict = obj.getDict();
  active_child = -1;
  noAllOff = false;

  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(-1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
    } 
  }
}

void FormFieldButton::fillChildrenSiblingsID()
{
  if (!terminal) {
    for(int i=0; i<numChildren; i++) {
      children[i]->fillChildrenSiblingsID();
    }
  } else {
    for(int i=0; i<numChildren; i++) {
      FormWidgetButton *btn = static_cast<FormWidgetButton*>(widgets[i]);
      btn->setNumSiblingsID(numChildren-1);
      for(int j=0, counter=0; j<numChildren; j++) {
        if (i == j) continue;
        btn->setSiblingsID(counter, widgets[j]->getID());
        counter++;
      }
    }
  }
}

GBool FormFieldButton::setState (int num, GBool s) 
{
  if (readOnly) {
    error(-1, "FormFieldButton::setState called on a readOnly field\n");
    return gFalse;
  }

  // A check button could behave as a radio button
  // when it's in a set of more than 1 buttons
  if (btype == formButtonRadio || btype == formButtonCheck) {
    if (!s && noAllOff)
      return gFalse; //don't allow to set all radio to off

    if (s == gTrue) {
      active_child = num;
      for(int i=0; i<numChildren; i++) {
        if (i==active_child) continue;
        static_cast<FormWidgetButton*>(widgets[i])->setState(gFalse, gTrue);
      }

      //The parent field's V entry holds a name object corresponding to the ap-
      //pearance state of whichever child field is currently in the on state
      if (active_child >= 0) {
        FormWidgetButton* actChild = static_cast<FormWidgetButton*>(widgets[active_child]);
        if (actChild->getOnStr()) {
          Object obj1;
          obj1.initName(actChild->getOnStr());
	  obj.getDict()->set("V", &obj1);
	  xref->setModifiedObject(&obj, ref);
        }
      }
    } else {
      active_child = -1;
      Object obj1;
      obj1.initName("Off");
      obj.getDict()->set("V", &obj1);
      xref->setModifiedObject(&obj, ref);
    }
  }
  return gTrue;
}

FormFieldButton::~FormFieldButton()
{
}

//------------------------------------------------------------------------
// FormFieldText
//------------------------------------------------------------------------
FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref) 
	: FormField(xrefA, aobj, ref, 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();
}

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

void FormFieldText::setContentCopy (GooString* new_content)
{
  if(content) {
    delete content; 
  }
  content = new_content->copy();
}

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


//------------------------------------------------------------------------
// FormFieldChoice
//------------------------------------------------------------------------
FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref) 
	: FormField(xrefA, aobj, ref, formChoice)
{
  numChoices = 0;
  choices = NULL;
  editedChoice = NULL;

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

}

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

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

void FormFieldChoice::toggle (int i)
{
  choices[i].selected = !choices[i].selected;
}

void FormFieldChoice::select (int i)
{
  if (!multiselect) 
    deselectAll();
  choices[i].selected = true;
}

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

  deselectAll();

  editedChoice = new_content->copy();
}

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

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

//------------------------------------------------------------------------
// FormFieldSignature
//------------------------------------------------------------------------
FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref)
	: FormField(xrefA, dict, ref, formSignature)
{
}

FormFieldSignature::~FormFieldSignature()
{

}

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

Form::Form(XRef *xrefA, Object* acroFormA)
{
  Object obj1;

  xref = xrefA;
  acroForm = acroFormA;
  
  size = 0;
  numFields = 0;
  rootFields = NULL;

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

  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(-1, "Direct object in rootFields");
	obj2.free();
	oref.free();
        continue;
      }

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

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

      rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef());

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

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

// Look up an inheritable field dictionary entry.
Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
  Dict *dict;
  Object parent;

  dict = field;
  if (!dict->lookup(key, obj)->isNull()) {
    return obj;
  }
  obj->free();
  if (dict->lookup("Parent", &parent)->isDict()) {
    fieldLookup(parent.getDict(), key, obj);
  } else {
    obj->initNull();
  }
  parent.free();
  return obj;
}

FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref)
{
    Object obj2;
    FormField *field;

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

    return field;
}

void Form::postWidgetsLoad ()
{
 for(int i=0; i<numFields; i++) {
   rootFields[i]->fillChildrenSiblingsID(); 
 }
}

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 (XRef *xrefA, Object* annots, unsigned int page, Form *form)
{
  Object obj1;
  numWidgets = 0;
  widgets = NULL;
  xref = xrefA;
  if (annots->isArray() && form) {
    size = annots->arrayGetLength();
    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) {
      if (!annots->arrayGetNF(i, &obj1)->isRef())  {
        /* 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 */
        obj1.free();
        continue;
      }
      Ref r = obj1.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;
        //create a temporary Annot to get the font size
        Object obj2;
        if (annots->arrayGet(i, &obj2)->isDict()) {
          Annot *ann;
	  
          ann = new Annot(xref, obj2.getDict(), NULL);
          tmp->setFontSize(ann->getFontSize());
          delete ann;
        }
        obj2.free();
      } 
      
      obj1.free();
    }
  } 
}

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