//========================================================================
//
// Form.cc
//
// Copyright 2006 Julien Rebetez
//
//========================================================================

#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(FormWidget *dest)
{
  x1 = dest->x1;
  y1 = dest->y1;
  x2 = dest->x2;
  y2 = dest->x2;

  type = dest->type;
  field = dest->field;
}

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 ("V", 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()) {
          Stream *str = obj2.getStream();
          Dict *tmpDict2 = str->getDict();
          Object obj3;
          tmpDict2->lookup("Length", &obj3);
          onStr = new GooString ("D");
        }
        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");
    }
  }

  if (Form::fieldLookup(dict, "V", &obj1)->isName()) {
    if (strcmp (obj1.getName(), "Off") != 0) {
      setState(gTrue);
    }
  } 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(0, &obj4);
        parent->_setChoiceExportVal(i, obj3.getString()->copy());
        parent->_setChoiceOptionName(i, obj4.getString()->copy());
        obj3.free();
        obj4.free();
      } else {
        error(-1, "FormWidgetChoice:: invalid Opt entry\n");
      }
      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->getExportVal(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->getExportVal(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 & 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]->loadChildrenDefaults();
  }
}


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

      //Mark readonly field
      Object obj3;
      if (Form::fieldLookup(obj2.getDict (), "Ff", &obj3)->isInt()) {
        int flags = obj3.getInt();
        if (flags & 0x1)
          rootFields[numFields-1]->setReadOnly(true);
      }
      obj3.free();

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