/* This file is part of the KDE project
   Copyright (C) 1999 David Faure <faure@kde.org>
   Copyright (C) 2005 Laurent Montel <montel@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

/* GNUmeric import filter by Phillip Ezolt 6-2-2001 */
/*                        phillipezolt@hotmail.com  */
/* additions: Norbert Andres nandres@web.de         */

#include <tqdict.h>
#include <tqfile.h>
#include <tqstringlist.h>

#include <gnumericimport.h>
#include <tdemessagebox.h>
#include <kfilterdev.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <KoFilterChain.h>
#include <KoGlobal.h>

// hehe >:->
#include <kspread_doc.h>
#include <kspread_map.h>
#include <kspread_sheet.h>
#include <kspread_sheetprint.h>
#include <kspread_cell.h>
#include <kspread_util.h>
#include <KoDocumentInfo.h>

#include <math.h>

#define SECS_PER_DAY 86400
#define HALF_SEC (0.5 / SECS_PER_DAY)

using namespace KSpread;

// copied from gnumeric: src/format.c:
static const int g_dateSerial_19000228 = 59;
/* One less that the Julian day number of 19000101.  */
static int g_dateOrigin = 0;

// copied from gnumeric: src/formats.c:
static char const * cell_format_date [] = {
	"m/d/yy",		/* 0 Cell::date_format5*/
	"m/d/yyyy",		/* 1 Cell::date_format6*/
	"d-mmm-yy",		/* 2 Cell::date_format1 18-Feb-99 */
	"d-mmm-yyyy",		/* 3 Cell::date_format2 18-Feb-1999 */
	"d-mmm",		/* 4 Cell::date_format3 18-Feb */
	"d-mm",			/* 5 Cell::date_format4 18-05 */
	"mmm/d",		/* 6 Cell::date_format11*/
	"mm/d",			/* 7 Cell::date_format12*/
	"mm/dd/yy",		/* 8 Cell::date_format19*/
	"mm/dd/yyyy",		/* 9 Cell::date_format18*/
	"mmm/dd/yy",		/* 10 Cell::date_format20*/
	"mmm/dd/yyyy",		/* 11 Cell::date_format21*/
	"mmm/ddd/yy",		/* 12 */
	"mmm/ddd/yyyy",		/* 13 */
	"mm/ddd/yy",		/* 14 */
	"mm/ddd/yyyy",		/* 15 */
	"mmm-yy",		/* 16 Cell::date_format7*/
	"mmm-yyyy",		/* 17 Cell::date_format22*/
	"mmmm-yy",		/* 18 Cell::date_format8*/
	"mmmm-yyyy",		/* 19 Cell::date_format9*/
	"m/d/yy h:mm",		/* 20 */
	"m/d/yyyy h:mm",	/* 21 */
	"yyyy/mm/d",		/* 22 Cell::date_format25*/
	"yyyy/mmm/d",		/* 23 Cell::date_format14*/
	"yyyy/mm/dd",		/* 24 Cell::date_format25*/
	"yyyy/mmm/dd",		/* 25 Cell::date_format26*/
	"yyyy-mm-d",		/* 26 Cell::date_format16*/
	"yyyy-mmm-d",		/* 27 Cell::date_format15*/
	"yyyy-mm-dd",		/* 28 Cell::date_format16*/
	"yyyy-mmm-dd",		/* 29 Cell::date_format15*/
	"yy",			/* 30 Cell::date_format24*/
	"yyyy",			/* 31 Cell::date_format23*/
	NULL
};

// copied from gnumeric: src/formats.c:
static char const * cell_format_time [] = {
  "h:mm AM/PM",    // Cell::Time_format1 9 : 01 AM
  "h:mm:ss AM/PM", // Cell::Time_format2 9:01:05 AM
  "h:mm",          // Cell::Time_format4 9:01
  "h:mm:ss",       // Cell::Time_format5 9:01:12
  "m/d/yy h:mm",
  "mm:ss",         // Cell::Time_format6 01:12
  "mm:ss.0",       // Cell::Time_format6 01:12
  "[h]:mm:ss",
  "[h]:mm",
  "[mm]:ss",
  "[ss]",
  NULL
};

namespace gnumeric_import_LNS
{
  TQStringList list1;
  TQStringList list2;
}

using namespace gnumeric_import_LNS;

void GNUMERICFilter::dateInit()
{
  // idea copied form gnumeric src/format.c:
  /* Day 1 means 1st of January of 1900 */
  g_dateOrigin = GnumericDate::greg2jul( 1900, 1, 1 ) - 1;
}

uint GNUMERICFilter::GnumericDate::greg2jul( int y, int m, int d )
{
  return TQDate::gregorianToJulian( y, m, d );
}

void GNUMERICFilter::GnumericDate::jul2greg( double num, int & y, int & m, int & d )
{
  int i = (int) floor( num + HALF_SEC );
  if (i > g_dateSerial_19000228)
    --i;
  else if (i == g_dateSerial_19000228 + 1)
    kdWarning(30521) << "Request for date 02/29/1900." << endl;

  kdDebug(30521) << "***** Num: " << num << ", i: " << i  << endl;

  TQDate::julianToGregorian( i + g_dateOrigin, y, m, d );
  kdDebug(30521) << "y: " << y << ", m: " << m << ", d: " << d << endl;
}

TQTime GNUMERICFilter::GnumericDate::getTime( double num )
{
  // idea copied from gnumeric: src/datetime.c
  num += HALF_SEC;
  int secs = tqRound( (num - floor(num)) * SECS_PER_DAY );

  kdDebug(30521) << "***** Num: " << num << ", secs " << secs << endl;

  const int h = secs / 3600;
  secs -= h * 3600;
  const int m = secs / 60;
  secs -= h * 60;

  kdDebug(30521) << "****** h: " << h << ", m: " << m << ", secs: " << secs << endl;
  const TQTime time( h, m, ( secs < 0 || secs > 59 ? 0 : secs ) );

  return time;
}

typedef KGenericFactory<GNUMERICFilter, KoFilter> GNUMERICFilterFactory;
K_EXPORT_COMPONENT_FACTORY( libgnumericimport, GNUMERICFilterFactory( "kofficefilters" ) )

GNUMERICFilter::GNUMERICFilter( KoFilter *, const char *, const TQStringList & )
  : KoFilter()
{
}

/* This converts GNUmeric's color string "0:0:0" to a TQColor. */
void  convert_string_to_qcolor(TQString color_string, TQColor * color)
{
  int red, green, blue, first_col_pos, second_col_pos;

  bool number_ok;

  first_col_pos  = color_string.find(":", 0);
  second_col_pos = color_string.find(":", first_col_pos + 1);

  /* Fore="0:0:FF00" */
  /* If GNUmeric kicks out some invalid colors, we could crash. */
  /* GNUmeric gives us two bytes of color data per element. */
  /* We only care about the top byte. */

  red   = color_string.mid( 0, first_col_pos).toInt( &number_ok, 16 ) >> 8;
  green = color_string.mid(first_col_pos + 1,
                           (second_col_pos-first_col_pos) - 1).toInt( &number_ok, 16) >> 8;
  blue  = color_string.mid(second_col_pos + 1,
                           (color_string.length() - first_col_pos) - 1).toInt( &number_ok, 16) >> 8;
  color->setRgb(red, green, blue);
}

void areaNames( Doc * ksdoc, const TQString &_name, TQString _zone )
{
//Sheet2!$A$2:$D$8
    TQString tableName;
    int pos = _zone.find( '!' );
    if ( pos != -1 )
    {
        tableName = _zone.left( pos );
        _zone = _zone.right( _zone.length()-pos-1 );
         pos = _zone.find( ':' );
        TQRect rect;
        if ( pos != -1 )
        {
            TQString left = _zone.mid( 1, pos-1 );
            TQString right = _zone.mid( pos+2, _zone.length()-pos-2 );
            int pos = left.find( '$' );

            rect.setLeft( util_decodeColumnLabelText(left.left(pos ) ) );
            rect.setTop( left.right( left.length()-pos-1 ).toInt() );

            pos = right.find( '$' );
            rect.setRight( util_decodeColumnLabelText(right.left(pos ) ) );
            rect.setBottom( right.right( right.length()-pos-1 ).toInt() );
       }
        else
        {
            TQString left = _zone;
            int pos = left.find( '$' );
            int leftPos = util_decodeColumnLabelText(left.left(pos ) );
            rect.setLeft( leftPos );
            rect.setRight( leftPos );

            int top = left.right( left.length()-pos-1 ).toInt();
            rect.setTop( top );
            rect.setBottom( top );
        }
        ksdoc->addAreaName( rect, _name ,tableName);
    }
}


