Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "formula.h"
21 :
22 : #include "mzstring.h"
23 : #include "nodes.h"
24 : #include "mapping.h"
25 : #include "hwpeq.h"
26 : #include <iostream>
27 : #include <list>
28 :
29 : extern std::list<Node*> nodelist;
30 :
31 : #ifndef DEBUG
32 :
33 : #include "hcode.h"
34 :
35 : #define ascii(x) OUString::createFromAscii(x)
36 : #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(0)
37 : #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(0)
38 : #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(ascii(x)); } while(0)
39 : #define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x)); } while(0)
40 : #define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(0)
41 : #define padd(x,y,z) pList->addAttribute(x,y,z)
42 : #else
43 : static int indent = 0;
44 : #define inds indent++; for(int i = 0 ; i < indent ; i++) fprintf(stderr," ")
45 : #define inde for(int i = 0 ; i < indent ; i++) fprintf(stderr," "); indent--
46 : #define indo indent--;
47 : #endif
48 :
49 : extern Node *mainParse(const char *);
50 :
51 :
52 0 : void Formula::makeMathML(Node *res)
53 : {
54 0 : Node *tmp = res;
55 0 : if( !tmp ) return;
56 : #ifdef DEBUG
57 : inds;
58 : fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
59 : #else
60 0 : padd(ascii("xmlns:math"), ascii("CDATA"), ascii("http://www.w3.org/1998/Math/MathML"));
61 0 : rstartEl(ascii("math:math"), rList);
62 0 : pList->clear();
63 0 : rstartEl(ascii("math:semantics"), rList);
64 : #endif
65 0 : if( tmp->child )
66 0 : makeLines( tmp->child );
67 :
68 : #ifdef DEBUG
69 : inds;
70 : fprintf(stderr,"<math:semantics/>\n");
71 : indo;
72 : inde;
73 : fprintf(stderr,"</math:math>\n");
74 : #else
75 0 : rendEl(ascii("math:semantics"));
76 0 : rendEl(ascii("math:math"));
77 : #endif
78 : }
79 :
80 0 : void Formula::makeLines(Node *res)
81 : {
82 0 : Node *tmp = res;
83 0 : if( !tmp ) return;
84 :
85 0 : if( tmp->child ){
86 0 : if( tmp->child->id == ID_LINES )
87 0 : makeLines( tmp->child );
88 : else
89 0 : makeLine( tmp->child );
90 : }
91 0 : if( tmp->next )
92 0 : makeLine( tmp->next );
93 : }
94 :
95 0 : void Formula::makeLine(Node *res)
96 : {
97 0 : if( !res ) return;
98 : #ifdef DEBUG
99 : inds; fprintf(stderr,"<math:mrow>\n");
100 : #else
101 0 : rstartEl(ascii("math:mrow"), rList);
102 : #endif
103 0 : if( res->child )
104 0 : makeExprList( res->child );
105 : #ifdef DEBUG
106 : inde; fprintf(stderr,"</math:mrow>\n");
107 : #else
108 0 : rendEl(ascii("math:mrow"));
109 : #endif
110 : }
111 :
112 0 : void Formula::makeExprList(Node *res)
113 : {
114 0 : if( !res ) return;
115 0 : Node *tmp = res->child;
116 0 : if( !tmp ) return ;
117 :
118 0 : if( tmp->id == ID_EXPRLIST ){
119 0 : Node *next = tmp->next;
120 0 : makeExprList( tmp ) ;
121 0 : if( next )
122 0 : makeExpr( next );
123 : }
124 : else
125 0 : makeExpr( tmp );
126 : }
127 :
128 0 : void Formula::makeExpr(Node *res)
129 : {
130 0 : if( !res ) return;
131 0 : Node *tmp = res->child;
132 0 : if( !tmp ) return;
133 0 : switch( tmp->id ) {
134 : case ID_PRIMARYEXPR:
135 0 : if( tmp->next ){
136 : #ifdef DEBUG
137 : inds;
138 : fprintf(stderr,"<math:mrow>\n");
139 : #else
140 0 : rstartEl(ascii("math:mrow"), rList);
141 : #endif
142 : }
143 :
144 0 : makePrimary(tmp);
145 :
146 0 : if( tmp->next ){
147 : #ifdef DEBUG
148 : inde; fprintf(stderr,"</math:mrow>\n");
149 : #else
150 0 : rendEl(ascii("math:mrow"));
151 : #endif
152 : }
153 0 : break;
154 : case ID_SUBEXPR:
155 : case ID_SUPEXPR:
156 : case ID_SUBSUPEXPR:
157 0 : makeSubSup(tmp);
158 0 : break;
159 : case ID_FRACTIONEXPR:
160 : case ID_OVER:
161 0 : makeFraction(tmp);
162 0 : break;
163 : case ID_DECORATIONEXPR:
164 0 : makeDecoration(tmp);
165 0 : break;
166 : case ID_SQRTEXPR:
167 : case ID_ROOTEXPR:
168 0 : makeRoot(tmp);
169 0 : break;
170 : case ID_ARROWEXPR:
171 0 : makeArrow(tmp);
172 0 : break;
173 : case ID_ACCENTEXPR:
174 0 : makeAccent(tmp);
175 0 : break;
176 : case ID_PARENTH:
177 : case ID_ABS:
178 0 : makeParenth(tmp);
179 0 : break;
180 : case ID_FENCE:
181 0 : makeFence(tmp);
182 0 : break;
183 : case ID_BLOCK:
184 0 : makeBlock(tmp);
185 : case ID_BEGIN:
186 0 : makeBegin(tmp);
187 : case ID_END:
188 0 : makeEnd(tmp);
189 0 : break;
190 : }
191 : }
192 :
193 0 : void Formula::makeIdentifier(Node *res)
194 : {
195 0 : Node *tmp = res;
196 0 : if( !tmp ) return;
197 0 : if( !tmp->value ) return;
198 0 : switch( tmp->id ){
199 : case ID_CHARACTER :
200 : #ifdef DEBUG
201 : inds;
202 : fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value);
203 : indo;
204 : #else
205 0 : rstartEl(ascii("math:mi"), rList);
206 0 : rchars(tmp->value);
207 0 : rendEl(ascii("math:mi"));
208 : #endif
209 0 : break;
210 : case ID_STRING :
211 : {
212 : #ifdef DEBUG
213 : #else
214 0 : rstartEl(ascii("math:mi"), rList);
215 0 : reucstr(tmp->value, strlen(tmp->value));
216 0 : rendEl(ascii("math:mi"));
217 : #endif
218 : }
219 0 : break;
220 : case ID_IDENTIFIER :
221 : #ifdef DEBUG
222 : inds;
223 : fprintf(stderr,"<math:mi>%s</math:mi>\n",
224 : getMathMLEntity(tmp->value).c_str());
225 : indo;
226 : #else
227 0 : rstartEl(ascii("math:mi"), rList);
228 0 : runistr(getMathMLEntity(tmp->value).c_str());
229 0 : rendEl(ascii("math:mi"));
230 : #endif
231 0 : break;
232 : case ID_NUMBER :
233 : #ifdef DEBUG
234 : inds;
235 : fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value);
236 : indo;
237 : #else
238 0 : rstartEl(ascii("math:mn"), rList);
239 0 : rchars(tmp->value);
240 0 : rendEl(ascii("math:mn"));
241 : #endif
242 0 : break;
243 : case ID_OPERATOR :
244 : case ID_DELIMETER :
245 : {
246 : #ifdef DEBUG
247 : inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value); indo;
248 : #else
249 0 : rstartEl(ascii("math:mo"), rList);
250 0 : runistr(getMathMLEntity(tmp->value).c_str());
251 0 : rendEl(ascii("math:mo"));
252 : #endif
253 0 : break;
254 : }
255 : }
256 : }
257 0 : void Formula::makePrimary(Node *res)
258 : {
259 0 : Node *tmp = res;
260 0 : if( !tmp ) return ;
261 0 : if( tmp->child ){
262 0 : if( tmp->child->id == ID_PRIMARYEXPR ){
263 0 : makePrimary(tmp->child);
264 : }
265 : else{
266 0 : makeIdentifier(tmp->child);
267 : }
268 : }
269 0 : if( tmp->next ){
270 0 : makeIdentifier(tmp->next);
271 : }
272 : }
273 :
274 0 : void Formula::makeSubSup(Node *res)
275 : {
276 0 : Node *tmp = res;
277 0 : if( !tmp ) return;
278 :
279 : #ifdef DEBUG
280 : inds;
281 : if( res->id == ID_SUBEXPR )
282 : fprintf(stderr,"<math:msub>\n");
283 : else if( res->id == ID_SUPEXPR )
284 : fprintf(stderr,"<math:msup>\n");
285 : else
286 : fprintf(stderr,"<math:msubsup>\n");
287 : #else
288 0 : if( res->id == ID_SUBEXPR )
289 0 : rstartEl(ascii("math:msub"), rList);
290 0 : else if( res->id == ID_SUPEXPR )
291 0 : rstartEl(ascii("math:msup"), rList);
292 : else
293 0 : rstartEl(ascii("math:msubsup"), rList);
294 : #endif
295 :
296 0 : tmp = tmp->child;
297 0 : if( res->id == ID_SUBSUPEXPR ) {
298 0 : makeExpr(tmp);
299 0 : makeBlock(tmp->next);
300 0 : makeBlock(tmp->next->next);
301 : }
302 : else{
303 0 : makeExpr(tmp);
304 0 : makeExpr(tmp->next);
305 : }
306 :
307 : #ifdef DEBUG
308 : inde;
309 : if( res->id == ID_SUBEXPR )
310 : fprintf(stderr,"</math:msub>\n");
311 : else if( res->id == ID_SUPEXPR )
312 : fprintf(stderr,"</math:msup>\n");
313 : else
314 : fprintf(stderr,"</math:msubsup>\n");
315 : #else
316 0 : if( res->id == ID_SUBEXPR )
317 0 : rendEl(ascii("math:msub"));
318 0 : else if( res->id == ID_SUPEXPR )
319 0 : rendEl(ascii("math:msup"));
320 : else
321 0 : rendEl(ascii("math:msubsup"));
322 : #endif
323 : }
324 :
325 0 : void Formula::makeFraction(Node *res)
326 : {
327 0 : Node *tmp = res;
328 0 : if( !tmp ) return;
329 :
330 : #ifdef DEBUG
331 : inds;
332 : fprintf(stderr,"<math:mfrac>\n");
333 : #else
334 0 : rstartEl(ascii("math:mfrac"), rList);
335 : #endif
336 :
337 0 : tmp = tmp->child;
338 : #ifdef DEBUG
339 : inds;
340 : fprintf(stderr,"<math:mrow>\n");
341 : #else
342 0 : rstartEl(ascii("math:mrow"), rList);
343 : #endif
344 :
345 0 : if( res->id == ID_FRACTIONEXPR )
346 0 : makeBlock(tmp);
347 : else
348 0 : makeExprList(tmp);
349 :
350 : #ifdef DEBUG
351 : inde;
352 : fprintf(stderr,"</math:mrow>\n");
353 : inds;
354 : fprintf(stderr,"<math:mrow>\n");
355 : #else
356 0 : rendEl(ascii("math:mrow"));
357 0 : rstartEl(ascii("math:mrow"), rList);
358 : #endif
359 :
360 0 : if( res->id == ID_FRACTIONEXPR )
361 0 : makeBlock(tmp->next);
362 : else
363 0 : makeExprList(tmp->next);
364 :
365 : #ifdef DEBUG
366 : inde;
367 : fprintf(stderr,"</math:mrow>\n");
368 : inde;
369 : fprintf(stderr,"</math:mfrac>\n");
370 : #else
371 0 : rendEl(ascii("math:mrow"));
372 0 : rendEl(ascii("math:mfrac"));
373 : #endif
374 : }
375 :
376 0 : void Formula::makeDecoration(Node *res)
377 : {
378 0 : int isover = 1;
379 0 : Node *tmp = res->child;
380 0 : if( !tmp ) return;
381 0 : if( !strncmp(tmp->value,"under", 5) )
382 0 : isover = 0;
383 : #ifdef DEBUG
384 : inds;
385 : if( isover )
386 : fprintf(stderr,"<math:mover>\n");
387 : else
388 : fprintf(stderr,"<math:munder>\n");
389 : #else
390 : /* accent´Â ¾ðÁ¦ trueÀÌ°í, ¾ðÁ¦, falseÀÎÁö ¸ð¸£°Ú´Ù. */
391 0 : if( isover ){
392 0 : padd(ascii("accent"),ascii("CDATA"),ascii("true"));
393 0 : rstartEl(ascii("math:mover"), rList);
394 : }
395 : else{
396 0 : padd(ascii("accentunder"),ascii("CDATA"),ascii("true"));
397 0 : rstartEl(ascii("math:munder"), rList);
398 : }
399 0 : pList->clear();
400 : #endif
401 :
402 0 : makeBlock(tmp->next);
403 :
404 : #ifdef DEBUG
405 : inds;
406 : fprintf(stderr,"<math:mo>%s</math:mo>\n",
407 : getMathMLEntity(tmp->value).c_str());
408 : indo;
409 : #else
410 0 : rstartEl(ascii("math:mo"), rList);
411 0 : runistr(getMathMLEntity(tmp->value).c_str());
412 0 : rendEl(ascii("math:mo"));
413 : #endif
414 :
415 : #ifdef DEBUG
416 : inde;
417 : if( isover )
418 : fprintf(stderr,"</math:mover>\n");
419 : else
420 : fprintf(stderr,"</math:munder>\n");
421 : #else
422 0 : if( isover )
423 0 : rendEl(ascii("math:mover"));
424 : else
425 0 : rendEl(ascii("math:munder"));
426 : #endif
427 : }
428 :
429 0 : void Formula::makeRoot(Node *res)
430 : {
431 0 : Node *tmp = res;
432 0 : if( !tmp ) return;
433 : #ifdef DEBUG
434 : inds;
435 : if( tmp->id == ID_SQRTEXPR )
436 : fprintf(stderr,"<math:msqrt>\n");
437 : else
438 : fprintf(stderr,"<math:mroot>\n");
439 : #else
440 0 : if( tmp->id == ID_SQRTEXPR )
441 0 : rstartEl(ascii("math:msqrt"), rList);
442 : else
443 0 : rstartEl(ascii("math:mroot"), rList);
444 : #endif
445 :
446 0 : if( tmp->id == ID_SQRTEXPR ){
447 0 : makeBlock(tmp->child);
448 : }
449 : else{
450 0 : makeBracket(tmp->child);
451 0 : makeBlock(tmp->child->next);
452 : }
453 :
454 : #ifdef DEBUG
455 : inde;
456 : if( tmp->id == ID_SQRTEXPR )
457 : fprintf(stderr,"</math:msqrt>\n");
458 : else
459 : fprintf(stderr,"</math:mroot>\n");
460 : #else
461 0 : if( tmp->id == ID_SQRTEXPR )
462 0 : rendEl(ascii("math:msqrt"));
463 : else
464 0 : rendEl(ascii("math:mroot"));
465 : #endif
466 : }
467 : // DVO: add space to avoid warning
468 0 : void Formula::makeArrow(Node * /*res*/)
469 : {
470 0 : }
471 0 : void Formula::makeAccent(Node *res)
472 : {
473 0 : makeDecoration( res );
474 0 : }
475 0 : void Formula::makeParenth(Node *res)
476 : {
477 0 : Node *tmp = res;
478 0 : if( !tmp ) return;
479 : #ifdef DEBUG
480 : inds;
481 : fprintf(stderr,"<math:mrow>\n");
482 : inds;
483 : if( tmp->id == ID_PARENTH ){
484 : fprintf(stderr,"<math:mo>(</math:mo>\n");
485 : }
486 : else
487 : fprintf(stderr,"<math:mo>|</math:mo>\n");
488 : indo; inds;
489 : fprintf(stderr,"<math:mrow>\n");
490 : #else
491 0 : rstartEl(ascii("math:mrow"), rList);
492 0 : rstartEl(ascii("math:mo"), rList);
493 0 : if( tmp->id == ID_PARENTH )
494 0 : rchars("(");
495 : else
496 0 : rchars("|");
497 0 : rendEl(ascii("math:mo"));
498 0 : rstartEl(ascii("math:mrow"), rList);
499 : #endif
500 :
501 0 : if( tmp->child )
502 0 : makeExprList(tmp->child);
503 :
504 : #ifdef DEBUG
505 : inde;
506 : fprintf(stderr,"</math:mrow>\n");
507 : inds;
508 : if( tmp->id == ID_PARENTH )
509 : fprintf(stderr,"<math:mo>)</math:mo>\n");
510 : else
511 : fprintf(stderr,"<math:mo>|</math:mo>\n");
512 : indo;
513 : inde;
514 : fprintf(stderr,"</math:mrow>\n");
515 : #else
516 0 : rendEl(ascii("math:mrow"));
517 0 : rstartEl(ascii("math:mo"), rList);
518 0 : if( tmp->id == ID_PARENTH )
519 0 : rchars(")");
520 : else
521 0 : rchars("|");
522 0 : rendEl(ascii("math:mo"));
523 0 : rendEl(ascii("math:mrow"));
524 : #endif
525 : }
526 :
527 0 : void Formula::makeFence(Node *res)
528 : {
529 0 : Node *tmp = res->child;
530 : #ifdef DEBUG
531 : inds;
532 : fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
533 : getMathMLEntity(tmp->value).c_str(),
534 : getMathMLEntity(tmp->next->next->value).c_str());
535 : #else
536 0 : padd(ascii("open"), ascii("CDATA"),
537 0 : OUString(getMathMLEntity(tmp->value).c_str()) );
538 0 : padd(ascii("close"), ascii("CDATA"),
539 0 : OUString(getMathMLEntity(tmp->next->next->value).c_str()) );
540 0 : rstartEl(ascii("math:mfenced"), rList);
541 0 : pList->clear();
542 : #endif
543 :
544 0 : makeExprList(tmp->next);
545 :
546 : #ifdef DEBUG
547 : inde;
548 : fprintf(stderr,"</math:mfenced>\n");
549 : #else
550 0 : rendEl(ascii("math:mfenced"));
551 : #endif
552 0 : }
553 :
554 0 : void Formula::makeBracket(Node *res)
555 : {
556 0 : makeBlock(res);
557 0 : }
558 :
559 0 : void Formula::makeBlock(Node *res)
560 : {
561 : #ifdef DEBUG
562 : inds;
563 : fprintf(stderr,"<math:mrow>\n");
564 : #else
565 0 : rstartEl(ascii("math:mrow"), rList);
566 : #endif
567 :
568 0 : if( res->child )
569 0 : makeExprList(res->child);
570 :
571 : #ifdef DEBUG
572 : inde;
573 : fprintf(stderr,"</math:mrow>\n");
574 : #else
575 0 : rendEl(ascii("math:mrow"));
576 : #endif
577 0 : }
578 :
579 : // DVO: add space to avoid warning
580 0 : void Formula::makeBegin(Node * /*res*/)
581 : {
582 0 : }
583 :
584 : // DVO: add space to avoid warning
585 0 : void Formula::makeEnd(Node * /*res*/)
586 : {
587 0 : }
588 :
589 0 : int Formula::parse()
590 : {
591 0 : Node *res = 0L;
592 0 : if( !eq ) return 0;
593 0 : if( isHwpEQ ){
594 0 : MzString a;
595 : // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
596 0 : eq2latex(a,eq);
597 :
598 0 : int idx=a.find(sal::static_int_cast<char>(0xff));
599 0 : while(idx){
600 : //printf("idx = [%d]\n",idx);
601 0 : a.replace(idx,0x20);
602 0 : if((idx = a.find(sal::static_int_cast<char>(0xff),idx+1)) < 0)
603 0 : break;
604 : }
605 :
606 0 : char *buf = (char *)malloc(a.length()+1);
607 0 : bool bStart = false;
608 : int i, j;
609 0 : for( i = 0, j=0 ; i < a.length() ; i++){ // rtrim and ltrim 32 10 13
610 0 : if( bStart ){
611 0 : buf[j++] = a[i];
612 : }
613 : else{
614 0 : if( a[i] != 32 && a[i] != 10 && a[i] != 13){
615 0 : bStart = true;
616 0 : buf[j++] = a[i];
617 : }
618 : }
619 : }
620 0 : buf[j] = 0;
621 0 : for( i = j-1 ; i >= 0 ; i++ ){
622 0 : if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
623 0 : buf[i] = 0;
624 : }
625 : else
626 0 : break;
627 : }
628 : // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
629 0 : if( strlen(buf) > 0 )
630 0 : res = mainParse( a.c_str() );
631 : else
632 0 : res = 0L;
633 0 : free(buf);
634 : }
635 : else{
636 0 : res = mainParse( eq );
637 : }
638 :
639 0 : if( res ){
640 0 : makeMathML( res );
641 : }
642 : Node *tmpNode;
643 0 : int count = nodelist.size();
644 0 : for( int i = 0 ; i < count ; i++ ){
645 0 : tmpNode = nodelist.front();
646 0 : nodelist.pop_front();
647 0 : delete tmpNode;
648 : }
649 :
650 0 : return 0;
651 : }
652 :
653 0 : void Formula::trim()
654 : {
655 0 : int len = strlen(eq);
656 0 : char *buf = (char *)malloc(len+1);
657 0 : bool bStart = false;
658 : int i, j;
659 0 : for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
660 0 : if( bStart ){
661 0 : buf[j++] = eq[i];
662 : }
663 : else{
664 0 : if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
665 0 : bStart = true;
666 0 : buf[j++] = eq[i];
667 : }
668 : }
669 : }
670 0 : buf[j] = 0;
671 0 : for( i = j-1 ; i >= 0 ; i++ ){
672 0 : if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
673 0 : buf[i] = 0;
674 : }
675 : else
676 0 : break;
677 : }
678 0 : if( strlen(buf) > 0 )
679 0 : strcpy(eq, buf);
680 : else
681 0 : eq = 0L;
682 0 : free(buf);
683 3 : }
684 :
685 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|