File indexing completed on 2025-01-19 13:27:13
0001 /* This file is part of the KDE project 0002 Copyright (C) 2001 Enno Bartels <ebartels@nwn.de> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "applixspreadimport.h" 0021 0022 #include <QMessageBox> 0023 #include <QStringList> 0024 #include <QRegExp> 0025 #include <QList> 0026 #include <QTextStream> 0027 #include <QByteArray> 0028 #include <kdebug.h> 0029 #include <math.h> 0030 #include <KoFilterChain.h> 0031 #include <kpluginfactory.h> 0032 #include <sheets/Util.h> 0033 0034 K_PLUGIN_FACTORY_WITH_JSON(APPLIXSPREADImportFactory, "calligra_filter_applixspread2kspread.json", 0035 registerPlugin<APPLIXSPREADImport>();) 0036 0037 0038 APPLIXSPREADImport::APPLIXSPREADImport(QObject *parent, const QVariantList&) 0039 : KoFilter(parent) 0040 { 0041 } 0042 0043 QString APPLIXSPREADImport::nextLine(QTextStream & stream) 0044 { 0045 if (!m_nextPendingLine.isNull()) { 0046 const QString s = m_nextPendingLine; 0047 m_nextPendingLine.clear(); 0048 return s; 0049 } 0050 0051 QString s = stream.readLine(); 0052 m_instep += s.length(); 0053 if (m_instep > m_stepsize) { 0054 m_instep = 0; 0055 m_progress += 2; 0056 emit sigProgress(m_progress); 0057 } 0058 return s; 0059 } 0060 0061 struct t_mycolor { 0062 int r; 0063 int g; 0064 int b; 0065 0066 int c; 0067 int m; 0068 int y; 0069 int k; 0070 }; 0071 0072 struct t_rc { 0073 QStringList tabname; 0074 QStringList rc; 0075 }; 0076 0077 // Store shared formula definitions 0078 struct t_sharedFormula { 0079 int origRow; 0080 int origColumn; 0081 QString formula; 0082 }; 0083 0084 KoFilter::ConversionStatus APPLIXSPREADImport::convert(const QByteArray& from, const QByteArray& to) 0085 { 0086 0087 if (to != "application/x-kspread" || from != "application/x-applix-spreadsheet") 0088 return KoFilter::NotImplemented; 0089 0090 QFile in(m_chain->inputFile()); 0091 if (!in.open(QIODevice::ReadOnly)) { 0092 kError(30502) << "Unable to open input file!" << endl; 0093 in.close(); 0094 return KoFilter::FileNotFound; 0095 } 0096 0097 QString str; 0098 QList<t_mycolor*> mcol; 0099 0100 str += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 0101 "<!DOCTYPE spreadsheet>\n" 0102 "<spreadsheet mime=\"application/x-kspread\" editor=\"KSpread\" >\n" 0103 " <paper format=\"A4\" orientation=\"Portrait\" >\n" 0104 " <borders right=\"20\" left=\"20\" bottom=\"20\" top=\"20\" />\n" 0105 " <head/>\n" 0106 " <foot/>\n" 0107 " </paper>\n" 0108 // str += " <locale positivePrefixCurrencySymbol=\"True\" negativeMonetarySignPosition=\"1\" negativePrefixCurrencySymbol=\"True\" fracDigits=\"2\" thousandsSeparator=\" \" dateFormat=\"%A, %e. %B %Y\" timeFormat=\"%H:%M:%S\" monetaryDecimalSymbol=\",\" weekStartsMonday=\"True\" currencySymbol=\"DM\" negativeSign=\"-\" positiveSign=\"\" positiveMonetarySignPosition=\"1\" decimalSymbol=\",\" monetaryThousandsSeparator=\" \" dateFormatShort=\"%d.%m.%Y\" />\n"; 0109 " <map markerColumn=\"1\" activeTable=\"Table1\" markerRow=\"1\" >\n"; 0110 // str += " <table columnnumber=\"0\" borders=\"0\" hide=\"0\" hidezero=\"0\" firstletterupper=\"0\" grid=\"1\" formular=\"0\" lcmode=\"0\" name=\"Tabelle1\" >\n"; 0111 0112 0113 // QTextStream 0114 QTextStream stream(&in); 0115 m_stepsize = in.size() / 50; 0116 m_instep = 0; 0117 m_progress = 0; 0118 int pos; 0119 QString tabctr ; // Tab control (current tab name) 0120 QStringList typefacetab; 0121 QHash<QString, t_sharedFormula> sharedFormulas; 0122 0123 t_rc my_rc; 0124 0125 0126 0127 /************************************************************************** 0128 * Read header * 0129 **************************************************************************/ 0130 if (! readHeader(stream)) return KoFilter::StupidError; 0131 0132 while (!stream.atEnd()) { 0133 // Read one line 0134 QString mystr = nextLine(stream); 0135 0136 kDebug() << "INPUT :" << mystr; 0137 0138 0139 /********************************************************************** 0140 * Looking for the colormap * 0141 **********************************************************************/ 0142 if (mystr.startsWith("COLORMAP")) { 0143 readColormap(stream, mcol); 0144 } 0145 0146 /********************************************************************** 0147 * Looking for the typeface table * 0148 **********************************************************************/ 0149 else if (mystr.startsWith("TYPEFACE TABLE")) { 0150 readTypefaceTable(stream, typefacetab); 0151 } 0152 0153 /********************************************************************** 0154 * Looking for some View-Information * 0155 **********************************************************************/ 0156 else if (mystr.startsWith("View Start, Name:")) { 0157 readView(stream, mystr, my_rc); 0158 } 0159 0160 0161 /********************************************************************** 0162 * Detect ( at the first place of the Line * 0163 **********************************************************************/ 0164 else if (mystr[0] == '(') { 0165 0166 // Delete '(' 0167 mystr.remove(0, 1); 0168 0169 // Remember length of the string 0170 if (mystr.length() >= 80 - 1) { 0171 //kDebug() << " Line >= 80 chars"; 0172 bool ok = true; 0173 do { 0174 QString mystrn = nextLine(stream); 0175 if (mystrn[0] == ' ') { 0176 mystrn.remove(0, 1); 0177 mystr += mystrn; 0178 } else { 0179 m_nextPendingLine = mystrn; 0180 ok = false; 0181 } 0182 } while (ok); 0183 kDebug() << " Long line -> new input line:" << mystr; 0184 } 0185 0186 // Search for ')' 0187 pos = mystr.indexOf(')'); 0188 QString typestr = mystr.left(pos); 0189 0190 // Delete typeformat info incl. Space 0191 mystr.remove(0, pos + 1); 0192 0193 // At this point mystr looks like " A!E15: 10" 0194 Q_ASSERT(mystr.startsWith(' ')); 0195 0196 // Extract table number/name 0197 pos = mystr.indexOf('!'); 0198 0199 // Copy tabnumber information 0200 QString tabnostr = mystr.left(pos).mid(1); 0201 0202 // Delete tabnumber information 0203 mystr.remove(0, pos + 1); 0204 0205 // At this point mystr looks like "E15: 10" 0206 pos = 0; 0207 while (mystr[pos].isLetter()) { 0208 ++pos; 0209 } 0210 const QString cellcolstr = mystr.mid(0, pos); 0211 // Transform ascii column to int column 0212 const int icol = translateColumnNumber(cellcolstr); 0213 0214 int endPos = pos; 0215 while (mystr[endPos].isDigit()) { 0216 ++endPos; 0217 } 0218 0219 const QString rowstr = mystr.mid(pos, endPos - pos); 0220 bool ok; 0221 const int irow = rowstr.toInt(&ok); 0222 Q_ASSERT(ok); 0223 0224 // OK, what do we have now? 0225 const QChar contentType = mystr.at(endPos); 0226 0227 // Delete cellnumber information 0228 mystr.remove(0, endPos + 1); 0229 if (mystr.startsWith(' ')) { 0230 mystr.remove(0, 1); 0231 } 0232 0233 // ';' // first instance (definition) of a shared formula 0234 // '.' // instance (usage) of a shared formula 0235 // ':' // simple value 0236 0237 if (contentType == ';' || contentType == '.') { 0238 // Skip the value 0239 int pos = 0; 0240 while (!mystr.at(pos).isSpace()) { 0241 ++pos; 0242 } 0243 while (mystr.at(pos).isSpace()) { 0244 ++pos; 0245 } 0246 kDebug() << "Skipping value" << mystr.mid(0, pos); 0247 mystr.remove(0, pos); 0248 0249 if (contentType == ';') { 0250 if (mystr.at(0) == '+') 0251 mystr[0] = '='; 0252 Q_ASSERT(mystr.at(0) == '='); 0253 } 0254 } 0255 0256 // Replace part for this characters: <, >, & 0257 mystr.replace(QRegExp("&"), "&"); 0258 mystr.replace(QRegExp("<"), "<"); 0259 mystr.replace(QRegExp(">"), ">"); 0260 0261 0262 // Replace part for Applix Characters 0263 bool foundSpecialCharakter; 0264 0265 do { 0266 // initialize 0267 foundSpecialCharakter = false; 0268 0269 pos = mystr.indexOf('^'); 0270 0271 // is there a special character ? 0272 if (pos > -1) { 0273 // i have found a special character ! 0274 foundSpecialCharakter = true; 0275 0276 // translate the applix special character 0277 const QChar newchar = specCharfind(mystr[pos+1], mystr[pos+2]); 0278 0279 // replace the character 0280 mystr.replace(pos, 3, newchar); 0281 } 0282 0283 } while (foundSpecialCharakter == true); 0284 0285 0286 // examine the typestring 0287 // split typestring in 3 parts by an | 0288 0289 const int pos1 = typestr.indexOf('|'); 0290 const int pos2 = typestr.lastIndexOf('|'); 0291 const QString typeFormStr = typestr.left(pos1); 0292 const QString typeCharStr = typestr.mid(pos1 + 1, pos2 - pos1 - 1); 0293 const QString typeCellStr = typestr.right(typestr.length() - pos2 - 1); 0294 0295 // Is it a new table 0296 if (tabctr != tabnostr) { 0297 // is it not the first table 0298 if (!(tabctr.isNull())) str += " </table>\n"; 0299 0300 str += " <table columnnumber=\"0\" borders=\"0\" hide=\"0\" hidezero=\"0\" firstletterupper=\"0\" grid=\"1\" formular=\"0\" lcmode=\"0\" name=\"" + 0301 tabnostr + 0302 "\" >\n"; 0303 0304 tabctr = tabnostr; 0305 0306 // Searching for the rowcol part and adding to the hole string 0307 pos = my_rc.tabname.indexOf(tabnostr); 0308 if (pos > -1) str += my_rc.rc[pos]; 0309 } 0310 0311 //kDebug()<<" Data : Text :"<<mystr<<" tab :"<<tabnostr<<""<< cellnostr <<"" <<ccol<<"" << irow<<""<< typeFormStr<<"" <<typeCharStr<<"" <<typeCellStr; 0312 0313 /******************************************************************** 0314 * Support for shared formulas * 0315 ********************************************************************/ 0316 0317 if (contentType == ';') { 0318 0319 mystr = convertFormula(mystr); 0320 0321 const QString formulaRefLine = nextLine(stream); // "Formula: 358" 0322 kDebug() << "shared formula: next line is" << formulaRefLine; 0323 if (!formulaRefLine.startsWith("Formula: ")) { 0324 kError() << "Missing formula ID after" << mystr; 0325 } else { 0326 const QString key = formulaRefLine.mid(9); 0327 t_sharedFormula sf; 0328 sf.origColumn = icol; 0329 sf.origRow = irow; 0330 sf.formula = mystr; 0331 sharedFormulas.insert(key, sf); 0332 } 0333 } else if (contentType == '.') { 0334 const QString key = mystr; 0335 const t_sharedFormula sf = sharedFormulas.value(key); 0336 0337 // adjust the formula: if it came from C1, with =A1+B1, 0338 // and we're now in C3, then it needs to become =A3+B3, just like copy/paste would do. 0339 mystr = Calligra::Sheets::Util::adjustFormulaReference(sf.formula, sf.origRow, sf.origColumn, irow, icol); 0340 } 0341 0342 /******************************************************************** 0343 * examine character format String, split it up in basic parts * 0344 ********************************************************************/ 0345 int bold = 0, italic = 0, underline = 0, fontsize = 12, fontnr = -1; 0346 int fg = -1; // fg = foregound 0347 0348 const QStringList typeCharList = typeCharStr.split(',', QString::SkipEmptyParts); 0349 Q_FOREACH(const QString& typeChar, typeCharList) { 0350 // Output 0351 kDebug() << "typeChar: " << typeChar; 0352 0353 if (typeChar == "B") { 0354 kDebug() << " bold"; 0355 bold = 1; 0356 } else if (typeChar == "I") { 0357 kDebug() << " = italic"; 0358 italic = 1; 0359 } else if (typeChar == "U") { 0360 kDebug() << " = underline"; 0361 underline = 1; 0362 } else if (typeChar.startsWith("FG")) { 0363 fg = typeChar.mid(2).toInt(); 0364 kDebug() << " = Colornr" << fg; 0365 } else if (typeChar.startsWith("TF")) { 0366 fontnr = typeChar.mid(2).toInt(); 0367 kDebug() << " = Font :" << fontnr << "" << typefacetab[fontnr]; 0368 } else if (typeChar.startsWith('P')) { 0369 fontsize = typeChar.mid(1).toInt(); 0370 kDebug() << " = Fontsize" << fontsize; 0371 } else { 0372 kDebug() << " = ??? Unknown typeChar:" << typeChar; 0373 } 0374 } 0375 kDebug(); 0376 0377 0378 /******************************************************************** 0379 * examine pos format String, split it up in basic parts * 0380 ********************************************************************/ 0381 int align = 0, valign = 0; 0382 0383 const QStringList typeFormList = typeFormStr.split(',', QString::SkipEmptyParts); 0384 Q_FOREACH(const QString& typeFormat, typeFormList) { 0385 // Grep horizontal alignment 0386 if (typeFormat == "1") { 0387 kDebug() << " = left align"; 0388 align = 1; // left 0389 } else if (typeFormat == "2") { 0390 kDebug() << " = right align"; 0391 align = 3; // right 0392 } else if (typeFormat == "3") { 0393 kDebug() << " = center align"; 0394 align = 2; // center 0395 } 0396 0397 // Grep vertical alignment 0398 else if (typeFormat == "VT") { 0399 kDebug() << " = top valign"; 0400 valign = 1; // top 0401 } else if (typeFormat == "VC") { 0402 kDebug() << " = center valign"; 0403 valign = 0; // center - default (2) 0404 } else if (typeFormat == "VB") { 0405 kDebug() << " = bottom valign"; 0406 valign = 3; // bottom 0407 } else { 0408 kDebug() << " = ??? unknown typeFormat" << typeFormat; 0409 } 0410 } 0411 0412 0413 /******************************************************************** 0414 * examine cell format String, split it up in basic parts * 0415 ********************************************************************/ 0416 int topPenWidth = 0, bottomPenWidth = 0, leftPenWidth = 0, rightPenWidth = 0, fg_bg = -1; 0417 int topPenStyle = 0, bottomPenStyle = 0, leftPenStyle = 0, rightPenStyle = 0; 0418 int brushstyle = 0, brushcolor = 1; 0419 int topbrushstyle = 0, topbrushcolor = 1, topfg_bg = 1; 0420 int leftbrushstyle = 0, leftbrushcolor = 1, leftfg_bg = 1; 0421 int rightbrushstyle = 0, rightbrushcolor = 1, rightfg_bg = 1; 0422 int bottombrushstyle = 0, bottombrushcolor = 1, bottomfg_bg = 1; 0423 0424 const QStringList typeCellList = typeCellStr.split(',', QString::SkipEmptyParts); 0425 Q_FOREACH(/*can't use const QString&*/ QString typeCell, typeCellList) { 0426 0427 if (typeCell[0] == 'T') { 0428 kDebug() << " = top"; 0429 transPenFormat(typeCell, &topPenWidth, &topPenStyle); 0430 0431 if (typeCell.length() > 2) { 0432 typeCell.remove(0, 2); 0433 filterSHFGBG(typeCell, &topbrushstyle, &topbrushcolor, &topfg_bg); 0434 } 0435 0436 } 0437 0438 else if (typeCell[0] == 'B') { 0439 kDebug() << " = bottom"; 0440 transPenFormat(typeCell, &bottomPenWidth, &bottomPenStyle); 0441 0442 if (typeCell.length() > 2) { 0443 typeCell.remove(0, 2); 0444 filterSHFGBG(typeCell, &bottombrushstyle, &bottombrushcolor, &bottomfg_bg); 0445 } 0446 } 0447 0448 else if (typeCell[0] == 'L') { 0449 kDebug() << " = left"; 0450 transPenFormat(typeCell, &leftPenWidth, &leftPenStyle); 0451 0452 if (typeCell.length() > 2) { 0453 typeCell.remove(0, 2); 0454 filterSHFGBG(typeCell, &leftbrushstyle, &leftbrushcolor, &leftfg_bg); 0455 } 0456 } 0457 0458 else if (typeCell[0] == 'R') { 0459 kDebug() << " = right"; 0460 transPenFormat(typeCell, &rightPenWidth, &rightPenStyle); 0461 0462 if (typeCell.length() > 2) { 0463 typeCell.remove(0, 2); 0464 filterSHFGBG(typeCell, &rightbrushstyle, &rightbrushcolor, &rightfg_bg); 0465 } 0466 } 0467 0468 else if ((typeCell.startsWith("SH")) || (typeCell.startsWith("FG")) || 0469 (typeCell.startsWith("BG"))) { 0470 kDebug() << " ="; 0471 filterSHFGBG(typeCell, &brushstyle, &fg_bg, &brushcolor); 0472 } 0473 0474 else { 0475 kDebug() << " = ??? unknown typeCell" << typeCell; 0476 } 0477 0478 } 0479 0480 0481 0482 0483 0484 QString col; 0485 0486 // create kspread fileformat output 0487 str += " <cell row=\"" + QString::number(irow) + "\"" 0488 " column=\"" + QString::number(icol) + "\">\n"; 0489 if (bold == 1 || italic == 1 || underline == 1 || 0490 align != 0 || valign != 0 || 0491 topPenStyle != 0 || bottomPenStyle != 0 || 0492 leftPenStyle != 0 || rightPenStyle != 0 || fg != -1 || fg_bg != -1 || 0493 fontsize != 12 || brushstyle != 0 || fontnr != -1) { 0494 str += " <format"; 0495 if (brushstyle != 0) { 0496 str += " brushstyle=\"" + QString::number(brushstyle) + "\" " 0497 " brushcolor=\"" + 0498 writeColor(mcol.at(brushcolor)) + 0499 "\""; 0500 } 0501 0502 if (align != 0) str += " align=\"" + QString::number(align) + "\" "; 0503 if (valign != 0) str += " alignY=\"" + QString::number(valign) + "\" "; 0504 if (fg_bg != -1) { 0505 str += " bgcolor=\"" + 0506 writeColor(mcol.at(fg_bg)) + 0507 "\" "; 0508 } 0509 str += ">\n"; 0510 0511 // Font color 0512 if (fg != -1) { 0513 str += " <pen width=\"0\" style=\"1\" color=\"" + 0514 writeColor(mcol.at(fg)) + 0515 "\" />\n"; 0516 } 0517 0518 // Left border 0519 if (leftPenWidth > 0) { 0520 str += " <left-border>\n"; 0521 col = writeColor(mcol.at(leftfg_bg)); 0522 writePen(str, leftPenWidth, leftPenStyle, col); 0523 str += " </left-border>\n"; 0524 } 0525 0526 // Right border 0527 if (rightPenWidth > 0) { 0528 str += " <right-border>\n"; 0529 col = writeColor(mcol.at(rightfg_bg)); 0530 writePen(str, rightPenWidth, rightPenStyle, col); 0531 str += " </right-border>\n"; 0532 } 0533 0534 // Bottom border 0535 if (bottomPenWidth > 0) { 0536 str += " <bottom-border>\n"; 0537 col = writeColor(mcol.at(bottomfg_bg)); 0538 writePen(str, bottomPenWidth, bottomPenStyle, col); 0539 str += " </bottom-border>\n"; 0540 } 0541 0542 // Top border 0543 if (topPenWidth > 0) { 0544 str += " <top-border>\n"; 0545 col = writeColor(mcol.at(topfg_bg)); 0546 writePen(str, topPenWidth, topPenStyle, col); 0547 str += " </top-border>\n"; 0548 } 0549 0550 // Font (size and family) 0551 if ((fontsize != 12) || (fontnr != -1)) { 0552 str += " <font "; 0553 // Fontsize 0554 if (fontsize != 12) { 0555 str += "size=\"" + 0556 QString::number(fontsize) + 0557 "\" "; 0558 } 0559 // Fontfamily 0560 if (fontnr != -1) { 0561 str += "family=\"" + 0562 typefacetab[fontnr].toLatin1() + 0563 "\" "; 0564 } 0565 str += "weight=\"0\""; 0566 0567 if (italic == 1) str += " italic=\"yes\""; 0568 if (bold == 1) str += " bold=\"yes\""; 0569 if (underline == 1) str += " underline=\"yes\""; 0570 0571 str += " />\n"; 0572 } 0573 str += " </format>\n"; 0574 } 0575 str += " <text>" + mystr + "</text>\n" 0576 " </cell>\n"; 0577 } 0578 0579 } 0580 emit sigProgress(100); 0581 0582 str += " </table>\n" 0583 " </map>\n" 0584 "</spreadsheet>\n"; 0585 // str += "</DOC>\n"; 0586 0587 kDebug() << "Text" << str; 0588 0589 KoStoreDevice* out = m_chain->storageFile("root", KoStore::Write); 0590 0591 if (!out) { 0592 kError(38000/*30502*/) << "Unable to open output file!" << endl; 0593 in.close(); 0594 return KoFilter::StorageCreationError; 0595 } 0596 0597 QByteArray cstring = str.toUtf8(); 0598 out->write(cstring, cstring.length()); 0599 0600 in.close(); 0601 return KoFilter::OK; 0602 } 0603 0604 0605 0606 0607 /****************************************************************************** 0608 * function: specCharfind * 0609 ******************************************************************************/ 0610 QChar 0611 APPLIXSPREADImport::specCharfind(QChar a, QChar b) 0612 { 0613 QChar chr; 0614 0615 if ((a == 'n') && (b == 'p')) chr = 0x00DF; // 'ß'; 0616 0617 0618 else if ((a == 'n') && (b == 'c')) chr = 0x00D2; // 'Ò'; 0619 else if ((a == 'p') && (b == 'c')) chr = 0x00F2; // 'ò'; 0620 0621 else if ((a == 'n') && (b == 'd')) chr = 0x00D3; // 'Ó'; 0622 else if ((a == 'p') && (b == 'd')) chr = 0x00F3; // 'ó'; 0623 0624 else if ((a == 'n') && (b == 'e')) chr = 0x00D4; // 'Ô'; 0625 else if ((a == 'p') && (b == 'e')) chr = 0x00F4; // 'ô'; 0626 0627 else if ((a == 'n') && (b == 'f')) chr = 0x00D5; // 'Õ'; 0628 else if ((a == 'p') && (b == 'f')) chr = 0x00F5; // 'õ'; 0629 0630 else if ((a == 'n') && (b == 'g')) chr = 0x00D6; // 'Ö'; 0631 else if ((a == 'p') && (b == 'g')) chr = 0x00F6; // 'ö'; 0632 0633 0634 0635 else if ((a == 'n') && (b == 'j')) chr = 0x00D9; // 'Ù'; 0636 else if ((a == 'p') && (b == 'j')) chr = 0x00F9; // 'ù'; 0637 0638 else if ((a == 'n') && (b == 'k')) chr = 0x00DA; // 'Ú'; 0639 else if ((a == 'p') && (b == 'k')) chr = 0x00FA; // 'ú'; 0640 0641 else if ((a == 'n') && (b == 'l')) chr = 0x00DB; // 'Û'; 0642 else if ((a == 'p') && (b == 'l')) chr = 0x00FB; // 'û'; 0643 0644 else if ((a == 'n') && (b == 'm')) chr = 0x00DC; // 'Ü'; 0645 else if ((a == 'p') && (b == 'm')) chr = 0x00FC; // 'ü'; 0646 0647 0648 0649 else if ((a == 'm') && (b == 'a')) chr = 0x00C0; // 'À'; 0650 else if ((a == 'o') && (b == 'a')) chr = 0x00E0; // 'à'; 0651 0652 else if ((a == 'm') && (b == 'b')) chr = 0x00C1; // 'Á'; 0653 else if ((a == 'o') && (b == 'b')) chr = 0x00E1; // 'á'; 0654 0655 else if ((a == 'm') && (b == 'c')) chr = 0x00C2; // 'Â'; 0656 else if ((a == 'o') && (b == 'c')) chr = 0x00E2; // 'â'; 0657 0658 else if ((a == 'm') && (b == 'd')) chr = 0x00C3; // 'Ã'; 0659 else if ((a == 'o') && (b == 'd')) chr = 0x00E3; // 'ã'; 0660 0661 else if ((a == 'm') && (b == 'e')) chr = 0x00C4; // 'Ä'; 0662 else if ((a == 'o') && (b == 'e')) chr = 0x00E4; // 'ä'; 0663 0664 else if ((a == 'm') && (b == 'f')) chr = 0x00C5; // 'Å'; 0665 else if ((a == 'o') && (b == 'f')) chr = 0x00E5; // 'å'; 0666 0667 else if ((a == 'm') && (b == 'g')) chr = 0x00C6; // 'Æ'; 0668 else if ((a == 'o') && (b == 'g')) chr = 0x00E6; // 'æ'; 0669 0670 0671 0672 else if ((a == 'm') && (b == 'i')) chr = 0x00C8; // 'È'; 0673 else if ((a == 'o') && (b == 'i')) chr = 0x00E8; // 'è'; 0674 0675 else if ((a == 'm') && (b == 'j')) chr = 0x00C9; // 'É'; 0676 else if ((a == 'o') && (b == 'j')) chr = 0x00E9; // 'é'; 0677 0678 else if ((a == 'm') && (b == 'k')) chr = 0x00CA; // 'Ê'; 0679 else if ((a == 'o') && (b == 'k')) chr = 0x00EA; // 'ê'; 0680 0681 else if ((a == 'm') && (b == 'l')) chr = 0x00CB; // 'Ë'; 0682 else if ((a == 'o') && (b == 'l')) chr = 0x00EB; // 'ë'; 0683 0684 0685 0686 else if ((a == 'm') && (b == 'm')) chr = 0x00CC; // 'Ì'; 0687 else if ((a == 'o') && (b == 'm')) chr = 0x00EC; // 'ì'; 0688 0689 else if ((a == 'm') && (b == 'n')) chr = 0x00CD; // 'Í'; 0690 else if ((a == 'o') && (b == 'n')) chr = 0x00ED; // 'í'; 0691 0692 else if ((a == 'm') && (b == 'o')) chr = 0x00CE; // 'Î'; 0693 else if ((a == 'o') && (b == 'o')) chr = 0x00EE; // 'î'; 0694 0695 else if ((a == 'm') && (b == 'p')) chr = 0x00CF; // 'Ï'; 0696 else if ((a == 'o') && (b == 'p')) chr = 0x00EF; // 'ï'; 0697 0698 0699 else if ((a == 'n') && (b == 'b')) chr = 0x00D1; // 'Ñ'; 0700 else if ((a == 'p') && (b == 'b')) chr = 0x00F1; // 'ñ'; 0701 0702 0703 else if ((a == 'k') && (b == 'c')) chr = 0x00A2; // '¢'; 0704 else if ((a == 'k') && (b == 'j')) chr = 0x00A9; // '©'; 0705 else if ((a == 'l') && (b == 'f')) chr = 0x00B5; // 'µ'; 0706 else if ((a == 'n') && (b == 'i')) chr = 0x00D8; // 'Ø'; 0707 else if ((a == 'p') && (b == 'i')) chr = 0x00F8; // 'ø'; 0708 0709 else if ((a == 'l') && (b == 'j')) chr = 0x00B9; // '¹'; 0710 else if ((a == 'l') && (b == 'c')) chr = 0x00B2; // '²'; 0711 else if ((a == 'l') && (b == 'd')) chr = 0x00B3; // '³'; 0712 0713 else if ((a == 'l') && (b == 'm')) chr = 0x0152; // 'Œ'; 0714 else if ((a == 'l') && (b == 'n')) chr = 0x0153; // 'œ'; 0715 else if ((a == 'l') && (b == 'o')) chr = 0x0178; // 'Ÿ'; 0716 0717 else if ((a == 'l') && (b == 'a')) chr = 0x00B0; // '°'; 0718 0719 else if ((a == 'k') && (b == 'o')) chr = 0x00AE; // '®'; 0720 else if ((a == 'k') && (b == 'h')) chr = 0x00A7; // '§'; 0721 else if ((a == 'k') && (b == 'd')) chr = 0x00A3; // '£'; 0722 0723 else if ((a == 'p') && (b == 'a')) chr = 0x00F0; // 'ð'; 0724 else if ((a == 'n') && (b == 'a')) chr = 0x00D0; // 'Ð'; 0725 0726 else if ((a == 'l') && (b == 'l')) chr = 0x00BB; // '»'; 0727 else if ((a == 'k') && (b == 'l')) chr = 0x00AB; // '«'; 0728 0729 else if ((a == 'l') && (b == 'k')) chr = 0x00BA; // 'º'; 0730 0731 else if ((a == 'l') && (b == 'h')) chr = 0x00B7; // '·'; 0732 0733 else if ((a == 'k') && (b == 'b')) chr = 0x00A1; // '¡'; 0734 0735 else if ((a == 'k') && (b == 'e')) chr = 0x20AC; // '€'; 0736 0737 else if ((a == 'l') && (b == 'b')) chr = 0x00B1; // '±'; 0738 0739 else if ((a == 'l') && (b == 'p')) chr = 0x00BF; // '¿'; 0740 0741 else if ((a == 'k') && (b == 'f')) chr = 0x00A5; // '¥'; 0742 0743 else if ((a == 'p') && (b == 'o')) chr = 0x00FE; // 'þ'; 0744 else if ((a == 'n') && (b == 'o')) chr = 0x00DE; // 'Þ'; 0745 0746 else if ((a == 'n') && (b == 'n')) chr = 0x00DD; // 'Ý'; 0747 else if ((a == 'p') && (b == 'n')) chr = 0x00FD; // 'ý'; 0748 else if ((a == 'p') && (b == 'p')) chr = 0x00FF; // 'ÿ'; 0749 0750 else if ((a == 'k') && (b == 'k')) chr = 0x00AA; // 'ª'; 0751 0752 else if ((a == 'k') && (b == 'm')) chr = 0x00AC; // '¬'; 0753 else if ((a == 'p') && (b == 'h')) chr = 0x00F7; // '÷'; 0754 0755 else if ((a == 'k') && (b == 'g')) chr = 0x007C; // '|'; 0756 0757 else if ((a == 'l') && (b == 'e')) chr = 0x0027; // '\''; 0758 0759 else if ((a == 'k') && (b == 'i')) chr = 0x0161; // 'š'; 0760 0761 else if ((a == 'k') && (b == 'n')) chr = 0x00AD; // ''; 0762 0763 else if ((a == 'k') && (b == 'p')) chr = 0x00AF; // '¯'; 0764 0765 else if ((a == 'l') && (b == 'g')) chr = 0x00B6; // '¶'; 0766 0767 else if ((a == 'l') && (b == 'i')) chr = 0x017E; // 'ž'; 0768 0769 else if ((a == 'm') && (b == 'h')) chr = 0x00C7; // 'Ç'; 0770 else if ((a == 'o') && (b == 'h')) chr = 0x00E7; // 'ç'; 0771 0772 else if ((a == 'n') && (b == 'h')) chr = 0x00D7; // '×'; 0773 0774 else if ((a == 'k') && (b == 'a')) chr = 0x0020; // ' '; 0775 0776 else if ((a == 'a') && (b == 'j')) chr = 0x0021; // '!'; 0777 0778 else chr = 0x0023; // '#'; 0779 0780 return chr; 0781 } 0782 0783 0784 0785 /****************************************************************************** 0786 * function: writePen * 0787 ******************************************************************************/ 0788 void 0789 APPLIXSPREADImport::writePen(QString &str, int penwidth, int penstyle, const QString &framecolor) 0790 { 0791 str += " <pen width=\"" + 0792 0793 // width of the pen 0794 QString::number(penwidth) + 0795 "\" style=\"" + 0796 0797 // style of the pen 0798 QString::number(penstyle) + 0799 "\" color=\"" + 0800 0801 // color of the pen 0802 framecolor + 0803 "\" />\n"; 0804 0805 } 0806 0807 0808 0809 /****************************************************************************** 0810 * function: writeColor * 0811 ******************************************************************************/ 0812 QString 0813 APPLIXSPREADImport::writeColor(t_mycolor *mc) 0814 { 0815 char rgb[20]; 0816 0817 // printf (" WriteColor: <%d>-<%d>-<%d> <%d>-<%d>-<%d>-<%d>\n", 0818 // mc->r, mc->g, mc->b, 0819 // mc->c, mc->m, mc->y, mc->k); 0820 0821 sprintf(rgb, "#%02X%02X%02X", mc->r, mc->g, mc->b); 0822 QString bla = rgb; 0823 0824 0825 return bla; 0826 } 0827 0828 0829 0830 0831 /****************************************************************************** 0832 * function: readTypefaceTable * 0833 ******************************************************************************/ 0834 void 0835 APPLIXSPREADImport::readTypefaceTable(QTextStream &stream, QStringList &typefacetab) 0836 { 0837 int tftabCounter = 0; 0838 QString mystr; 0839 0840 // Read the colormap 0841 kDebug() << "Reading typeface table:"; 0842 0843 bool ok = true; 0844 do { 0845 mystr = nextLine(stream); 0846 // FIXME: What happens if the magic words are not present in the stream? 0847 if (mystr == "END TYPEFACE TABLE") ok = false; 0848 else { 0849 //printf (" %2d: <%s>\n", tftabCounter, mystr.toLatin1()); 0850 typefacetab.append(mystr); 0851 tftabCounter++; 0852 } 0853 } while (ok == true); 0854 0855 kDebug() << "... done"; 0856 } 0857 0858 0859 0860 /****************************************************************************** 0861 * function: readColormap * 0862 ******************************************************************************/ 0863 void 0864 APPLIXSPREADImport::readColormap(QTextStream &stream, QList<t_mycolor*> &mcol) 0865 { 0866 int contcount, pos; 0867 0868 QString colstr, mystr; 0869 kDebug() << "Reading colormap:"; 0870 0871 bool ok = true; 0872 0873 do { 0874 0875 mystr = nextLine(stream).trimmed(); 0876 0877 if (mystr == "END COLORMAP") ok = false; 0878 else { 0879 kDebug() << " ->" << mystr; 0880 0881 // Count the number of whitespaces 0882 contcount = mystr.count(' '); 0883 kDebug() << "contcount:" << contcount; 0884 contcount -= 5; 0885 0886 // Begin off interest 0887 pos = mystr.indexOf(" 0 "); 0888 0889 // get colorname 0890 colstr = mystr.left(pos); 0891 mystr.remove(0, pos + 1); 0892 mystr = mystr.trimmed(); 0893 0894 t_mycolor *tmc = new t_mycolor; 0895 0896 // get sub colors 0897 pos = sscanf(mystr.toLatin1(), "0 %d %d %d %d 0", 0898 &tmc->c, &tmc->m, &tmc->y, &tmc->k); 0899 0900 printf(" - <%-20s> <%-15s> <%3d> <%3d> <%3d> <%3d> pos: %d\n", 0901 mystr.toLatin1().data(), 0902 colstr.toLatin1().data(), 0903 tmc->c, tmc->m, tmc->y, tmc->k, pos); 0904 0905 // Color transformation cmyk -> rgb 0906 tmc->r = 255 - (tmc->c + tmc->k); 0907 if (tmc->r < 0) tmc->r = 0; 0908 0909 tmc->g = 255 - (tmc->m + tmc->k); 0910 if (tmc->g < 0) tmc->g = 0; 0911 0912 tmc->b = 255 - (tmc->y + tmc->k); 0913 if (tmc->b < 0) tmc->b = 0; 0914 0915 mcol.append(tmc); 0916 } 0917 0918 } while (ok == true); 0919 0920 kDebug() << "... done" << mcol.count(); 0921 0922 foreach(t_mycolor* emp, mcol) { 0923 printf(" c:%3d m:%3d y:%3d k:%3d r:%3d g:%3d b:%3d\n", 0924 emp->c, emp->m, emp->y, emp->k, emp->r, emp->g, emp->b); 0925 } 0926 } 0927 0928 0929 0930 0931 /****************************************************************************** 0932 * function: readColormap * 0933 ******************************************************************************/ 0934 void 0935 APPLIXSPREADImport::readView(QTextStream &stream, const QString &instr, t_rc &rc) 0936 { 0937 QString rowcolstr; 0938 QString mystr, tabname; 0939 0940 kDebug() << "Reading View"; 0941 0942 tabname = instr; 0943 0944 tabname.remove(0, 19); 0945 tabname.remove(tabname.length() - 2, 2); 0946 kDebug() << " - Table name:" << tabname; 0947 0948 bool ok = true; 0949 do { 0950 mystr = nextLine(stream); 0951 0952 kDebug() << "" << mystr; 0953 if (mystr.startsWith("View End, Name:")) ok = false; 0954 else { 0955 // COLUMN Widths 0956 if (mystr.startsWith("View Column Widths")) { 0957 kDebug() << " - Column Widths"; 0958 mystr.remove(0, 20); 0959 kDebug() << "" << mystr; 0960 0961 int colwidth, icolumn; 0962 char ccolumn; 0963 0964 // loop 0965 QStringList ColumnList; 0966 ColumnList = mystr.split(' '); 0967 0968 for (QStringList::Iterator it = ColumnList.begin(); it != ColumnList.end(); ++it) { 0969 0970 sscanf((*it).toLatin1(), "%c:%d", &ccolumn, &colwidth); 0971 int len = (*it).length(); 0972 int pos = (*it).indexOf(':'); 0973 (*it).remove(pos, len - pos); 0974 0975 printf(" >%s<- -<%c><%d> \n", (*it).toLatin1().data(), ccolumn, colwidth); 0976 0977 // Transformat ascii column to int column 0978 icolumn = translateColumnNumber(*it); 0979 0980 //icolumn = ccolumn - 64; 0981 // Translate the column width right from applix to kspread 0982 icolumn = icolumn * 5; 0983 0984 0985 rowcolstr += " <column width=\"" + 0986 QString::number(colwidth) + 0987 "\" column=\"" + 0988 QString::number(icolumn) + 0989 "\" >\n" 0990 " <format/>\n" 0991 " </column>\n"; 0992 } 0993 } 0994 0995 // ROW Heights 0996 else if (mystr.startsWith("View Row Heights")) { 0997 kDebug() << " - Row Heights"; 0998 mystr.remove(0, 17); 0999 kDebug() << "" << mystr; 1000 1001 int irow, rowheight; 1002 1003 // loop 1004 QStringList RowList; 1005 RowList = mystr.split(' '); 1006 1007 for (QStringList::Iterator it = RowList.begin(); it != RowList.end(); ++it) { 1008 sscanf((*it).toLatin1(), " %d:%d", 1009 &irow, &rowheight); 1010 printf(" row: %2d height: %2d\n", irow, rowheight); 1011 if (rowheight > 32768) rowheight -= 32768; 1012 printf(" height: %2d\n", rowheight); 1013 rowcolstr += " <row row=\"" + 1014 QString::number(irow) + 1015 "\" height=\"" + 1016 QString::number(rowheight) + 1017 "\" >\n" 1018 " <format/>\n" 1019 " </row>\n"; 1020 } 1021 1022 1023 } 1024 } // else != END COLORMAP 1025 } while (ok == true); 1026 1027 // tabname append to my list 1028 // tabname append to my list 1029 rc.tabname.append(tabname); 1030 rc.rc.append(rowcolstr); 1031 1032 printf("%s %s\n", tabname.toLatin1().data(), 1033 rowcolstr.toLatin1().data()); 1034 1035 printf("...done \n\n"); 1036 } 1037 1038 1039 1040 1041 1042 /****************************************************************************** 1043 * function: filterSHFGBG * 1044 ******************************************************************************/ 1045 void 1046 APPLIXSPREADImport::filterSHFGBG(const QString &it, int *style, int *bgcolor, 1047 int *fgcolor) 1048 { 1049 QString tmpstr; 1050 int pos; 1051 int m2 = 0, m3 = 0; 1052 1053 // filter SH = Brushstyle Background 1054 pos = it.indexOf("SH"); 1055 if (pos > -1) { 1056 tmpstr = it; 1057 if (pos > 0) tmpstr.remove(0, pos); 1058 pos = sscanf(tmpstr.toLatin1(), "SH%d", 1059 style); 1060 1061 printf("style: %d(%d) ", 1062 *style, pos); 1063 } 1064 1065 1066 // filter FG = FGCOLOR 1067 pos = it.indexOf("FG"); 1068 if (pos > -1) { 1069 tmpstr = it; 1070 if (pos > 0) tmpstr.remove(0, pos); 1071 pos = sscanf(tmpstr.toLatin1(), "FG%d", 1072 fgcolor); 1073 printf("fg: %d(%d) ", 1074 *fgcolor, pos); 1075 m2 = 1; 1076 } 1077 1078 1079 // filter BG = BGCOLOR 1080 pos = it.indexOf("BG"); 1081 if (pos > -1) { 1082 tmpstr = it; 1083 if (pos > 0) tmpstr.remove(0, pos); 1084 pos = sscanf(tmpstr.toLatin1(), "BG%d", 1085 bgcolor); 1086 printf("bgcolor: %d(%d) ", 1087 *bgcolor, pos); 1088 m3 = 1; 1089 } 1090 1091 1092 printf("\n"); 1093 1094 1095 // correct the bgcolor to the fgcolor if the background is plain 1096 if ((*style == 8) && (m2 == 1) && (m3 == 0)) { 1097 *bgcolor = *fgcolor; 1098 } 1099 1100 1101 // Translate brushstyle to kspread brushstyle 1102 if (*style != 0) { 1103 if (*style == 1) *style = 0; 1104 else if (*style == 2) *style = 7; 1105 else if (*style == 3) *style = 0; 1106 else if (*style == 4) *style = 4; 1107 else if (*style == 5) *style = 3; 1108 else if (*style == 6) *style = 2; 1109 else if (*style == 7) *style = 0; 1110 else if (*style == 8) *style = 0; 1111 else if (*style == 9) *style = 10; 1112 else if (*style == 10) *style = 9; 1113 else if (*style == 11) *style = 11; 1114 else if (*style == 12) *style = 12; 1115 else if (*style == 13) *style = 13; 1116 else if (*style == 14) *style = 14; 1117 else if (*style == 15) *style = 0; 1118 else if (*style == 16) *style = 0; 1119 else if (*style == 17) *style = 0; 1120 else if (*style == 18) *style = 0; 1121 else if (*style == 19) *style = 0; 1122 } 1123 } 1124 1125 1126 1127 /****************************************************************************** 1128 * function: filterSHFGBG * 1129 ******************************************************************************/ 1130 void 1131 APPLIXSPREADImport::transPenFormat(const QString &it, int *PenWidth, int *PenStyle) 1132 { 1133 1134 if (it[1] == '1') { 1135 *PenWidth = 1; 1136 *PenStyle = 1; 1137 } 1138 1139 else if (it[1] == '2') { 1140 *PenWidth = 2; 1141 *PenStyle = 1; 1142 } 1143 1144 else if (it[1] == '3') { 1145 *PenWidth = 3; 1146 *PenStyle = 1; 1147 } 1148 1149 else if (it[1] == '4') { 1150 *PenWidth = 1; 1151 *PenStyle = 3; 1152 } 1153 1154 else if (it[1] == '5') { 1155 *PenWidth = 5; 1156 *PenStyle = 1; 1157 } 1158 1159 printf("frame (w:%d - s:%d) \n", *PenWidth, *PenStyle); 1160 } 1161 1162 1163 1164 1165 /****************************************************************************** 1166 * function: readHeader * 1167 ******************************************************************************/ 1168 int 1169 APPLIXSPREADImport::readHeader(QTextStream &stream) 1170 { 1171 QString mystr; 1172 int vers[3] = { 0, 0, 0 }; 1173 int rueck; 1174 1175 1176 // Read Headline 1177 mystr = nextLine(stream); 1178 rueck = sscanf(mystr.toLatin1(), 1179 "*BEGIN SPREADSHEETS VERSION=%d/%d ENCODING=%dBIT", 1180 &vers[0], &vers[1], &vers[2]); 1181 printf("Versions info: %d %d %d\n", vers[0], vers[1], vers[2]); 1182 1183 // Check the headline 1184 if (rueck <= 0) { 1185 printf("Header not correct - May be it is not an applixspreadsheet file\n"); 1186 printf("Headerline: <%s>\n", mystr.toLatin1().data()); 1187 1188 QMessageBox::critical(0L, "Applix spreadsheet header problem", 1189 QString("The Applix Spreadsheet header is not correct. " 1190 "May be it is not an applix spreadsheet file! <BR>" 1191 "This is the header line I did read:<BR><B>%1</B>").arg(mystr), 1192 "Okay"); 1193 1194 1195 return false; 1196 } else { 1197 return true; 1198 } 1199 } 1200 1201 1202 /****************************************************************************** 1203 * function: translateColumnNumber * 1204 ******************************************************************************/ 1205 int 1206 APPLIXSPREADImport::translateColumnNumber(const QString& colstr) 1207 { 1208 int icol = 0; 1209 const int len = colstr.length(); 1210 int p = len - 1; 1211 int x = 1; 1212 1213 //kDebug() << "len=" << len; 1214 while (p >= 0) { 1215 //kDebug() << "x=" << x << "p=" << p << "char=" << colstr[p].toLatin1(); 1216 const char c = colstr[p].toLatin1(); 1217 // Upper chars 1218 if ((c >= 'A') && (c <= 'Z')) { 1219 //kDebug() << " UPPER"; 1220 icol += ((int)pow((double)x, 26) * (c - 'A' + 1)); 1221 ++x; 1222 } 1223 // lower chars 1224 else if ((c >= 'a') && (c <= 'z')) { 1225 //kDebug() << " lower"; 1226 icol += ((int)pow((double)x, 26) * (c - 'a' + 1)); 1227 ++x; 1228 } 1229 p--; 1230 } 1231 1232 kDebug() << colstr << "->" << icol; 1233 return icol; 1234 } 1235 1236 // Converts =SUM(F1,4) into =SUM(F1;4) -- well, plus possible nesting 1237 QString APPLIXSPREADImport::convertFormula(const QString& input) const 1238 { 1239 // Let me be stupid for now 1240 QString ret = input; 1241 ret.replace(',', ';'); 1242 return ret; 1243 } 1244 1245 #include "applixspreadimport.moc"