void set_document_area_names( Doc * ksdoc, TQDomElement * docElem )
{
    TQDomNode areaNamesElement = docElem->namedItem( "gmr:Names" );
    if ( areaNamesElement.isNull() )
        return;
    TQDomNode areaNameItem = areaNamesElement.namedItem( "gmr:Name" );
    while ( !areaNameItem.isNull() )
    {
        TQDomNode gmr_name  = areaNameItem.namedItem("gmr:name");
        TQDomNode gmr_value = areaNameItem.namedItem("gmr:value");
        TQString name = gmr_name.toElement().text();
        areaNames( ksdoc, name, gmr_value.toElement().text() );
        areaNameItem = areaNameItem.nextSibling();
    }
}



void set_document_attributes( Doc * ksdoc, TQDomElement * docElem)
{
    ksdoc->loadConfigFromFile();
    TQDomNode attributes  = docElem->namedItem("gmr:Attributes");
    if ( attributes.isNull() )
        return;

    TQDomNode attributeItem = attributes.namedItem("gmr:Attribute");
    while( !attributeItem.isNull() )
    {
        TQDomNode gmr_name  = attributeItem.namedItem("gmr:name");
        TQDomNode gmr_value = attributeItem.namedItem("gmr:value");
        if (gmr_name.toElement().text() == "WorkbookView::show_horizontal_scrollbar")
        {
            ksdoc->setShowHorizontalScrollBar( gmr_value.toElement().text().lower()=="true"? true : false );
        }
        else if ( gmr_name.toElement().text() == "WorkbookView::show_vertical_scrollbar")
        {
            ksdoc->setShowVerticalScrollBar( gmr_value.toElement().text().lower()=="true"? true : false );
        }
        else if ( gmr_name.toElement().text() == "WorkbookView::show_notebook_tabs")
        {
            ksdoc->setShowTabBar(gmr_value.toElement().text().lower()=="true"? true : false );
        }
        else if ( gmr_name.toElement().text() == "WorkbookView::do_auto_completion")
        {
            ksdoc->setCompletionMode( TDEGlobalSettings::CompletionAuto);
        }
        else if ( gmr_name.toElement().text() == "WorkbookView::is_protected")
        {
            //TODO protect document ???
            //ksdoc->map()->isProtected()
        }

        attributeItem = attributeItem.nextSibling();
    }
}

/* This sets the documentation information from the information stored in
   the GNUmeric file. Particularly in the "gmr:Summary" subcategory.
*/
void set_document_info(KoDocument * document, TQDomElement * docElem)
{
  /* Summary Handling START */
  TQDomNode summary  = docElem->namedItem("gmr:Summary");
  TQDomNode gmr_item = summary.namedItem("gmr:Item");

  while( !gmr_item.isNull() )
  {
    TQDomNode gmr_name  = gmr_item.namedItem("gmr:name");
    TQDomNode gmr_value = gmr_item.namedItem("gmr:val-string");

    KoDocumentInfo * DocumentInfo     = document->documentInfo();
    KoDocumentInfoAbout  * aboutPage  = static_cast<KoDocumentInfoAbout *>(DocumentInfo->page( "about" ));
    KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(DocumentInfo->page( "author" ));


    if (gmr_name.toElement().text() == "title")
    {
      aboutPage->setTitle(gmr_value.toElement().text());
    }
    else if (gmr_name.toElement().text() == "keywords")
    {
        aboutPage->setKeywords( gmr_value.toElement().text());
    }
    else if (gmr_name.toElement().text() == "comments")
    {
      aboutPage->setAbstract(gmr_value.toElement().text());
    }
    else if (gmr_name.toElement().text() == "category")
    {
      /* Not supported by KSpread */
    }
    else if (gmr_name.toElement().text() == "manager")
    {
      /* Not supported by KSpread */
    }
    else if (gmr_name.toElement().text() == "application")
    {
      /* Not supported by KSpread */
    }
    else if (gmr_name.toElement().text() == "author")
    {
      authorPage->setFullName(gmr_value.toElement().text());
    }
    else if (gmr_name.toElement().text() == "company")
    {
      authorPage->setCompany(gmr_value.toElement().text());
    }

    gmr_item = gmr_item.nextSibling();
  }

  /* Summany Handling STOP */
}


void setColInfo(TQDomNode * sheet, Sheet * table)
{
  TQDomNode columns =  sheet->namedItem("gmr:Cols");
  TQDomNode columninfo = columns.namedItem("gmr:ColInfo");

  TQDomElement def = columns.toElement();
  if ( def.hasAttribute( "DefaultSizePts" ) )
  {
    bool ok = false;
    double d = def.attribute( "DefaultSizePts" ).toDouble( &ok );
    if ( ok )
    {
      Format::setGlobalColWidth( d );
      table->setDefaultWidth( d );
    }
  }

  while( !columninfo.isNull() )
  {
    TQDomElement e = columninfo.toElement(); // try to convert the node to an element.
    int column_number;

    column_number = e.attribute("No").toInt()+1;
    ColumnFormat *cl = new ColumnFormat(table, column_number);
    if (e.hasAttribute("Hidden"))
    {
      if (e.attribute("Hidden")=="1")
      {
        cl->setHide(true);
      }
    }
    if (e.hasAttribute("Unit"))
    {
      //  xmm = (x_points) * (1 inch / 72 points) * (25.4 mm/ 1 inch)
      cl->setDblWidth(e.attribute("Unit").toDouble());
      //cl->setWidth(e.attribute("Unit").toInt());
    }
    table->insertColumnFormat(cl);
    columninfo = columninfo.nextSibling();
  }
}

void setRowInfo(TQDomNode *sheet, Sheet *table)
{
  TQDomNode rows =  sheet->namedItem("gmr:Rows");
  TQDomNode rowinfo = rows.namedItem("gmr:RowInfo");

  double d;
  bool ok = false;

  TQDomElement def = rows.toElement();
  if ( def.hasAttribute( "DefaultSizePts" ) )
  {
    d = def.attribute( "DefaultSizePts" ).toDouble( &ok );
    if ( ok )
    {
      Format::setGlobalRowHeight( d );
      table->setDefaultHeight( d );
    }
  }

  while( !rowinfo.isNull() )
  {
    TQDomElement e = rowinfo.toElement(); // try to convert the node to an element.
    int row_number;
    row_number = e.attribute("No").toInt() + 1;
    RowFormat *rl = new RowFormat(table, row_number);

    if (e.hasAttribute("Hidden"))
    {
      if (e.attribute("Hidden") == "1")
      {
        rl->setHide(true);
      }
    }
    if (e.hasAttribute("Unit"))
    {
      double dbl = e.attribute( "Unit" ).toDouble( &ok );
      if ( ok )
        rl->setDblHeight( dbl );
    }
    table->insertRowFormat(rl);
    rowinfo = rowinfo.nextSibling();
  }
}

void setSelectionInfo( TQDomNode * sheet, Sheet * /* table */ )
{
  TQDomNode selections =  sheet->namedItem("gmr:Selections");
  TQDomNode selection = selections.namedItem("gmr:Selection");

  /* Kspread does not support mutiple selections.. */
  /* This code will set the selection to the last one GNUmeric's multiple
     selections. */
  while( !selection.isNull() )
  {
    TQDomElement e = selection.toElement(); // try to convert the node to an element.
    TQRect kspread_selection;

    kspread_selection.setLeft((e.attribute("startCol").toInt() + 1));
    kspread_selection.setTop((e.attribute("startRow").toInt() + 1));
    kspread_selection.setRight((e.attribute("endCol").toInt() + 1));
    kspread_selection.setBottom((e.attribute("endRow").toInt() + 1));

    /* can't set it in the table -- must set it to a view */
    //	  table->setSelection(kspread_selection);

    selection = selection.nextSibling();
  }
}


void setObjectInfo(TQDomNode * sheet, Sheet * table)
{
  TQDomNode gmr_objects =  sheet->namedItem("gmr:Objects");
  TQDomNode gmr_cellcomment = gmr_objects.namedItem("gmr:CellComment");
  while( !gmr_cellcomment.isNull() )
  {
    TQDomElement e = gmr_cellcomment.toElement(); // try to convert the node to an element.
    if (e.hasAttribute("Text"))
    {
      if (e.hasAttribute("ObjectBound"))
      {
        Point point(e.attribute("ObjectBound"));
        Cell * cell = table->nonDefaultCell( point.pos().x(), point.pos().y() );
        cell->format()->setComment(e.attribute("Text"));
      }
    }

    gmr_cellcomment  = gmr_cellcomment.nextSibling();
  }
}

