summaryrefslogtreecommitdiffstats
path: root/kspread/kspread_util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kspread/kspread_util.cpp')
-rw-r--r--kspread/kspread_util.cpp1218
1 files changed, 1218 insertions, 0 deletions
diff --git a/kspread/kspread_util.cpp b/kspread/kspread_util.cpp
new file mode 100644
index 000000000..c7b28af12
--- /dev/null
+++ b/kspread/kspread_util.cpp
@@ -0,0 +1,1218 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
+ Copyright (C) 1998, 1999 Torben Weis <weis@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.
+*/
+
+#include <ctype.h>
+
+#include <tqregexp.h>
+
+#include <kdebug.h>
+
+#include "formula.h"
+#include "kspread_doc.h"
+#include "kspread_locale.h"
+#include "kspread_map.h"
+#include "kspread_sheet.h"
+#include "kspread_style.h"
+#include "kspread_util.h"
+
+using namespace KSpread;
+
+//helper functions for the formatting
+bool KSpread::formatIsDate (FormatType fmt)
+{
+ return ((fmt == ShortDate_format) || (fmt == TextDate_format) ||
+ (((int) fmt >= 200) && ((int) fmt < 300)));
+}
+
+bool KSpread::formatIsTime (FormatType fmt)
+{
+ return (((int) fmt >= 50) && ((int) fmt < 70));
+}
+
+bool KSpread::formatIsFraction (FormatType fmt)
+{
+ return (((int) fmt >= 70) && ((int) fmt < 80));
+}
+
+
+//used in Point::init, Cell::encodeFormula and
+// dialogs/kspread_dlg_paperlayout.cpp
+int KSpread::util_decodeColumnLabelText( const TQString &_col )
+{
+ int col = 0;
+ int offset='a'-'A';
+ int counterColumn = 0;
+ for ( uint i=0; i < _col.length(); i++ )
+ {
+ counterColumn = (int) pow(26.0 , static_cast<int>(_col.length() - i - 1));
+ if( (int)(_col[i]) >= 'A' && (int)(_col[i]) <= 'Z' )
+ col += counterColumn * ( _col[i].latin1() - 'A' + 1); // okay here (Werner)
+ else if( (int)(_col[i]) >= 'a' && (int)(_col[i]) <= 'z' )
+ col += counterColumn * ( _col[i].latin1() - 'A' - offset + 1 );
+ else
+ kdDebug(36001) << "util_decodeColumnLabelText: Wrong characters in label text for col:'" << _col << "'" << endl;
+ }
+ return col;
+}
+
+//used in dialogs/kspread_dlg_paperlayout.cpp
+TQString KSpread::util_rangeColumnName( const TQRect &_area)
+{
+ return TQString("%1:%2")
+ .arg( Cell::columnName( _area.left()))
+ .arg( Cell::columnName(_area.right()));
+}
+
+//used in dialogs/kspread_dlg_paperlayout.cpp
+TQString KSpread::util_rangeRowName( const TQRect &_area)
+{
+ return TQString("%1:%2")
+ .arg( _area.top())
+ .arg(_area.bottom());
+}
+
+TQString KSpread::util_rangeName(const TQRect &_area)
+{
+ return Cell::name( _area.left(), _area.top() ) + ":" +
+ Cell::name( _area.right(), _area.bottom() );
+}
+
+TQString KSpread::util_rangeName(Sheet * _sheet, const TQRect &_area)
+{
+ return _sheet->sheetName() + "!" + util_rangeName(_area);
+}
+
+TQDomElement KSpread::util_createElement( const TQString & tagName, const TQFont & font, TQDomDocument & doc )
+{
+ TQDomElement e( doc.createElement( tagName ) );
+
+ e.setAttribute( "family", font.family() );
+ e.setAttribute( "size", font.pointSize() );
+ e.setAttribute( "weight", font.weight() );
+ if ( font.bold() )
+ e.setAttribute( "bold", "yes" );
+ if ( font.italic() )
+ e.setAttribute( "italic", "yes" );
+ if ( font.underline() )
+ e.setAttribute( "underline", "yes" );
+ if ( font.strikeOut() )
+ e.setAttribute( "strikeout", "yes" );
+ //e.setAttribute( "charset", TDEGlobal::charsets()->name( font ) );
+
+ return e;
+}
+
+TQDomElement KSpread::util_createElement( const TQString & tagname, const TQPen & pen, TQDomDocument & doc )
+{
+ TQDomElement e( doc.createElement( tagname ) );
+ e.setAttribute( "color", pen.color().name() );
+ e.setAttribute( "style", (int)pen.style() );
+ e.setAttribute( "width", (int)pen.width() );
+ return e;
+}
+
+TQFont KSpread::util_toFont( TQDomElement & element )
+{
+ TQFont f;
+ f.setFamily( element.attribute( "family" ) );
+
+ bool ok;
+ f.setPointSize( element.attribute("size").toInt( &ok ) );
+ if ( !ok )
+ return TQFont();
+
+ f.setWeight( element.attribute("weight").toInt( &ok ) );
+ if ( !ok )
+ return TQFont();
+
+ if ( element.hasAttribute( "italic" ) && element.attribute("italic") == "yes" )
+ f.setItalic( true );
+
+ if ( element.hasAttribute( "bold" ) && element.attribute("bold") == "yes" )
+ f.setBold( true );
+
+ if ( element.hasAttribute( "underline" ) && element.attribute("underline") == "yes" )
+ f.setUnderline( true );
+
+ if ( element.hasAttribute( "strikeout" ) && element.attribute("strikeout") == "yes" )
+ f.setStrikeOut( true );
+
+ /* Uncomment when charset is added to kspread_dlg_layout
+ + save a document-global charset
+ if ( element.hasAttribute( "charset" ) )
+ TDEGlobal::charsets()->setTQFont( f, element.attribute("charset") );
+ else
+ */
+ // ######## Not needed anymore in 3.0?
+ //TDEGlobal::charsets()->setTQFont( f, TDEGlobal::locale()->charset() );
+
+ return f;
+}
+
+TQPen KSpread::util_toPen( TQDomElement & element )
+{
+ bool ok;
+ TQPen p;
+
+ p.setStyle( (Qt::PenStyle)element.attribute("style").toInt( &ok ) );
+ if ( !ok )
+ return TQPen();
+
+ p.setWidth( element.attribute("width").toInt( &ok ) );
+ if ( !ok )
+ return TQPen();
+
+ p.setColor( TQColor( element.attribute("color") ) );
+
+ return p;
+}
+
+Point::Point(const TQString & _str)
+{
+ _sheet = 0;
+ init(_str);
+}
+
+void Point::setPos(TQPoint pos)
+{
+ _pos=pos;
+}
+TQPoint Point::pos() const
+{
+ return _pos;
+}
+void Point::setSheet(Sheet* sheet)
+{
+ _sheet=sheet;
+}
+KSpread::Sheet* Point::sheet() const
+{
+ return _sheet;
+}
+void Point::setSheetName(TQString name)
+{
+ _sheetName=name;
+}
+TQString Point::sheetName() const
+{
+ return _sheetName;
+}
+void Point::setColumnFixed(bool colFixed)
+{
+ _columnFixed=colFixed;
+}
+bool Point::columnFixed() const
+{
+ return _columnFixed;
+}
+void Point::setRowFixed(bool rowFixed)
+{
+ _rowFixed=rowFixed;
+}
+bool Point::rowFixed() const
+{
+ return _rowFixed;
+}
+
+
+void Point::init(const TQString & _str)
+{
+ _columnFixed=false;
+ _rowFixed=false;
+
+// kdDebug(36001) <<"Point::init ("<<_str<<")"<<endl;
+ _pos.setX(-1);
+
+ uint len = _str.length();
+ if ( !len )
+ {
+ kdDebug(36001) << "Point::init: len = 0" << endl;
+ return;
+ }
+
+ TQString str( _str );
+ int n = _str.find( '!' );
+ if ( n != -1 )
+ {
+ _sheetName = _str.left( n );
+ str = _str.right( len - n - 1 ); // remove the '!'
+ len = str.length();
+ }
+
+ uint p = 0;
+
+ // Fixed ?
+ if ( str[0] == '$' )
+ {
+ _columnFixed = true;
+ p++;
+ }
+ else
+ _columnFixed = false;
+
+ // Malformed ?
+ if ( p == len )
+ {
+ kdDebug(36001) << "Point::init: no point after '$' (str: '" << str.mid( p ) << "'" << endl;
+ return;
+ }
+ if ( str[p] < 'A' || str[p] > 'Z' )
+ {
+ if ( str[p] < 'a' || str[p] > 'z' )
+ {
+ kdDebug(36001) << "Point::init: wrong first character in point (str: '" << str.mid( p ) << "'" << endl;
+ return;
+ }
+ }
+ //default is error
+ int x = -1;
+ //search for the first character != text
+ int result = str.find( TQRegExp("[^A-Za-z]+"), p );
+
+ //get the colomn number for the character between actual position and the first non text charakter
+ if ( result != -1 )
+ x = util_decodeColumnLabelText( str.mid( p, result - p ) ); // x is defined now
+ else // If there isn't any, then this is not a point -> return
+ {
+ kdDebug(36001) << "Point::init: no number in string (str: '" << str.mid( p, result ) << "'" << endl;
+ return;
+ }
+ p = result;
+
+ //limit is KS_colMax
+ if ( x > KS_colMax )
+ {
+ kdDebug(36001) << "Point::init: column value too high (col: " << x << ")" << endl;
+ return;
+ }
+
+ // Malformed ?
+ if (p == len)
+ {
+ kdDebug(36001) << "Point::init: p==len after cols" << endl;
+ return;
+ }
+
+ if (str[p] == '$')
+ {
+ _rowFixed = true;
+ p++;
+ // Malformed ?
+ if ( p == len )
+ {
+ kdDebug(36001) << "Point::init: p==len after $ of row" << endl;
+ return;
+ }
+ }
+ else
+ _rowFixed = false;
+
+ uint p2 = p;
+ while ( p < len )
+ {
+ if ( !isdigit( TQChar(str[p++]) ) )
+ {
+ kdDebug(36001) << "Point::init: no number" << endl;
+ return;
+ }
+ }
+
+ bool ok;
+ int y = str.mid( p2, p-p2 ).toInt( &ok );
+ if ( !ok )
+ {
+ kdDebug(36001) << "Point::init: Invalid number (str: '" << str.mid( p2, p-p2 ) << "'" << endl;
+ return;
+ }
+ if ( y > KS_rowMax )
+ {
+ kdDebug(36001) << "Point::init: row value too high (row: " << y << ")" << endl;
+ return;
+ }
+ if ( y <= 0 )
+ {
+ kdDebug(36001) << "Point::init: y <= 0" << endl;
+ return;
+ }
+ _pos = TQPoint( x, y );
+}
+
+bool util_isPointValid( TQPoint point )
+{
+ if ( point.x() >= 1
+ && point.y() >= 1
+ && point.x() <= KS_colMax
+ && point.y() <= KS_rowMax
+ )
+ return true;
+ else
+ return false;
+}
+
+bool util_isRectValid( TQRect rect )
+{
+ if ( util_isPointValid( rect.topLeft() )
+ && util_isPointValid( rect.bottomRight() )
+ )
+ return true;
+ else
+ return false;
+}
+
+Point::Point( const TQString & str, Map * map,
+ Sheet * sheet )
+{
+
+ uint p = 0;
+ int p2 = str.find( '!' );
+ if ( p2 != -1 )
+ {
+ _sheetName = str.left( p2++ );
+ while ( true )
+ {
+ _sheet = map->findSheet( _sheetName );
+ if ( !sheet && _sheetName[0] == ' ' )
+ {
+ _sheetName = _sheetName.right( _sheetName.length() - 1 );
+ continue;
+ }
+ break;
+ }
+ p = p2;
+
+ //If the loop didn't return a sheet, better keep a string for isValid
+ if ( _sheetName.isEmpty() )
+ {
+ kdDebug(36001) << "Point: tableName is unknown" << endl;
+ _sheetName = "unknown";
+ }
+ }
+ else
+ {
+ if ( sheet != 0 )
+ {
+ _sheet = sheet;
+ _sheetName = sheet->sheetName();
+ }
+ else
+ _sheet = 0;
+ }
+
+ init( str.mid( p ) );
+}
+
+Cell *Point::cell() const
+{
+ return _sheet->cellAt(_pos);
+}
+
+bool Point::operator== (const Point &cell) const
+{
+ //sheet info ignored
+ return (_pos == cell.pos());
+}
+
+bool Point::operator< (const Point &cell) const
+{
+ //sheet info ignored
+ return (pos().y() < cell.pos().y()) ? true :
+ ((pos().y() == cell.pos().y()) && (pos().x() < cell.pos().x()));
+}
+
+bool Range::operator ==(const Range& otherRange) const
+{
+ if ( _range == otherRange._range
+ && _leftFixed == otherRange._leftFixed
+ && _rightFixed == otherRange._rightFixed
+ && _bottomFixed == otherRange._bottomFixed
+ && _topFixed == otherRange._topFixed
+ && _sheet == otherRange._sheet )
+ return true;
+ else
+ return false;
+}
+
+Range::Range()
+{
+ _sheet = 0;
+ _range.setLeft( -1 );
+
+ _leftFixed=false;
+ _rightFixed=false;
+ _topFixed=false;
+ _bottomFixed=false;
+}
+Range::Range(const TQString & _str)
+{
+ _range.setLeft(-1);
+ _sheet = 0;
+
+ int p = _str.find(':');
+ // if (p == -1)
+ // return;
+
+ Point ul;
+ Point lr; ;
+
+ if ( p != -1)
+ {
+ ul = Point(_str.left(p));
+ lr = Point(_str.mid(p + 1));
+ }
+ else
+ {
+ ul = Point(_str);
+ lr = ul;
+ }
+
+ _range = TQRect(ul.pos(), lr.pos());
+ _sheetName = ul.sheetName();
+
+ _leftFixed = ul.columnFixed();
+ _rightFixed = lr.columnFixed();
+ _topFixed = ul.rowFixed();
+ _bottomFixed = lr.rowFixed();
+}
+
+ Range::Range( const Range& r )
+ {
+ _sheet = r.sheet();
+ _sheetName = r.sheetName();
+ _range = r.range();
+ _namedArea = r.namedArea();
+
+ _leftFixed=r._leftFixed;
+ _rightFixed=r._rightFixed;
+ _topFixed=r._topFixed;
+ _bottomFixed=r._bottomFixed;
+ }
+
+ Range::Range( const Point& ul, const Point& lr )
+ {
+ _range = TQRect( ul.pos(), lr.pos() );
+ if ( ul.sheetName() != lr.sheetName() )
+ {
+ _range.setLeft( -1 );
+ return;
+ }
+ _sheetName = ul.sheetName();
+ _sheet = ul.sheet();
+ _leftFixed = ul.columnFixed();
+ _rightFixed = lr.columnFixed();
+ _topFixed = ul.rowFixed();
+ _bottomFixed = lr.rowFixed();
+ }
+
+Range::Range(const TQString & str, Map * map,
+ Sheet * sheet)
+{
+ _range.setLeft(-1);
+ _sheet = 0;
+
+ //try to parse as named area
+ bool gotNamed = false;
+ TQString tmp = str.lower();
+ TQValueList < Reference >::Iterator it;
+ TQValueList < Reference > area = map->doc()->listArea();
+ for (it = area.begin(); it != area.end(); ++it) {
+ if ((*it).ref_name.lower() == tmp) {
+ // success - such named area exists
+ _range = (*it).rect;
+ _sheet = map->findSheet((*it).sheet_name);
+ gotNamed = true;
+ _namedArea = tmp;
+ break;
+ }
+ }
+ if (gotNamed) {
+ // we have a named area - no need to proceed further
+ _leftFixed = false;
+ _rightFixed = false;
+ _topFixed = false;
+ _bottomFixed = false;
+ return;
+ }
+
+ _range.setLeft(-1);
+ _sheet = 0;
+
+ int p = 0;
+ int p2 = str.find('!');
+ if (p2 != -1)
+ {
+ _sheetName = str.left(p2++);
+ while ( true )
+ {
+ _sheet = map->findSheet(_sheetName);
+
+ if ( !_sheet && _sheetName[0] == ' ' )
+ {
+ _sheetName = _sheetName.right( _sheetName.length() - 1 );
+ continue;
+ }
+ break;
+ }
+ p = p2;
+ } else
+ _sheet = sheet;
+
+
+ int p3 = str.find(':', p);
+ if (p3 == -1)
+ return;
+
+ Point ul(str.mid(p, p3 - p));
+ Point lr(str.mid(p3 + 1));
+ _range = TQRect(ul.pos(), lr.pos());
+
+ _leftFixed = ul.columnFixed();
+ _rightFixed = lr.columnFixed();
+ _topFixed = ul.rowFixed();
+ _bottomFixed = lr.rowFixed();
+}
+
+TQString Range::toString() const
+{
+ TQString result;
+
+ if (_sheet)
+ {
+ result=util_rangeName(_sheet,_range);
+ }
+ else
+ {
+ result=util_rangeName(_range);
+ }
+
+ //Insert $ characters to show fixed parts of range
+
+ int pos=result.find("!")+1;
+ Q_ASSERT(pos != -1);
+
+ if (_leftFixed)
+ {
+ result.insert(pos,'$');
+ pos++; //Takes account of extra character added in
+ }
+ if (_topFixed)
+ {
+ result.insert(pos+Cell::columnName(_range.left()).length(),'$');
+ }
+
+ pos=result.find(":")+1;
+ Q_ASSERT(pos != -1);
+
+ if (_rightFixed)
+ {
+ result.insert(pos,'$');
+ pos++; //Takes account of extra character added in
+ }
+ if (_bottomFixed)
+ {
+ result.insert(pos+Cell::columnName(_range.right()).length(),'$');
+ }
+
+
+ return result;
+}
+
+void Range::getStartPoint(Point* pt)
+{
+ if (!isValid()) return;
+
+ pt->setRow(startRow());
+ pt->setColumn(startCol());
+ pt->setColumnFixed(_leftFixed);
+ pt->setRowFixed(_topFixed);
+ pt->setSheet(_sheet);
+ pt->setSheetName(_sheetName);
+}
+
+void Range::getEndPoint(Point* pt)
+{
+ if (!isValid()) return;
+
+ pt->setRow(endRow());
+ pt->setColumn(endCol());
+ pt->setColumnFixed(_rightFixed);
+ pt->setRowFixed(_bottomFixed);
+ pt->setSheet(_sheet);
+ pt->setSheetName(_sheetName);
+}
+
+bool Range::contains (const Point &cell) const
+{
+ return _range.contains (cell.pos());
+}
+
+bool Range::intersects (const Range &r) const
+{
+ return _range.intersects (r.range());
+}
+
+bool Range::isValid() const
+{
+ return ( _range.left() >= 0 ) &&
+ ( _range.right() >= 0 ) &&
+ ( _sheet != 0 || _sheetName.isEmpty() ) &&
+ ( _range.isValid() ) ;
+}
+
+TQRect Range::range() const
+{
+ return _range;
+}
+
+void Range::setLeftFixed(bool fixed)
+{
+ _leftFixed=fixed;
+}
+bool Range::leftFixed() const
+{
+ return _leftFixed;
+}
+void Range::setRightFixed(bool fixed)
+{
+ _rightFixed=fixed;
+}
+bool Range::rightFixed() const
+{
+ return _rightFixed;
+}
+void Range::setTopFixed(bool fixed)
+{
+ _topFixed=fixed;
+}
+bool Range::topFixed() const
+{
+ return _topFixed;
+}
+void Range::setBottomFixed(bool fixed)
+{
+ _bottomFixed=fixed;
+}
+bool Range::bottomFixed() const
+{
+ return _bottomFixed;
+}
+void Range::setSheet(Sheet* sheet)
+{
+ _sheet=sheet;
+}
+KSpread::Sheet* Range::sheet() const
+{
+ return _sheet;
+}
+void Range::setSheetName(TQString sheetName)
+{
+ _sheetName=sheetName;
+}
+TQString Range::sheetName() const
+{
+ return _sheetName;
+}
+TQString Range::namedArea() const
+{
+ return _namedArea;
+}
+
+
+bool KSpread::util_isAllSelected(const TQRect &selection)
+{
+ return ( selection.top() == 1 && selection.bottom() == KS_rowMax
+ && selection.left() == 1 && selection.right() == KS_colMax);
+}
+
+bool KSpread::util_isColumnSelected(const TQRect &selection)
+{
+ return ( (selection.top() == 1) && (selection.bottom() == KS_rowMax) );
+}
+
+bool KSpread::util_isRowSelected(const TQRect &selection)
+{
+ return ( (selection.left() == 1) && (selection.right() == KS_colMax) );
+}
+
+bool KSpread::util_isRowOrColumnSelected(const TQRect &selection)
+{
+ return ( (selection.left() == 1) && (selection.right() == KS_colMax)
+ || (selection.top() == 1) && (selection.bottom() == KS_rowMax) );
+}
+
+//used in View::slotRename
+bool KSpread::util_validateSheetName(const TQString &name)
+{
+ if (name[0] == ' ')
+ {
+ return false;
+ }
+ for (unsigned int i = 0; i < name.length(); i++)
+ {
+ if ( !(name[i].isLetterOrNumber() ||
+ name[i] == ' ' || name[i] == '.' ||
+ name[i] == '_'))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+RangeIterator::RangeIterator(TQRect _range, Sheet* _sheet)
+{
+ range = _range;
+ sheet = _sheet;
+ current = TQPoint(0,0);
+}
+
+RangeIterator::~RangeIterator()
+{
+}
+
+Cell* RangeIterator::first()
+{
+ current.setY(range.top());
+
+ /* OK, because even if this equals zero, the 'getNextCellRight' won't
+ try to access it*/
+ current.setX(range.left() - 1);
+ return next();
+}
+
+Cell* RangeIterator::next()
+{
+ if (current.x() == 0 && current.y() == 0)
+ {
+ return first();
+ }
+
+ Cell* cell = NULL;
+ bool done = false;
+
+ while (cell == NULL && !done)
+ {
+ cell = sheet->getNextCellRight(current.x(), current.y());
+ if (cell != NULL && cell->column() > range.right())
+ {
+ cell = NULL;
+ }
+
+ if (cell == NULL)
+ {
+ current.setX(range.left() - 1);
+ current.setY(current.y() + 1);
+ done = (current.y() > range.bottom());
+ }
+ }
+ return cell;
+}
+
+//not used anywhere
+int KSpread::util_penCompare( TQPen const & pen1, TQPen const & pen2 )
+{
+ if ( pen1.style() == TQt::NoPen && pen2.style() == TQt::NoPen )
+ return 0;
+
+ if ( pen1.style() == TQt::NoPen )
+ return -1;
+
+ if ( pen2.style() == TQt::NoPen )
+ return 1;
+
+ if ( pen1.width() < pen2.width() )
+ return -1;
+
+ if ( pen1.width() > pen2.width() )
+ return 1;
+
+ if ( pen1.style() < pen2.style() )
+ return -1;
+
+ if ( pen1.style() > pen2.style() )
+ return 1;
+
+ if ( pen1.color().name() < pen2.color().name() )
+ return -1;
+
+ if ( pen1.color().name() > pen2.color().name() )
+ return 1;
+
+ return 0;
+}
+
+
+TQString KSpread::convertRefToBase( const TQString & sheet, const TQRect & rect )
+{
+ TQPoint bottomRight( rect.bottomRight() );
+
+ TQString s( "$" );
+ s += sheet;
+ s += ".$";
+ s += Cell::columnName( bottomRight.x() );
+ s += '$';
+ s += TQString::number( bottomRight.y() );
+
+ return s;
+}
+
+TQString KSpread::convertRefToRange( const TQString & sheet, const TQRect & rect )
+{
+ TQPoint topLeft( rect.topLeft() );
+ TQPoint bottomRight( rect.bottomRight() );
+
+ if ( topLeft == bottomRight )
+ return convertRefToBase( sheet, rect );
+
+ TQString s( "$" );
+ s += sheet;
+ s += ".$";
+ s += /*util_encodeColumnLabelText*/Cell::columnName( topLeft.x() );
+ s += '$';
+ s += TQString::number( topLeft.y() );
+ s += ":.$";
+ s += /*util_encodeColumnLabelText*/Cell::columnName( bottomRight.x() );
+ s += '$';
+ s += TQString::number( bottomRight.y() );
+
+ return s;
+}
+
+//used in Cell::convertFormulaToOasisFormat
+void KSpread::insertBracket( TQString & s )
+{
+ TQChar c;
+ int i = (int) s.length() - 1;
+
+ while ( i >= 0 )
+ {
+ c = s[i];
+ if ( c == ' ' )
+ s[i] = '_';
+ if ( !(c.isLetterOrNumber() || c == ' ' || c == '.'
+ || c == '_') )
+ {
+ s.insert( i + 1, '[' );
+ return;
+ }
+ --i;
+ }
+}
+
+ // e.g.: Sheet4.A1:Sheet4.E28
+ //used in Sheet::saveOasis
+TQString KSpread::convertRangeToRef( const TQString & sheetName, const TQRect & _area )
+{
+ return sheetName + "." + Cell::name( _area.left(), _area.top() ) + ":" + sheetName + "."+ Cell::name( _area.right(), _area.bottom() );
+}
+
+TQString KSpread::convertOasisPenToString( const TQPen & pen )
+{
+// kdDebug()<<"convertOasisPenToString( const TQPen & pen ) :"<<pen<<endl;
+ // NOTE Stefan: TQPen api docs:
+ // For horizontal and vertical lines a line width of 0 is
+ // the same as a line width of 1.
+ // A line width of 0 will produce a 1 pixel wide line using
+ // a fast algorithm for diagonals. A line width of 1 will
+ // also produce a 1 pixel wide line, but uses a slower more
+ // accurate algorithm for diagonals.
+ TQString s = TQString( "%1pt " ).arg( (pen.width() == 0) ? 1 : pen.width() );
+ switch( pen.style() )
+ {
+ case TQt::NoPen:
+ return "none";
+ case TQt::SolidLine:
+ s+="solid";
+ break;
+ case TQt::DashLine:
+ s+="dashed";
+ break;
+ case TQt::DotLine:
+ s+="dotted";
+ break;
+ case TQt::DashDotLine:
+ s+="dot-dash";
+ break;
+ case TQt::DashDotDotLine:
+ s+="dot-dot-dash";
+ break;
+ default: break;
+ }
+ kdDebug()<<" convertOasisPenToString :"<<s<<endl;
+ if ( pen.color().isValid() )
+ {
+ s+=' ';
+ s+=Style::colorName(pen.color());
+ }
+ return s;
+}
+
+TQPen KSpread::convertOasisStringToPen( const TQString &border )
+{
+ TQPen pen;
+ //string like "0.088cm solid #800000"
+ if (border.isEmpty() || border=="none" || border=="hidden") // in fact no border
+ {
+ pen.setStyle( Qt::NoPen );
+ return pen;
+ }
+ //code from koborder, for the moment kspread doesn't use koborder
+ // ## isn't it faster to use TQStringList::split than parse it 3 times?
+ TQString _width = border.section(' ', 0, 0);
+ TQCString _style = border.section(' ', 1, 1).latin1();
+ TQString _color = border.section(' ', 2, 2);
+
+ pen.setWidth( ( int )( KoUnit::parseValue( _width, 1.0 ) ) );
+
+ if ( _style =="none" )
+ pen.setStyle( Qt::NoPen );
+ else if ( _style =="solid" )
+ pen.setStyle( Qt::SolidLine );
+ else if ( _style =="dashed" )
+ pen.setStyle( Qt::DashLine );
+ else if ( _style =="dotted" )
+ pen.setStyle( Qt::DotLine );
+ else if ( _style =="dot-dash" )
+ pen.setStyle( Qt::DashDotLine );
+ else if ( _style =="dot-dot-dash" )
+ pen.setStyle( Qt::DashDotDotLine );
+ else
+ kdDebug()<<" style undefined : "<<_style<<endl;
+
+ if ( _color.isEmpty() )
+ pen.setColor( TQColor() );
+ else
+ pen.setColor( TQColor( _color ) );
+
+ return pen;
+}
+
+//Return true when it's a reference to cell from sheet.
+bool KSpread::localReferenceAnchor( const TQString &_ref )
+{
+ bool isLocalRef = (_ref.find("http://") != 0 &&
+ _ref.find("mailto:") != 0 &&
+ _ref.find("ftp://") != 0 &&
+ _ref.find("file:") != 0 );
+ return isLocalRef;
+}
+
+
+TQString KSpread::Oasis::decodeFormula(const TQString& expr, const TDELocale* locale)
+{
+ // parsing state
+ enum { Start, InNumber, InString, InIdentifier, InReference, InSheetName } state;
+
+ // use locale settings
+ TQString decimal = locale ? locale->decimalSymbol() : ".";
+
+ // initialize variables
+ state = Start;
+ unsigned int i = 0;
+ const TQString ex = expr;
+ TQString result;
+
+ if (ex[0] == '=')
+ {
+ result="=";
+ ++i;
+ }
+
+ // main loop
+ while( i < ex.length() )
+ {
+ TQChar ch = ex[i];
+
+ switch( state )
+ {
+ case Start:
+ {
+ // check for number
+ if( ch.isDigit() )
+ {
+ state = InNumber;
+ }
+
+ // a string?
+ else if ( ch == '"' )
+ {
+ state = InString;
+ result.append( ex[i++] );
+ }
+
+ // beginning with alphanumeric ?
+ // could be identifier, cell, range, or function...
+ else if( isIdentifier( ch ) )
+ {
+ state = InIdentifier;
+ }
+
+ // [ marks sheet name for 3-d cell, e.g ['Sales Q3'.A4]
+ else if ( ch.unicode() == '[' )
+ {
+ ++i;
+ state = InReference;
+ // NOTE Stefan: As long as KSpread does not support fixed sheets eat the dollar sign.
+ if ( ex[i] == '$' ) ++i;
+ }
+
+ // decimal dot ?
+ else if ( ch == '.' )
+ {
+ if ( ex[i+1].isDigit() )
+ state = InNumber;
+ else
+ state = InReference;
+ }
+
+ // look for operator match
+ else
+ {
+ int op;
+ TQString s;
+
+ // check for two-chars operator, such as '<=', '>=', etc
+ s.append( ch ).append( ex[i+1] );
+ op = matchOperator( s );
+
+ // check for one-char operator, such as '+', ';', etc
+ if( op == Token::InvalidOp )
+ {
+ s = TQString( ch );
+ op = matchOperator( s );
+ }
+
+ // any matched operator ?
+ if ( op == Token::Equal )
+ {
+ result.append( "==" );
+ }
+ else
+ {
+ result.append( s );
+ }
+ if( op != Token::InvalidOp )
+ {
+ int len = s.length();
+ i += len;
+ }
+ else
+ {
+ ++i;
+ state = Start;
+ }
+ }
+ break;
+ }
+ case InReference:
+ {
+ // consume as long as alpha, dollar sign, underscore, or digit, or colon
+ if( isIdentifier( ch ) || ch.isDigit() || ch == ':' )
+ result.append( ex[i] );
+ else if ( ch == '.' && i > 0 && ex[i-1] != '[' && ex[i-1] != ':' )
+ result.append( '!' );
+ else if( ch == ']' )
+ state = Start;
+ else if ( ch == '\'' )
+ {
+ result.append( ex[i] );
+ state = InSheetName;
+ // NOTE Stefan: As long as KSpread does not support fixed sheets eat the dollar sign.
+ if ( ex[i] == '$' ) ++i;
+ }
+ else if ( ch != '.' )
+ {
+ state = Start;
+ break;
+ }
+ ++i;
+ break;
+ }
+ case InSheetName:
+ {
+ if ( ch == '\'' )
+ state = InReference;
+ result.append( ex[i] );
+ ++i;
+ break;
+ }
+ case InNumber:
+ {
+ // consume as long as it's digit
+ if( ch.isDigit() )
+ result.append( ex[i++] );
+ // convert '.' to decimal separator
+ else if ( ch == '.' )
+ {
+ result.append( decimal );
+ ++i;
+ }
+ // exponent ?
+ else if( ch.upper() == 'E' )
+ {
+ result.append( 'E' );
+ ++i;
+ }
+ // we're done with integer number
+ else
+ state = Start;
+ break;
+ }
+ case InString:
+ {
+ // consume until "
+ if( ch != '"' )
+ {
+ result.append( ex[i++] );
+ }
+ // we're done
+ else
+ {
+ result.append( ch );
+ ++i;
+ state = Start;
+ }
+ break;
+ }
+ case InIdentifier:
+ {
+ // consume as long as alpha, dollar sign, underscore, or digit
+ if( isIdentifier( ch ) || ch.isDigit() )
+ result.append( ex[i++] );
+ // we're done
+ else
+ state = Start;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+/*TQString KSpread::Oasis::encodeFormula(const TQString& expr, const TDELocale* locale)
+{
+ // TODO move Cell::convertFormulaToOasisFormat to this point
+ //expr = "not here yet";
+ //Q_UNUSED(locale);
+ kdDebug() << k_funcinfo << " not implemented"
+ tqFatal(0);
+}*/