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