void convertToPen( TQPen & pen, int style )
{
  switch( style )
  {
   case 0:
    break;
   case 1:
    pen.setStyle( Qt::SolidLine );
    pen.setWidth( 1 );
    break;
   case 2:
    pen.setStyle( Qt::SolidLine );
    pen.setWidth( 2 );
    break;
   case 3:
    pen.setStyle( Qt::DashLine );
    pen.setWidth( 1 );
    break;
   case 4:
    // width should be 1 but otherwise it would be the same as 7
    pen.setStyle( Qt::DotLine );
    pen.setWidth( 2 );
    break;
   case 5:
    pen.setStyle( Qt::SolidLine );
    pen.setWidth( 3 );
    break;
   case 6:
    // TODO should be double
    pen.setStyle( Qt::SolidLine );
    pen.setWidth( 1 );
    break;
   case 7:
    // very thin dots => no match in KSpread
    pen.setStyle( Qt::DotLine );
    pen.setWidth( 1 );
    break;
   case 8:
    pen.setStyle( Qt::DashLine );
    pen.setWidth( 2 );
    break;
   case 9:
    pen.setStyle( Qt::DashDotLine );
    pen.setWidth( 1 );
    break;
   case 10:
    pen.setStyle( Qt::DashDotLine );
    pen.setWidth( 2 );
    break;
   case 11:
    pen.setStyle( Qt::DashDotDotLine );
    pen.setWidth( 1 );
    break;
   case 12:
    pen.setStyle( Qt::DashDotDotLine );
    pen.setWidth( 2 );
    break;
   case 13:
    // TODO: long dash, short dash, long dash,...
    pen.setStyle( Qt::DashDotLine );
    pen.setWidth( 3 );
    break;
   default:
    pen.setStyle( Qt::SolidLine );
    pen.setWidth( 1 );
  }
}

void GNUMERICFilter::ParseBorder( TQDomElement & gmr_styleborder, Cell * kspread_cell )
{
  TQDomNode gmr_diagonal = gmr_styleborder.namedItem("gmr:Diagonal");
  TQDomNode gmr_rev_diagonal = gmr_styleborder.namedItem("gmr:Rev-Diagonal");
  TQDomNode gmr_top = gmr_styleborder.namedItem("gmr:Top");
  TQDomNode gmr_bottom = gmr_styleborder.namedItem("gmr:Bottom");
  TQDomNode gmr_left = gmr_styleborder.namedItem("gmr:Left");
  TQDomNode gmr_right = gmr_styleborder.namedItem("gmr:Right");

  // NoPen - no line at all. For example,
  // TQPainter::drawRect() fills but does not
  // draw any explicit boundary
  // line. SolidLine - a simple line. DashLine
  // - dashes, separated by a few
  // pixels. DotLine - dots, separated by a
  // few pixels. DashDotLine - alternately
  // dots and dashes. DashDotDotLine - one dash, two dots, one dash, two dots...

  if ( !gmr_left.isNull() )
  {
    TQDomElement e = gmr_left.toElement(); // try to convert the node to an element.
    importBorder( e, Left, kspread_cell);
   }

  if ( !gmr_right.isNull() )
  {
    TQDomElement e = gmr_right.toElement(); // try to convert the node to an element.
    importBorder( e, Right, kspread_cell);
  }

  if ( !gmr_top.isNull() )
  {
    TQDomElement e = gmr_top.toElement(); // try to convert the node to an element.
    importBorder( e, Top,  kspread_cell);
  }

  if ( !gmr_bottom.isNull() )
  {
    TQDomElement e = gmr_bottom.toElement(); // try to convert the node to an element.
    importBorder( e, Bottom, kspread_cell);
  }

  if ( !gmr_diagonal.isNull() )
  {
    TQDomElement e = gmr_diagonal.toElement(); // try to convert the node to an element.
    importBorder( e, Diagonal, kspread_cell);
  }

  if ( !gmr_rev_diagonal.isNull() )
  {
    TQDomElement e = gmr_rev_diagonal.toElement(); // try to convert the node to an element.
    importBorder( e, Revdiagonal, kspread_cell);
  }

  //  TQDomElement gmr_styleborder_element = gmr_styleborder.toElement();
}


void GNUMERICFilter::importBorder( TQDomElement border, borderStyle _style,  Cell *cell)
{
    if ( !border.isNull() )
    {
        TQDomElement e = border.toElement(); // try to convert the node to an element.
        if ( e.hasAttribute( "Style" ) )
        {
            int style = e.attribute( "Style" ).toInt();

            TQPen pen;
            convertToPen( pen, style );

            if ( style > 0 )
            {
                switch( _style )
                {
                case Left:
                    cell->setLeftBorderPen( pen );
                    break;
                case Right:
                    cell->setRightBorderPen( pen );
                    break;
                case Top:
                    cell->setTopBorderPen( pen );
                    break;
                case Bottom:
                    cell->setBottomBorderPen( pen );
                    break;
                case Diagonal:
                    cell->format()->setFallDiagonalPen( pen ); // check if this is really Fall border
                    break;
                case Revdiagonal:
                    cell->format()->setGoUpDiagonalPen( pen ); // check if this is really GoUp
                    break;
                }
            }
            if ( e.hasAttribute( "Color" ) )
            {
                TQColor color;
                TQString colorString = e.attribute( "Color" );
                convert_string_to_qcolor( colorString, &color );
                {
                    switch( _style )
                    {
                    case Left:
                        cell->format()->setLeftBorderColor( color );
                        break;
                    case Right:
                        cell->format()->setRightBorderColor( color );
                        break;
                    case Top:
                        cell->format()->setTopBorderColor( color );
                        break;
                    case Bottom:
                        cell->format()->setBottomBorderColor( color );
                        break;
                    case Diagonal:
                        cell->format()->setFallDiagonalColor( color );
                        break;
                    case Revdiagonal:
                        cell->format()->setGoUpDiagonalPen( color );
                        break;
                    }
                }
            }
        }
    }

}

bool GNUMERICFilter::setType( Cell * kspread_cell,
                              TQString const & formatString,
                              TQString & cell_content )
{
  int i = 0;
  for ( i = 0; cell_format_date[i] ; ++i )
  {
    kdDebug(30521) << "Cell_format: " << cell_format_date[i] << ", FormatString: " << formatString << endl;
    if ( ( formatString == "d/m/yy" ) || ( formatString == cell_format_date[i] ) )
    {
      kdDebug(30521) << "   FormatString: Date: " << formatString << ", CellContent: " << cell_content << endl;
      TQDate date;
      if ( !kspread_cell->isDate() )
      {
        // convert cell_content to date
        int y, m, d;
        bool ok = true;
        int val  = cell_content.toInt( &ok );

        kdDebug(30521) << "!!!   FormatString: Date: " << formatString << ", CellContent: " << cell_content
                  << ", Double: " << val << endl;
        if ( !ok )
          return false;

        GnumericDate::jul2greg( val, y, m, d );
        kdDebug(30521) << "     num: " << val << ", y: " << y << ", m: " << m << ", d: " << d << endl;

        date.setYMD( y, m, d );
      }
      else
        date = kspread_cell->value().asDate();

      FormatType type;
      switch( i )
      {
       case 0:  type = date_format5;  break;
       case 1:  type = date_format6;  break;
       case 2:  type = date_format1;  break;
       case 3:  type = date_format2;  break;
       case 4:  type = date_format3;  break;
       case 5:  type = date_format4;  break;
       case 6:  type = date_format11; break;
       case 7:  type = date_format12; break;
       case 8:  type = date_format19; break;
       case 9:  type = date_format18; break;
       case 10: type = date_format20; break;
       case 11: type = date_format21; break;
       case 16: type = date_format7;  break;
       case 17: type = date_format22; break;
       case 18: type = date_format8;  break;
       case 19: type = date_format9;  break;
       case 22: type = date_format25; break;
       case 23: type = date_format14; break;
       case 24: type = date_format25; break;
       case 25: type = date_format26; break;
       case 26: type = date_format16; break;
       case 27: type = date_format15; break;
       case 28: type = date_format16; break;
       case 29: type = date_format15; break;
       case 30: type = date_format24; break;
       case 31: type = date_format23; break;
       default:
        type = ShortDate_format;
        break;
        /* 12, 13, 14, 15, 20, 21 */
      }

      kdDebug(30521) << "i: " << i << ", Type: " << type << ", Date: " << TQString(date.toString()) << endl;

      kspread_cell->setValue( date );
      kspread_cell->format()->setFormatType( type );

      return true;
    }
  }

  for ( i = 0; cell_format_time[i] ; ++i )
  {
    if (formatString == cell_format_time[i])
    {
      TQTime time;

      if ( !kspread_cell->isTime() )
      {
        bool ok = true;
        double content = cell_content.toDouble( &ok );

        kdDebug(30521) << "   FormatString: Time: " << formatString << ", CellContent: " << cell_content
                  << ", Double: " << content << endl;

        if ( !ok )
          return false;

        time = GnumericDate::getTime( content );
      }
      else
        time = kspread_cell->value().asTime();

      FormatType type;
      switch( i )
      {
       case 0: type = Time_format1; break;
       case 1: type = Time_format2; break;
       case 2: type = Time_format4; break;
       case 3: type = Time_format5; break;
       case 5: type = Time_format6; break;
       case 6: type = Time_format6; break;
       default:
        type = Time_format1; break;
      }

      kdDebug(30521) << "i: " << i << ", Type: " << type << endl;
      kspread_cell->setValue( time );
      kspread_cell->format()->setFormatType( type );

      return true;
    }
  }

  return false; // no date or time
}

