diff options
Diffstat (limited to 'kspread/kspread_util.cpp')
-rw-r--r-- | kspread/kspread_util.cpp | 1218 |
1 files changed, 1218 insertions, 0 deletions
diff --git a/kspread/kspread_util.cpp b/kspread/kspread_util.cpp new file mode 100644 index 00000000..c7b28af1 --- /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); +}*/ |