00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include <qvaluelist.h>
00024
00025
#include <kdebug.h>
00026
#include "kformuladefs.h"
00027
#include "kformulacompatibility.h"
00028
00029 KFORMULA_NAMESPACE_BEGIN
00030
00031
const int SYMBOL_ABOVE = 20000;
00032
const int UNUSED_OFFSET = 1000;
00033
00034
typedef int BoxType;
00035
00036
00037
00038
00039
const BoxType OF_DIVIDE =
'\\' + UNUSED_OFFSET;
00040
const BoxType OF_POWER =
'^' + UNUSED_OFFSET;
00041
const BoxType OF_SQRT =
'@' + UNUSED_OFFSET;
00042
00043
00044
const BoxType OF_SUB =
'_' + UNUSED_OFFSET;
00045
const BoxType OF_LSUP =
'6' + UNUSED_OFFSET;
00046
const BoxType OF_LSUB =
'%' + UNUSED_OFFSET;
00047
00048
00049
00050
00051
00052
00053
00054
const BoxType OF_MATRIX =
'm' + UNUSED_OFFSET;
00055
const BoxType OF_SEPARATOR =
'&' + UNUSED_OFFSET;
00056
const BoxType OF_ABOVE =
')' + UNUSED_OFFSET;
00057
const BoxType OF_BELOW =
']' + UNUSED_OFFSET;
00058
const BoxType OF_SYMBOL =
's' + UNUSED_OFFSET;
00059
00060
00061
00062
const int INTEGRAL = SYMBOL_ABOVE + 0;
00063
const int SUM = SYMBOL_ABOVE + 1;
00064
const int PRODUCT = SYMBOL_ABOVE + 2;
00065
const int ARROW = SYMBOL_ABOVE + 3;
00066
00067
00068
00069 Compatibility::Compatibility()
00070 {
00071 }
00072
00073
00074 QDomDocument Compatibility::buildDOM(
QString text)
00075 {
00076
QDomDocument doc(
"KFORMULA");
00077 pos = 0;
00078 formulaString = text;
00079
QDomElement formula = readSequence(doc);
00080 formula.setTagName(
"FORMULA");
00081 doc.appendChild(formula);
00082
return doc;
00083 }
00084
00085
00086
void Compatibility::appendNextSequence(
QDomDocument doc,
QDomElement element)
00087 {
00088
if (hasNext() && nextToken() ==
'{') {
00089 element.appendChild(readSequence(doc));
00090 }
00091
else {
00092 pushback();
00093 element.appendChild(doc.createElement(
"SEQUENCE"));
00094 }
00095 }
00096
00097
00098
QDomElement Compatibility::getLastSequence(
QDomDocument doc,
QDomElement sequence)
00099 {
00100
if (sequence.lastChild().nodeName() ==
"SEQUENCE") {
00101
QDomNode child = sequence.removeChild(sequence.lastChild());
00102
return child.toElement();
00103 }
00104
else {
00105
QDomElement newSeq = doc.createElement(
"SEQUENCE");
00106
if (!sequence.lastChild().isNull()) {
00107
QDomNode child = sequence.removeChild(sequence.lastChild());
00108 newSeq.appendChild(child);
00109 }
00110
return newSeq;
00111 }
00112 }
00113
00114
00115
QDomElement Compatibility::findIndexNode(
QDomDocument doc,
QDomElement sequence)
00116 {
00117
QDomElement element;
00118
if (sequence.lastChild().nodeName() ==
"INDEX") {
00119 element = sequence.lastChild().toElement();
00120 }
00121
else {
00122 element = doc.createElement(
"INDEX");
00123
QDomElement con = doc.createElement(
"CONTENT");
00124 element.appendChild(con);
00125 con.appendChild(getLastSequence(doc, sequence));
00126 sequence.appendChild(element);
00127 }
00128
return element;
00129 }
00130
00131
00132
void Compatibility::appendToSequence(
QDomElement sequence,
QDomElement element,
int leftIndexSeen)
00133 {
00134
if (leftIndexSeen > 0) {
00135
if (sequence.lastChild().nodeName() ==
"INDEX") {
00136
QDomElement index = sequence.lastChild().toElement();
00137
if ((index.firstChild().nodeName() ==
"CONTENT") &&
00138 (index.firstChild().firstChild().nodeName() ==
"SEQUENCE")) {
00139
QDomElement seq = index.firstChild().firstChild().toElement();
00140
if (element.nodeName() ==
"SEQUENCE") {
00141 index.firstChild().replaceChild(element, seq);
00142 }
00143
else {
00144 seq.appendChild(element);
00145 }
00146
return;
00147 }
00148 }
00149 }
00150 sequence.appendChild(element);
00151 }
00152
00153
00154
QDomElement Compatibility::readMatrix(
QDomDocument doc)
00155 {
00156
QDomElement element = doc.createElement(
"MATRIX");
00157
00158 uint cols = nextToken();
00159 nextToken();
00160 uint rows = nextToken();
00161
00162 element.setAttribute(
"ROWS", rows);
00163 element.setAttribute(
"COLUMNS", cols);
00164
00165
if ((nextToken() ==
'}') && (nextToken() == OF_MATRIX) && (nextToken() ==
'{')) {
00166
QValueList<QDomElement> matrix;
00167
for (uint c = 0; c < cols; c++) {
00168
for (uint r = 0; r < rows; r++) {
00169
if (hasNext() && (nextToken() ==
'{')) {
00170
QDomElement tmp = readSequence(doc);
00171 matrix.append(tmp);
00172 }
00173
if (hasNext() && (nextToken() != OF_SEPARATOR)) {
00174 pushback();
00175 }
00176 }
00177 }
00178
if (hasNext() && (nextToken() !=
'}')) {
00179 pushback();
00180 }
00181
00182
if (matrix.count() == rows*cols) {
00183
for (uint r = 0; r < rows; r++) {
00184
for (uint c = 0; c < cols; c++) {
00185 element.appendChild(matrix[c*rows+r]);
00186 }
00187 }
00188 }
00189 }
00190
else {
00191 pushback();
00192 }
00193
00194
return element;
00195 }
00196
00197
00198
QDomElement Compatibility::readSequence(
QDomDocument doc)
00199 {
00200
00201
if ((tokenLeft() > 6) && (lookAhead(1) == OF_SEPARATOR)) {
00202
return readMatrix(doc);
00203 }
00204
00205
int leftIndexSeen = 0;
00206
QDomElement sequence = doc.createElement(
"SEQUENCE");
00207
00208
while (hasNext()) {
00209 ushort ch = nextToken();
00210
00211
00212
00213
00214
if (leftIndexSeen > 0) leftIndexSeen--;
00215
00216
switch (ch) {
00217
case '{':
00218 appendToSequence(sequence, readSequence(doc), leftIndexSeen);
00219
break;
00220
case '}':
00221
return sequence;
00222
case '(':
00223
case '[':
00224
case '|': {
00225
00226
if (!sequence.lastChild().isNull()) {
00227 sequence.removeChild(sequence.lastChild());
00228 }
00229
00230
QDomElement element = doc.createElement(
"BRACKET");
00231 appendToSequence(sequence, element, leftIndexSeen);
00232 element.setAttribute(
"LEFT", ch);
00233 element.setAttribute(
"RIGHT", (ch==
'(') ?
')' : ((ch==
'[') ?
']' :
'|'));
00234
00235
QDomElement con = doc.createElement(
"CONTENT");
00236 element.appendChild(con);
00237 appendNextSequence(doc, con);
00238
break;
00239 }
00240
case OF_DIVIDE: {
00241
QDomElement element = doc.createElement(
"FRACTION");
00242
00243
QDomElement num = doc.createElement(
"NUMERATOR");
00244 element.appendChild(num);
00245 num.appendChild(getLastSequence(doc, sequence));
00246
00247
QDomElement den = doc.createElement(
"DENOMINATOR");
00248 element.appendChild(den);
00249 appendNextSequence(doc, den);
00250
00251 appendToSequence(sequence, element, leftIndexSeen);
00252
break;
00253 }
00254
case OF_SQRT: {
00255
QDomElement element = doc.createElement(
"ROOT");
00256
QDomElement con = doc.createElement(
"CONTENT");
00257 element.appendChild(con);
00258 appendNextSequence(doc, con);
00259
00260
QDomElement ind = doc.createElement(
"INDEX");
00261 element.appendChild(ind);
00262 ind.appendChild(getLastSequence(doc, sequence));
00263
00264 appendToSequence(sequence, element, leftIndexSeen);
00265
break;
00266 }
00267
case OF_POWER: {
00268
QDomElement element = findIndexNode(doc, sequence);
00269
QDomElement upperRight = doc.createElement(
"UPPERRIGHT");
00270 element.appendChild(upperRight);
00271 appendNextSequence(doc, upperRight);
00272
break;
00273 }
00274
case OF_SUB: {
00275
QDomElement element = findIndexNode(doc, sequence);
00276
QDomElement lowerRight = doc.createElement(
"LOWERRIGHT");
00277 element.appendChild(lowerRight);
00278 appendNextSequence(doc, lowerRight);
00279
break;
00280 }
00281
case OF_LSUP: {
00282
QDomElement upperLeft = doc.createElement(
"UPPERLEFT");
00283 upperLeft.appendChild(getLastSequence(doc, sequence));
00284
QDomElement element;
00285
if (sequence.lastChild().nodeName() ==
"INDEX") {
00286 element = sequence.lastChild().toElement();
00287 }
00288
else {
00289 element = doc.createElement(
"INDEX");
00290
QDomElement con = doc.createElement(
"CONTENT");
00291 element.appendChild(con);
00292
QDomElement seq = doc.createElement(
"SEQUENCE");
00293 con.appendChild(seq);
00294 appendToSequence(sequence, element, leftIndexSeen);
00295 }
00296 element.appendChild(upperLeft);
00297 leftIndexSeen = 2;
00298
break;
00299 }
00300
case OF_LSUB: {
00301
QDomElement lowerLeft = doc.createElement(
"LOWERLEFT");
00302 lowerLeft.appendChild(getLastSequence(doc, sequence));
00303
QDomElement element;
00304
if (sequence.lastChild().nodeName() ==
"INDEX") {
00305 element = sequence.lastChild().toElement();
00306 }
00307
else {
00308 element = doc.createElement(
"INDEX");
00309
QDomElement con = doc.createElement(
"CONTENT");
00310 element.appendChild(con);
00311
QDomElement seq = doc.createElement(
"SEQUENCE");
00312 con.appendChild(seq);
00313 appendToSequence(sequence, element, leftIndexSeen);
00314 }
00315 element.appendChild(lowerLeft);
00316 leftIndexSeen = 2;
00317
break;
00318 }
00319
case OF_ABOVE: {
00320
if (sequence.lastChild().nodeName() ==
"SEQUENCE") {
00321
QDomElement seq = sequence.lastChild().toElement();
00322
if ((seq.childNodes().count() == 1) &&
00323 ((seq.lastChild().nodeName() ==
"SYMBOL") ||
00324 (seq.lastChild().nodeName() ==
"INDEX"))) {
00325 sequence.removeChild(seq);
00326
00327
QDomElement element = seq.lastChild().toElement();
00328
QDomElement upper = (element.nodeName() ==
"SYMBOL") ?
00329 doc.createElement(
"UPPER") :
00330 doc.createElement("UPPERMIDDLE");
00331 element.appendChild(upper);
00332 appendNextSequence(doc, upper);
00333 appendToSequence(sequence, element, leftIndexSeen);
00334
break;
00335 }
00336 }
00337
QDomElement element = findIndexNode(doc, sequence);
00338
QDomElement upper = doc.createElement(
"UPPERMIDDLE");
00339 element.appendChild(upper);
00340 appendNextSequence(doc, upper);
00341
break;
00342 }
00343
case OF_BELOW: {
00344
if (sequence.lastChild().nodeName() ==
"SEQUENCE") {
00345
QDomElement seq = sequence.lastChild().toElement();
00346
if ((seq.childNodes().count() == 1) &&
00347 ((seq.lastChild().nodeName() ==
"SYMBOL") ||
00348 (seq.lastChild().nodeName() ==
"INDEX"))) {
00349 sequence.removeChild(seq);
00350
00351
QDomElement element = seq.lastChild().toElement();
00352
QDomElement lower = (element.nodeName() ==
"SYMBOL") ?
00353 doc.createElement(
"LOWER") :
00354 doc.createElement("LOWERMIDDLE");
00355 element.appendChild(lower);
00356 appendNextSequence(doc, lower);
00357 appendToSequence(sequence, element, leftIndexSeen);
00358
break;
00359 }
00360 }
00361
QDomElement element = findIndexNode(doc, sequence);
00362
QDomElement lower = doc.createElement(
"LOWERMIDDLE");
00363 element.appendChild(lower);
00364 appendNextSequence(doc, lower);
00365
break;
00366 }
00367
case OF_SYMBOL:
00368 kdDebug() <<
"OF_SYMBOL" << endl;
00369
break;
00370
case INTEGRAL:
00371
case SUM:
00372
case PRODUCT: {
00373
QDomElement element = doc.createElement(
"SYMBOL");
00374 element.setAttribute(
"TYPE",
00375 (ch==INTEGRAL) ? Integral :
00376 ((ch==SUM) ? Sum : Product));
00377
00378
QDomElement con = doc.createElement(
"CONTENT");
00379 element.appendChild(con);
00380 con.appendChild(readSequence(doc));
00381 pushback();
00382 appendToSequence(sequence, element, leftIndexSeen);
00383
break;
00384 }
00385
case ARROW: {
00386
QDomElement element = doc.createElement(
"TEXT");
00387 element.setAttribute(
"CHAR",
QString(
QChar(static_cast<char>(174))));
00388 element.setAttribute(
"SYMBOL",
"1");
00389 appendToSequence(sequence, element, leftIndexSeen);
00390
break;
00391 }
00392
default: {
00393
QDomElement element = doc.createElement(
"TEXT");
00394 element.setAttribute(
"CHAR",
QString(formulaString[pos-1]));
00395 appendToSequence(sequence, element, leftIndexSeen);
00396 }
00397 }
00398 }
00399
return sequence;
00400 }
00401
00402 KFORMULA_NAMESPACE_END