TQString GNUMERICFilter::convertVars( TQString const & str, Sheet * table ) const
{
  TQString result( str );
  uint count = list1.count();
  if ( count == 0 )
  {
    list1 << "&[TAB]" << "&[DATE]" << "&[PAGE]"
          << "&[PAGES]"<<"&[TIME]" << "&[FILE]";
    list2 << "<sheet>" << "<date>" << "<page>"
          << "<pages>" << "<time>" << "<file>";
    count = list1.count();
  }

  for ( uint i = 0; i < count; ++i )
  {
    int n = result.find( list1[i] );

    if ( n != -1 )
    {
        kdDebug(30521) << "Found var: " << list1[i] << endl;
      if ( i == 0 )
        result = result.replace( list1[i], table->tableName() );
      else
        result = result.replace( list1[i], list2[i] );
    }
  }

  return result;
}

double GNUMERICFilter::parseAttribute( const TQDomElement &_element )
{
    TQString unit = _element.attribute( "PrefUnit" );
    bool ok;
    double value = _element.attribute("Points").toFloat( &ok );
    if ( !ok )
        value = 2.0;
    if ( unit == "mm" )
        return value;
    else if ( unit == "cm" )
        return ( value/10.0 );
    else if ( unit == "in" )
        return MM_TO_INCH( value );
    else if ( unit == "Pt" || unit == "Px" || unit == "points" )
        return MM_TO_POINT( value );
    else
        return value;
}

void GNUMERICFilter::ParsePrintInfo( TQDomNode const & printInfo, Sheet * table )
{
  kdDebug(30521) << "Parsing print info " << endl;

  float fleft = 2.0;
  float fright = 2.0;
  float ftop = 2.0;
  float fbottom = 2.0;

  TQString paperSize("A4");
  TQString orientation("Portrait");
  TQString footLeft, footMiddle, footRight;
  TQString headLeft, headMiddle, headRight; // no we are zombies :-)

  TQDomNode margins( printInfo.namedItem("gmr:Margins") );
  if ( !margins.isNull() )
  {
    TQDomElement top( margins.namedItem( "gmr:top" ).toElement() );
    if ( !top.isNull() )
        ftop = parseAttribute( top );

    TQDomElement bottom( margins.namedItem( "gmr:bottom" ).toElement() );
    if ( !bottom.isNull() )
        fbottom= parseAttribute( bottom );

    TQDomElement left( margins.namedItem( "gmr:left" ).toElement() );
    if ( !left.isNull() )
        fleft = parseAttribute( left );

    TQDomElement right( margins.namedItem( "gmr:right" ).toElement() );
    if ( !right.isNull() )
        fright = parseAttribute( right );
  }

  TQDomElement foot( printInfo.namedItem("gmr:Footer").toElement() );
  if ( !foot.isNull() )
  {
    kdDebug(30521) << "Parsing footer: " << foot.attribute("Left") << ", " << foot.attribute("Middle") << ", "
              << foot.attribute("Right") << ", " <<endl;
    if ( foot.hasAttribute("Left") )
      footLeft = convertVars( foot.attribute("Left"), table );
    if ( foot.hasAttribute("Middle") )
      footMiddle = convertVars( foot.attribute("Middle"), table );
    if ( foot.hasAttribute("Right") )
      footRight = convertVars( foot.attribute("Right"), table );
  }

  TQDomElement head( printInfo.namedItem("gmr:Header").toElement() );
  if ( !head.isNull() )
  {
    kdDebug(30521) << "Parsing header: " << head.attribute("Left") << ", " << head.attribute("Middle") << ", " << head.attribute("Right") << ", "<< endl;
    if ( head.hasAttribute("Left") )
      headLeft = convertVars( head.attribute("Left"), table );
    if ( head.hasAttribute("Middle") )
      headMiddle = convertVars( head.attribute("Middle"), table );
    if ( head.hasAttribute("Right") )
      headRight = convertVars( head.attribute("Right"), table );
  }

  TQDomElement repeateColumn( printInfo.namedItem("gmr:repeat_top").toElement() );
  if ( !repeateColumn.isNull() )
  {
      TQString repeate = repeateColumn.attribute( "value" );
      if ( !repeate.isEmpty() )
      {
          Range range(repeate);
          //kdDebug()<<" repeate :"<<repeate<<"range. ::start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl;
          table->print()->setPrintRepeatRows( tqMakePair( range.startRow (),range.endRow ()) );
      }
  }

  TQDomElement repeateRow( printInfo.namedItem("gmr:repeat_left").toElement() );
  if ( !repeateRow.isNull() )
  {
      TQString repeate = repeateRow.attribute( "value" );
      if ( !repeate.isEmpty() )
      {
          //fix row too high
          repeate = repeate.replace( "65536", "32500" );
          Range range(repeate);
          //kdDebug()<<" repeate :"<<repeate<<"range. ::start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl;
          table->print()->setPrintRepeatColumns( tqMakePair( range.startCol (),range.endCol ()) );
      }
  }

  TQDomElement orient( printInfo.namedItem("gmr:orientation").toElement() );
  if ( !orient.isNull() )
    orientation = orient.text();

  TQDomElement size( printInfo.namedItem("gmr:paper").toElement() );
  if ( !size.isNull() )
    paperSize = size.text();

  table->print()->setPaperLayout( fleft, ftop, fright, fbottom,
                         paperSize, orientation );

  table->print()->setHeadFootLine( headLeft, headMiddle, headRight,
                                   footLeft, footMiddle, footRight );
}

void GNUMERICFilter::ParseFormat(TQString const & formatString, Cell * kspread_cell)
{
  int l = formatString.length();
  int lastPos = 0;

  if (formatString[l - 1] == '%')
    kspread_cell->format()->setFormatType(Percentage_format);
  else if (formatString[0] == '$')
  {
    kspread_cell->format()->setFormatType(Money_format);
    kspread_cell->format()->setCurrency( 1, "$" );
    lastPos = 1;
  }
  else if (formatString[0] == '£')
  {
    kspread_cell->format()->setFormatType(Money_format);
    kspread_cell->format()->setCurrency( 1, "£" );
    lastPos = 1;
  }
  else if (formatString[0] == '¥')
  {
    kspread_cell->format()->setFormatType(Money_format);
    kspread_cell->format()->setCurrency( 1, "¥" );
    lastPos = 1;
  }
  else if (formatString[0] == '¤')
  {
    kspread_cell->format()->setFormatType(Money_format);
    kspread_cell->format()->setCurrency( 1, "¤" );
    lastPos = 1;
  }
  else if (l > 1)
  {
    if ((formatString[0] == '[') && (formatString[1] == '$'))
    {
      int n = formatString.find(']');
      if (n != -1)
      {
        TQString currency = formatString.mid(2, n - 2);
        kspread_cell->format()->setFormatType(Money_format);
        kspread_cell->format()->setCurrency( 1, currency );
      }
      lastPos = ++n;
    }
    else if (formatString.find("E+0") != -1)
    {
      kspread_cell->format()->setFormatType(Scientific_format);
    }
    else
    {
      // do pattern matching with gnumeric formats
      TQString content(kspread_cell->value().asString());

      if ( setType(kspread_cell, formatString, content) )
        return;

      if (formatString.find("?/?") != -1)
      {
        // TODO: fixme!
        kspread_cell->format()->setFormatType( fraction_three_digits );
        return;
      }
      // so it's nothing we want to understand:-)
      return;
    }
  }

  while (formatString[lastPos] == ' ')
    ++lastPos;

  // GetPrecision and decimal point, format of negative items...

  // thousands separator
  if (formatString[lastPos] == '#')
  {
    bool sep = true;
    if (formatString[lastPos + 1] == ',')
      lastPos += 2;
    else
      sep = false;
    // since KSpread 1.3
    // kspread_cell->setThousandsSeparator( sep );
  }

  while (formatString[lastPos] == ' ')
    ++lastPos;

  int n = formatString.find( '.', lastPos );
  if ( n != -1)
  {
    lastPos = n + 1;
    int precision = lastPos;
    while (formatString[precision] == '0')
      ++precision;

    int tmp = lastPos;
    lastPos = precision;
    precision -= tmp;

    kspread_cell->format()->setPrecision( precision );
  }

  bool red = false;
  if (formatString.find("[RED]", lastPos) != -1)
  {
    red = true;
    kspread_cell->format()->setFloatColor( Format::NegRed );
  }
  if ( formatString.find('(', lastPos) != -1 )
  {
    if ( red )
      kspread_cell->format()->setFloatColor( Format::NegRedBrackets );
    else
      kspread_cell->format()->setFloatColor( Format::NegBrackets );
  }
}

void GNUMERICFilter::convertFormula( TQString & formula ) const
{
  int n = formula.find( '=', 1 );

  // TODO: check if we do not screw something up here...
  if ( n != -1 )
    formula = formula.replace( n, 1, "==" );

  bool inQuote1 = false;
  bool inQuote2 = false;
  int l = formula.length();
  for ( int i = 0; i < l; ++i )
  {
    if ( formula[i] == '\'' )
      inQuote1 = !inQuote1;
    else if ( formula[i] == '"' )
      inQuote2 = !inQuote2;
    else if ( formula[i] == ',' && !inQuote1 && !inQuote2 )
      formula = formula.replace( i, 1, ";" );
  }
}

void GNUMERICFilter::setStyleInfo(TQDomNode * sheet, Sheet * table)
{
    kdDebug(30521) << "SetStyleInfo entered " << endl;

    int row, column;
    TQDomNode styles =  sheet->namedItem( "gmr:Styles" );
    if ( !styles.isNull() )
    {
        // Get a style region within that sheet.
        TQDomNode style_region =  styles.namedItem( "gmr:StyleRegion" );

        while ( !style_region.isNull() )
        {
            TQDomElement e = style_region.toElement(); // try to convert the node to an element.

            TQDomNode style = style_region.namedItem( "gmr:Style" );
            TQDomNode font = style.namedItem( "gmr:Font" );
            TQDomNode validation = style.namedItem( "gmr:Validation" );
            TQDomNode gmr_styleborder = style.namedItem( "gmr:StyleBorder" );
            TQDomNode hyperlink = style.namedItem( "gmr:HyperLink" );
            int startCol = e.attribute( "startCol" ).toInt() + 1;
            int endCol   = e.attribute( "endCol" ).toInt() + 1;
            int startRow = e.attribute( "startRow" ).toInt() + 1;
            int endRow   = e.attribute( "endRow" ).toInt() + 1;

            kdDebug(30521) << "------Style: " << startCol << ", "
                           << startRow << " - " << endCol << ", " << endRow << endl;

            if ( endCol - startCol > 200 || endRow - startRow > 200 )
            {
                style_region = style_region.nextSibling();
                continue;
            }

            for ( column = startCol; column <= endCol; ++column )
            {
                for ( row = startRow; row <= endRow; ++row )
                {
                    kdDebug(30521) << "Cell: " << column << ", " << row << endl;
                    Cell * kspread_cell = table->cellAt( column, row, false );

                    // don't create new cells -> don't apply format on empty cells, if bigger region
                    if ( ( kspread_cell->isDefault() || kspread_cell->isEmpty() )
                         && ( ( endCol - startCol > 2 ) || ( endRow - startRow > 2 ) ) )
                    {
                        kdDebug(30521) << "CELL EMPTY OR RANGE TOO BIG " << endl;
                        continue;
                    }

                    TQDomElement style_element = style.toElement(); // try to convert the node to an element.

                    kdDebug(30521) << "Style valid for kspread" << endl;
                    kspread_cell = table->nonDefaultCell( column, row, false );

                    if (style_element.hasAttribute("Fore"))
                    {
                        TQString color_string = style_element.attribute("Fore");
                        TQColor color;
                        convert_string_to_qcolor(color_string, &color);
                        kspread_cell->format()->setTextColor(color);
                    }

                    if (style_element.hasAttribute("Back"))
                    {
                        TQString color_string = style_element.attribute("Back");
                        TQColor color;
                        convert_string_to_qcolor(color_string, &color);
                        kspread_cell->format()->setBgColor(color);
                    }

                    if (style_element.hasAttribute("PatternColor"))
                    {
                        TQString color_string = style_element.attribute("PatternColor");
                        TQColor color;
                        convert_string_to_qcolor(color_string, &color);
                        kspread_cell->format()->setBackGroundBrushColor( color );
                    }

                    if (style_element.hasAttribute("Shade"))
                    {
                        /* Pattern's taken from: gnumeric's pattern.c */
                        /* if "TODO" added: doesn't match exactly the gnumeric one */

                        TQString shade = style_element.attribute("Shade");
                        if (shade == "0")
                        {
                            // nothing to do
                        }
                        else if (shade == "1")
                        {
                            /* 1 Solid */
                            //kspread_cell->format()->setBackGroundBrushStyle(Qt::SolidPattern);
                            //This is as empty
                            /* What should this be? */

                        }
                        else if (shade == "2")
                        {
                            /* 2 75% */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense2Pattern);
                        }
                        else if (shade == "3")
                        {
                            /* 3 50% */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense4Pattern);
                        }
                        else if (shade == "4")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense5Pattern);
                            /* This should be 25%... All qt has is 37% */

                            /* 4 25% */
                        }
                        else if (shade == "5")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense6Pattern);
                            /* 5 12.5% */
                        }
                        else if (shade == "6")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense7Pattern);
                            /* 6 6.25% */

                        }
                        else if (shade == "7")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::HorPattern);
                            /* 7Qt::Horizontal Stripe */
                        }
                        else if (shade == "8")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::VerPattern);
                            /* 8Qt::Vertical Stripe */
                        }
                        else if (shade == "9")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::BDiagPattern);
                            /* 9 Reverse Diagonal Stripe */
                        }
                        else if (shade == "10")
                        {
                            /* 10 Diagonal Stripe */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::FDiagPattern);
                        }
                        else if (shade == "11")
                        {
                            /* 11 Diagonal Crosshatch */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern);
                        }
                        else if (shade == "12")
                        {
                            /* 12 Thick Diagonal Crosshatch TODO!*/
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern);
                        }
                        else if (shade == "13")
                        {
                            /* 13 ThinQt::Horizontal Stripe TODO: wrong: this is thick!*/
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::HorPattern);
                        }
                        else if (shade == "14")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::VerPattern);
                        }
                        else if (shade == "15")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::FDiagPattern);
                        }
                        else if (shade == "16")
                        {
                            /* 16 Thick Reverse Stripe TODO:*/
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::BDiagPattern);
                        }
                        else if (shade == "17")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern);
                        }
                        else if (shade == "18")
                        {
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern);
                        }
                        else if (shade == "19")
                        {
                            /* 19 Applix small circle */
                        }
                        else if (shade == "20")
                        {
                            /* 20 Applix semicircle */
                        }
                        else if (shade == "21")
                        {
                            /* 21 Applix small thatch */
                        }
                        else if (shade == "22")
                        {
                            /* 22 Applix round thatch */
                        }
                        else if (shade == "23")
                        {
                            /* 23 Applix Brick */
                        }
                        else if (shade == "24")
                        {
                            /* 24 100% */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::SolidPattern);
                        }
                        else if (shade == "25")
                        {
                            /* 25 87.5% */
                            kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense2Pattern);
                        }
                    }

                    if ( style_element.hasAttribute( "Rotation" ) )
                    {
                        int rot = style_element.attribute( "Rotation" ).toInt();
                        kspread_cell->format()->setAngle( -1* rot );
                    }
                    if (style_element.hasAttribute("Indent"))
                    {
                        double indent = style_element.attribute("Indent").toDouble();
                        // gnumeric saves indent in characters, we in points:
                        kspread_cell->format()->setIndent( indent * 10.0 );
                    }

                    if (style_element.hasAttribute("HAlign"))
                    {
                        TQString halign_string=style_element.attribute("HAlign");

                        if (halign_string == "1")
                        {
                            /* General: No equivalent in Kspread. */
                        }
                        else if (halign_string == "2")
                        {
                            kspread_cell->format()->setAlign(Format::Left);
                        }
                        else if (halign_string == "4")
                        {
                            kspread_cell->format()->setAlign(Format::Right);
                        }
                        else if (halign_string == "8")
                        {
                            kspread_cell->format()->setAlign(Format::Center);
                        }
                        else if (halign_string == "16")
                        {
                            /* Fill: No equivalent in Kspread. */
                        }
                        else if (halign_string == "32")
                        {
                            /* Justify: No equivalent in Kspread */
                        }
                        else if (halign_string == "64")
                        {
                            /* Centered across selection*/
                        }

                    }

                    if (style_element.hasAttribute("VAlign"))
                    {
                        TQString valign_string=style_element.attribute("VAlign");

                        if (valign_string == "1")
                        {
                            /* General: No equivalent in Kspread. */
                            kspread_cell->format()->setAlignY(Format::Top);
                        }
                        else if (valign_string == "2")
                        {
                            kspread_cell->format()->setAlignY(Format::Bottom);
                        }
                        else if (valign_string == "4")
                        {
                            kspread_cell->format()->setAlignY(Format::Middle);
                        }
                        else if (valign_string == "8")
                        {
                            /* Justify: No equivalent in Kspread */
                        }
                    }

                    if (style_element.hasAttribute("WrapText"))
                    {
                        TQString multiRow = style_element.attribute("WrapText");

                        if ( multiRow == "1" )
                            kspread_cell->format()->setMultiRow( true );
                    }

                    if (style_element.hasAttribute("Format"))
                    {
                        TQString formatString = style_element.attribute("Format");

                        kdDebug(30521) << "Format: " << formatString << endl;
                        ParseFormat(formatString, kspread_cell);

                    } // End "Format"

                    if (!gmr_styleborder.isNull())
                    {
                        TQDomElement style_element = gmr_styleborder.toElement(); // try to convert the node to an element.
                        ParseBorder( style_element, kspread_cell );
                    }
                    if ( !validation.isNull() )
                    {
                        TQDomElement validation_element = validation.toElement();
                        if ( !validation_element.isNull() )
                        {
                            kdDebug(30521)<<" Cell validation \n";
                            Validity* kspread_validity = kspread_cell->getValidity();
                            if ( validation_element.hasAttribute( "AllowBlank" ) && validation_element.attribute( "AllowBlank" )=="true" )
                            {
                                kspread_validity->allowEmptyCell=true;
                            }
                            if ( validation_element.hasAttribute( "Title" ))
                            {
                                kspread_validity->title=validation_element.attribute( "Title" );
                            }
                            if ( validation_element.hasAttribute( "Message" ))
                            {
                                kspread_validity->message=validation_element.attribute( "Message" );
                            }
                            if ( validation_element.hasAttribute( "Style" ) )
                            {
                                int value = validation_element.attribute( "Style" ).toInt();
                                switch( value )
                                {
                                case 0:
                                    kspread_validity->displayMessage=false;
                                    break;
                                case 1:
                                  kspread_validity->m_action=Action::Stop;
                                    break;
                                case 2:
                                  kspread_validity->m_action=Action::Warning;
                                    break;
                                case 3:
                                  kspread_validity->m_action=Action::Information;
                                    break;
                                default:
                                    kdDebug()<<" Error in validation style :"<<value<<endl;
                                    break;
                                }
                            }
                            TQDomNode expression0 = validation_element.namedItem( "gmr:Expression0" );
                            TQDomNode expression1 = validation_element.namedItem( "gmr:Expression1" );
                            //kdDebug()<<" expression0.isNull() "<<expression0.isNull()<<endl;
                            //kdDebug()<<" expression1.isNull() "<<expression1.isNull()<<endl;
                            if ( validation_element.hasAttribute( "Type" ) )
                            {
                                int valueOp = validation_element.attribute( "Type" ).toInt();
                                switch( valueOp )
                                {
                                case 0:
                                    kspread_validity->m_restriction=Restriction::None;
                                    break;
                                case 1:
                                {
                                    kspread_validity->m_restriction=Restriction::Integer;
                                    if ( validation_element.hasAttribute( "Operator" ) )
                                    {
                                        int value = validation_element.attribute( "Operator" ).toInt();

                                        switch( value )
                                        {
                                        case 0:
                                          kspread_validity->m_cond=Conditional::Between;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 1:
                                          kspread_validity->m_cond=Conditional::DifferentTo;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 2:
                                          kspread_validity->m_cond=Conditional::Equal;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 3:
                                          kspread_validity->m_cond=Conditional::Different;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 4:
                                          kspread_validity->m_cond=Conditional::Superior;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 5:
                                          kspread_validity->m_cond=Conditional::Inferior;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 6:
                                          kspread_validity->m_cond=Conditional::SuperiorEqual;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 7:
                                          kspread_validity->m_cond=Conditional::InferiorEqual;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        default:
                                            kdDebug()<<" Error in validation Operator :"<<value<<endl;
                                            break;
                                        }
                                    }
                                }
                                break;
                                case 2:
                                    kspread_validity->m_restriction=Restriction::Number;
                                    if ( validation_element.hasAttribute( "Operator" ) )
                                    {
                                        int value = validation_element.attribute( "Operator" ).toInt();
                                        switch( value )
                                        {
                                        case 0:
                                          kspread_validity->m_cond=Conditional::Between;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 1:
                                          kspread_validity->m_cond=Conditional::DifferentTo;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 2:
                                          kspread_validity->m_cond=Conditional::Equal;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 3:
                                          kspread_validity->m_cond=Conditional::Different;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 4:
                                          kspread_validity->m_cond=Conditional::Superior;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 5:
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            kspread_validity->m_cond=Conditional::Inferior;
                                            break;
                                        case 6:
                                          kspread_validity->m_cond=Conditional::SuperiorEqual;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 7:
                                          kspread_validity->m_cond=Conditional::InferiorEqual;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        default:
                                            kdDebug()<<" Error in validation Operator :"<<value<<endl;
                                            break;
                                        }
                                    }
                                    break;
                                case 3:
                                    kspread_validity->m_restriction=Restriction::List;
                                    break;
                                case 4:
                                    kspread_validity->m_restriction=Restriction::Date;
                                    if ( validation_element.hasAttribute( "Operator" ) )
                                    {
                                        int value = validation_element.attribute( "Operator" ).toInt();
                                        switch( value )
                                        {
                                        case 0:
                                          kspread_validity->m_cond=Conditional::Between;
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            if ( !expression1.isNull() )
                                                kspread_validity->dateMax=TQDate::fromString( expression1.toElement().text() );

                                            break;
                                        case 1:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            if ( !expression1.isNull() )
                                                kspread_validity->dateMax=TQDate::fromString( expression1.toElement().text() );
                                            kspread_validity->m_cond=Conditional::DifferentTo;
                                            break;
                                        case 2:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Equal;
                                            break;
                                        case 3:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Different;
                                            break;
                                        case 4:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Superior;
                                            break;
                                        case 5:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Inferior;
                                            break;
                                        case 6:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::SuperiorEqual;
                                            break;
                                        case 7:
                                            if ( !expression0.isNull() )
                                                kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::InferiorEqual;
                                            break;
                                        default:
                                            kdDebug()<<" Error in validation Operator :"<<value<<endl;
                                            break;
                                        }
                                    }
                                    break;
                                case 5:
                                    kspread_validity->m_restriction=Restriction::Time;
                                    if ( validation_element.hasAttribute( "Operator" ) )
                                    {
                                        int value = validation_element.attribute( "Operator" ).toInt();
                                        switch( value )
                                        {
                                        case 0:
                                          kspread_validity->m_cond=Conditional::Between;
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            if ( !expression1.isNull() )
                                                kspread_validity->timeMax=TQTime::fromString( expression1.toElement().text() );
                                            break;
                                        case 1:
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            if ( !expression1.isNull() )
                                                kspread_validity->timeMax=TQTime::fromString( expression1.toElement().text() );
                                            kspread_validity->m_cond=Conditional::DifferentTo;
                                            break;
                                        case 2:
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Equal;
                                            break;
                                        case 3:
                                          kspread_validity->m_cond=Conditional::Different;
                                            break;
                                        case 4:
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::Superior;
                                            break;
                                        case 5:
                                          kspread_validity->m_cond=Conditional::Inferior;
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            break;
                                        case 6:
                                          kspread_validity->m_cond=Conditional::SuperiorEqual;
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            break;
                                        case 7:
                                            if ( !expression0.isNull() )
                                                kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() );
                                            kspread_validity->m_cond=Conditional::InferiorEqual;
                                            break;
                                        default:
                                            kdDebug()<<" Error in validation Operator :"<<value<<endl;
                                            break;
                                        }
                                    }
                                    break;
                                case 6:
                                    kspread_validity->m_restriction=Restriction::TextLength;
                                    if ( validation_element.hasAttribute( "Operator" ) )
                                    {
                                        int value = validation_element.attribute( "Operator" ).toInt();
                                        switch( value )
                                        {
                                        case 0:
                                          kspread_validity->m_cond=Conditional::Between;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 1:
                                          kspread_validity->m_cond=Conditional::DifferentTo;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            if ( !expression1.isNull() )
                                                kspread_validity->valMax=expression1.toElement().text().toInt();
                                            break;
                                        case 2:
                                          kspread_validity->m_cond=Conditional::Equal;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 3:
                                          kspread_validity->m_cond=Conditional::Different;
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            break;
                                        case 4:
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            kspread_validity->m_cond=Conditional::Superior;
                                            break;
                                        case 5:
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            kspread_validity->m_cond=Conditional::Inferior;
                                            break;
                                        case 6:
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            kspread_validity->m_cond=Conditional::SuperiorEqual;
                                            break;
                                        case 7:
                                            if ( !expression0.isNull() )
                                                kspread_validity->valMin=expression0.toElement().text().toInt();
                                            kspread_validity->m_cond=Conditional::InferiorEqual;
                                            break;
                                        default:
                                            kdDebug()<<" Error in validation Operator :"<<value<<endl;
                                            break;
                                        }
                                    }
                                    break;
                                default:
                                    kdDebug()<<" Error in Type element : "<<valueOp<<endl;
                                }

                            }
                            //<gmr:Validation Style="0" Type="1" Operator="0" AllowBlank="true" UseDropdown="false">
                            //<gmr:Expression0>745</gmr:Expression0>
                            //<gmr:Expression1>4546</gmr:Expression1>
                        }
                    }
                    if (!font.isNull())
                    {
                        TQDomElement font_element = font.toElement();

                        kspread_cell->format()->setTextFontFamily( font_element.text() );

                        if (!font_element.isNull())
                        {
                            if (font_element.attribute("Italic") == "1")
                            { kspread_cell->format()->setTextFontItalic(true); }

                            if (font_element.attribute("Bold") == "1")
                            { kspread_cell->format()->setTextFontBold(true); }

                            if (font_element.hasAttribute("Underline") && ( font_element.attribute("Underline") != "0") )
                            { kspread_cell->format()->setTextFontUnderline(true); }

                            if (font_element.hasAttribute("StrikeThrough" ) && ( font_element.attribute("StrikeThrough") != "0") )
                            { kspread_cell->format()->setTextFontStrike(true); }

                            if (font_element.hasAttribute("Unit"))
                            { kspread_cell->format()->setTextFontSize(font_element.attribute("Unit").toInt()); }

                        }
                        if ( !hyperlink.isNull() )
                        {
                            //<gmr:HyperLink type="GnmHLinkURL" target="www.kde.org"/>
                            if ( hyperlink.toElement().hasAttribute( "type" ) )
                            {
                                TQString linkType= hyperlink.toElement().attribute( "type" );
                                TQString target = hyperlink.toElement().attribute( "target" );
                                TQString tip = hyperlink.toElement().attribute( "tip" );
                                if ( !tip.isEmpty() )
                                    kspread_cell->setCellText( tip );
                                if ( linkType=="GnmHLinkURL" )
                                {
                                    if ( !target.startsWith( "http://" ) )
                                        target="http://"+target;
                                    kspread_cell->setLink( target );
                                }
                                else if ( linkType=="GnmHLinkEMail" )
                                {
                                    if ( !target.startsWith( "mailto:/" ) )
                                        target="mailto:/"+target;
                                    kspread_cell->setLink( target );
                                }
                                else if ( linkType=="GnmHLinkExternal" )
                                {
                                    if ( !target.startsWith( "file://" ) )
                                        target="file://"+target;

                                    kspread_cell->setLink( target );
                                }
                                else if ( linkType=="GnmHLinkCurWB" )
                                {
                                    kspread_cell->setLink( target );
                                }
                                else
                                    kdDebug()<<" linkType not defined : "<<linkType<<endl;
                            }
                        }
                    }
                }
            }
            style_region = style_region.nextSibling();
        }

    }
}

/* NOTE: As of now everything is in a single huge function.  This is
	 very ugly.  It should all be broken up into smaller
	 functions, probably one for each GNUMeric section.  It kind
	 of grew out of control.  It could probably be cleaned up in
	 an hour or so. --PGE
  */


KoFilter::ConversionStatus GNUMERICFilter::convert( const TQCString & from, const TQCString & to )
{
    dateInit();
    bool bSuccess=true;

    kdDebug(30521) << "Entering GNUmeric Import filter." << endl;

    KoDocument * document = m_chain->outputDocument();
    if ( !document )
        return KoFilter::StupidError;

    kdDebug(30521) << "here we go... " << document->className() << endl;

    if ( !::tqqt_cast<const KSpread::Doc *>( document ) )  // it's safer that way :)
    {
        kdWarning(30521) << "document isn't a KSpread::Doc but a " << document->className() << endl;
        return KoFilter::NotImplemented;
    }
    if ( from != "application/x-gnumeric" || to != "application/x-kspread" )
    {
        kdWarning(30521) << "Invalid mimetypes " << from << " " << to << endl;
        return KoFilter::NotImplemented;
    }

    kdDebug(30521) << "...still here..." << endl;

    // No need for a dynamic cast here, since we use TQt's moc magic
    Doc * ksdoc = ( Doc * ) document;

    if ( ksdoc->mimeType() != "application/x-kspread" )
    {
        kdWarning(30521) << "Invalid document mimetype " << ksdoc->mimeType() << endl;
        return KoFilter::NotImplemented;
    }


    TQIODevice* in = KFilterDev::deviceForFile(m_chain->inputFile(),"application/x-gzip");

    if ( !in )
    {
        kdError(30521) << "Cannot create device for uncompressing! Aborting!" << endl;
        return KoFilter::FileNotFound;
    }

    if (!in->open(IO_ReadOnly))
    {
        kdError(30521) << "Cannot open file for uncompressing! Aborting!" << endl;
        delete in;
        return KoFilter::FileNotFound;
    }

    TQDomDocument doc;
    TQString errorMsg;
    int errorLine, errorColumn;
    if ( !doc.setContent(in, &errorMsg, &errorLine, &errorColumn) )
    {
        kdError(30521) << "Parsing error in " << from << "! Aborting!" << endl
            << " In line: " << errorLine << ", column: " << errorColumn << endl
            << " Error message: " << errorMsg << endl;
        in->close();
        return KoFilter::ParsingError;
    }

    in->close();
    delete in;

    int row, column;
    int value = 0;
    int currentTab = -1;
    int selectedTab = 0;
    Sheet * selTable = 0;

    TQDomElement docElem = doc.documentElement();
    TQDomElement uiData  = docElem.namedItem("gmr:UIData").toElement();
    if ( !uiData.isNull() )
    {
      if ( uiData.hasAttribute( "SelectedTab" ) )
      {
        bool ok = false;
        int n = uiData.attribute( "SelectedTab" ).toInt( &ok );
        if ( ok )
        {
          selectedTab = n;
        }
      }
    }
    TQDomNode sheets = docElem.namedItem("gmr:Sheets");
    if ( sheets.isNull() )
    {
        //avoid crash with new file format.
        //TODO allow to load new file format
        return KoFilter::ParsingError;
    }
    TQDomNode sheet =  sheets.namedItem("gmr:Sheet");

    /* This sets the Document information. */
    set_document_info( document, &docElem );

    /* This sets the Document attributes */
    set_document_attributes( ksdoc, &docElem );

    /* This sets the Area Names */
    set_document_area_names( ksdoc, &docElem );

    Sheet * table;

    // This is a mapping of exprID to expressions.

    TQDict<char> exprID_dict( 17, FALSE );
    int num = 1;

    while (!sheet.isNull())
    {
        ++currentTab;
        table = ksdoc->map()->addNewSheet();

        if ( currentTab == selectedTab )
          selTable = table;

        TQDomElement name = sheet.namedItem( "gmr:Name" ).toElement();
        TQDomElement sheetElement = sheet.toElement();

        if ( !name.isNull() )
          table->setSheetName( name.text(), false, false );
        else
          table->setSheetName( "Sheet" + TQString::number( num ), false, false );
        table->enableScrollBarUpdates( false );

        //kdDebug()<<" sheetElement.hasAttribute( DisplayFormulas ) :"<<sheetElement.hasAttribute( "DisplayFormulas" )<<endl;
        TQString tmp;
        if ( sheetElement.hasAttribute( "DisplayFormulas" ) )
        {
            tmp=sheetElement.attribute( "DisplayFormulas");
            table->setShowFormula( ( tmp=="true" )||( tmp=="1" ) );
        }
        if ( sheetElement.hasAttribute( "HideZero" ) )
        {
            tmp = sheetElement.attribute( "HideZero" );
            table->setHideZero( ( tmp=="true" )||( tmp=="1" ) );
        }
        if ( sheetElement.hasAttribute( "HideGrid" ) )
        {
            tmp = sheetElement.attribute( "HideGrid" );
            table->setShowGrid( ( tmp=="false" )||( tmp=="0" ) );
        }
        if ( sheetElement.hasAttribute( "HideColHeader" ) )
        {
            tmp = sheetElement.attribute( "HideColHeader" );
            ksdoc->setShowColumnHeader( ( tmp=="false" )||( tmp=="0" ) );
        }
        if ( sheetElement.hasAttribute( "HideRowHeader" ) )
        {
            tmp =sheetElement.attribute( "HideRowHeader" );
            ksdoc->setShowRowHeader( ( tmp=="false" )||( tmp=="0" ) );
        }


	setObjectInfo(&sheet, table);
	setColInfo(&sheet, table);
	setRowInfo(&sheet, table);
	setSelectionInfo(&sheet, table);

        /* handling print information */
	TQDomNode printInfo = sheet.namedItem("gmr:PrintInformation");
        if ( !printInfo.isNull() )
          ParsePrintInfo( printInfo, table );

        kdDebug(30521) << "Reading in cells" << endl;

	/* CELL handling START */
	TQDomNode cells = sheet.namedItem( "gmr:Cells" );
	TQDomNode cell  = cells.namedItem( "gmr:Cell" );
        TQDomNode mergedCells = sheet.namedItem( "gmr:MergedRegions" );
        TQDomNode mergedRegion = mergedCells.namedItem( "gmr:Merge" );
        if ( cell.isNull() )
        {
          kdWarning(30521) << "No cells" << endl;
        }

	while ( !cell.isNull() )
        {
	  value += 2;
	  emit sigProgress(value);

	  TQDomElement e = cell.toElement(); // try to convert the node to an element.
	  if ( !e.isNull() )
          { // the node was really an element.
            kdDebug(30521) << "New Cell " << endl;
	    TQDomNode content_node = cell.namedItem("gmr:Content");

	    if (!content_node.isNull())
            {
	      TQDomElement content = content_node.toElement();

	      if( !content.isNull() )
              { // the node was really an element.
		column = e.attribute( "Col" ).toInt() + 1;
		row    = e.attribute( "Row" ).toInt() + 1;

		TQString cell_content( content.text() );
                //kdDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content<<endl;
                if ( cell_content[0] == '=' )
                  convertFormula( cell_content );

                Cell * kspread_cell = table->nonDefaultCell( column, row );

                if (e.hasAttribute("ValueType"))
                {
                  // TODO: what is this for?
            	  // <xsd:enumeration value="10"/> <!-- empty     -->
            	  // <xsd:enumeration value="20"/> <!-- boolean   -->
                  // <xsd:enumeration value="30"/> <!-- integer   -->
                  // <xsd:enumeration value="40"/> <!-- float     -->
                  // <xsd:enumeration value="50"/> <!-- error     -->
                  // <xsd:enumeration value="60"/> <!-- string    -->
                  // <xsd:enumeration value="70"/> <!-- cellrange -->
                  // <xsd:enumeration value="80"/> <!-- array     -->
                    TQString valuetype = e.attribute( "ValueType" );
                    if ( valuetype == "40" )//percentage
                    {
                        kspread_cell->format()->setFormatType( Percentage_format );
                        kspread_cell->setValue( cell_content );
                    }
                    else if ( valuetype =="60" )//string
                    {
                        kspread_cell->format()->setFormatType( Text_format );
                        kspread_cell->setValue( cell_content );
                    }
                }

                if (e.hasAttribute( "ValueFormat" ))
                {
                  TQString formatString = e.attribute( "ValueFormat" );
                  if ( !setType( kspread_cell, formatString, cell_content ) )
                    table->setText(row, column, cell_content, false);
                }
                else
                  table->setText(row, column, cell_content, false);

		if (e.hasAttribute("ExprID"))
                {
		    // TQString encoded_string(table->cellAt( column, row, false)->encodeFormula( row, column ).utf8());
		    TQString encoded_string(table->cellAt( column, row, false )->encodeFormula().latin1());


		    char * tmp_string = ( char * ) malloc( strlen( encoded_string.latin1() ) );
		    strcpy( tmp_string, encoded_string.latin1() );

		    kdDebug(30521) << encoded_string.latin1() << endl;

		    exprID_dict.insert(e.attribute("ExprID"), tmp_string);

		    kdDebug(30521) << exprID_dict[e.attribute("ExprID")] << endl;
		    kdDebug(30521) << exprID_dict[TQString("1")] << endl;
		    kdDebug(30521) << e.attribute("ExprID") << endl;

		  }
	      }
	    }
	    else
            {

                column = e.attribute( "Col" ).toInt() + 1;
		row    = e.attribute( "Row" ).toInt() + 1;

		TQString cell_content( e.text() );
                //kdDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content<<endl;
                if ( cell_content[0] == '=' )
                  convertFormula( cell_content );

                Cell * kspread_cell = table->nonDefaultCell( column, row );

                if (e.hasAttribute("ValueType"))
                {
                  // TODO: Defined type of cell
                    //<xsd:enumeration value="10"/> <!-- empty     -->
                    //<xsd:enumeration value="20"/> <!-- boolean   -->
                    //<xsd:enumeration value="30"/> <!-- integer   -->
                    //<xsd:enumeration value="40"/> <!-- float     -->
                    //<xsd:enumeration value="50"/> <!-- error     -->
                    //<xsd:enumeration value="60"/> <!-- string    -->
                    //<xsd:enumeration value="70"/> <!-- cellrange -->
                    //<xsd:enumeration value="80"/> <!-- array     -->
                    //kspread_cell->setValue( date );
                    //kspread_cell->format()->setFormatType( type );
                    TQString valuetype = e.attribute( "ValueType" );
                    if ( valuetype == "40" )//percentage
                    {
                        kspread_cell->format()->setFormatType( Percentage_format );
                        kspread_cell->setValue( cell_content );
                    }
                    else if ( valuetype =="60" )//string
                    {
                        kspread_cell->format()->setFormatType( Text_format );
                        kspread_cell->setValue( cell_content );
                    }

                }

                if (e.hasAttribute( "ValueFormat" ))
                {
                  TQString formatString = e.attribute( "ValueFormat" );
                  if ( !setType( kspread_cell, formatString, cell_content ) )
                    table->setText(row, column, cell_content, false);
                }
                else
                  table->setText(row, column, cell_content, false);


                if (e.hasAttribute("ExprID"))
                {
		    column = e.attribute("Col").toInt() + 1;
		    row    = e.attribute("Row").toInt() + 1;
		    char * expr;
		    expr = exprID_dict[e.attribute("ExprID")];
		    // expr = exprID_dict[TQString("1")];

		    kdDebug(30521) << "FOO:" << column << row << endl;
		    kdDebug(30521) <<
                           table->cellAt( column, row, false )->decodeFormula( expr, column, row ).latin1() << endl;
		    kdDebug(30521) << expr << endl;

		    table->setText(row, column,
                                   table->cellAt( column, row, false )->decodeFormula( expr, column, row ),
                                   false);
		  }
	      }
	  }
	  cell = cell.nextSibling();
	}

        kdDebug(30521) << "Reading in cells done" << endl;

        if ( mergedRegion.isNull() )
        {
          kdWarning(30521) << "No cells merged !" << endl;
        }
	while ( !mergedRegion.isNull() )
        {
            TQDomElement e = mergedRegion.toElement(); // try to convert the node to an element.
            TQString cell_merge_area( e.text() );
            Range range(cell_merge_area);
            //kdDebug()<<"text !!! :"<<cell_merge_area<< "range :start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl;
            Cell * cell = table->nonDefaultCell( range.startCol (), range.startRow () );
            cell->mergeCells( range.startCol (), range.startRow (), range.endCol ()-range.startCol (),  range.endRow ()-range.startRow ());
            mergedRegion = mergedRegion.nextSibling();
        }
	/* There is a memory leak here...
	 * The strings in the exprID_dict have been allocated, but they have not been freed.
	 */

	/* exprID_dict.statistics(); */

	/* CELL handling STOP */

	/* STYLE handling START */
        //Laurent - 2001-12-07  desactivate this code : otherwise we
        //create 65535*255 cells (Styleregion is define for a area and
        //not for cell, so gnumeric define a style as : col start=0 col end=255
        //rowstart=0 rowend=255 => we create 255*255 cells
        //and gnumeric stocke all area and not just modify area
        //=> not good for kspread.
        // Norbert: activated again, only cells with texts get modified, nothing else created
	setStyleInfo(&sheet, table);

	/* STYLE handling STOP */
        table->enableScrollBarUpdates( true );

	sheet = sheet.nextSibling();
        ++num;
      }

    if ( selTable )
      ksdoc->setDisplaySheet( selTable );

    emit sigProgress(100);
    if ( bSuccess )
        return KoFilter::OK;
    else
        return KoFilter::StupidError;
}

#include <gnumericimport.moc>
