Bump for 3.6-28
[LibreOffice.git] / hwpfilter / source / formula.cxx
blobc1903e27f83a24f8a20c78d59436ff86376c0701
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "formula.h"
31 #include "mzstring.h"
32 #include "nodes.h"
33 #include "mapping.h"
34 #include "hwpeq.h"
35 #include <iostream>
36 #include <list>
38 extern std::list<Node*> nodelist;
40 #ifndef DEBUG
42 #include "hcode.h"
44 #define ascii(x) OUString::createFromAscii(x)
45 #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(0)
46 #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(0)
47 #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(ascii(x)); } while(0)
48 #define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x)); } while(0)
49 #define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(0)
50 #define padd(x,y,z) pList->addAttribute(x,y,z)
51 #else
52 static int indent = 0;
53 #define inds indent++; for(int i = 0 ; i < indent ; i++) fprintf(stderr," ")
54 #define inde for(int i = 0 ; i < indent ; i++) fprintf(stderr," "); indent--
55 #define indo indent--;
56 #endif
58 extern Node *mainParse(const char *);
61 void Formula::makeMathML(Node *res)
63 Node *tmp = res;
64 if( !tmp ) return;
65 #ifdef DEBUG
66 inds;
67 fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
68 #else
69 padd(ascii("xmlns:math"), ascii("CDATA"), ascii("http://www.w3.org/1998/Math/MathML"));
70 rstartEl(ascii("math:math"), rList);
71 pList->clear();
72 rstartEl(ascii("math:semantics"), rList);
73 #endif
74 if( tmp->child )
75 makeLines( tmp->child );
77 #ifdef DEBUG
78 inds;
79 fprintf(stderr,"<math:semantics/>\n");
80 indo;
81 inde;
82 fprintf(stderr,"</math:math>\n");
83 #else
84 rendEl(ascii("math:semantics"));
85 rendEl(ascii("math:math"));
86 #endif
89 void Formula::makeLines(Node *res)
91 Node *tmp = res;
92 if( !tmp ) return;
94 if( tmp->child ){
95 if( tmp->child->id == ID_LINES )
96 makeLines( tmp->child );
97 else
98 makeLine( tmp->child );
100 if( tmp->next )
101 makeLine( tmp->next );
104 void Formula::makeLine(Node *res)
106 if( !res ) return;
107 #ifdef DEBUG
108 inds; fprintf(stderr,"<math:mrow>\n");
109 #else
110 rstartEl(ascii("math:mrow"), rList);
111 #endif
112 if( res->child )
113 makeExprList( res->child );
114 #ifdef DEBUG
115 inde; fprintf(stderr,"</math:mrow>\n");
116 #else
117 rendEl(ascii("math:mrow"));
118 #endif
121 void Formula::makeExprList(Node *res)
123 if( !res ) return;
124 Node *tmp = res->child;
125 if( !tmp ) return ;
127 if( tmp->id == ID_EXPRLIST ){
128 Node *next = tmp->next;
129 makeExprList( tmp ) ;
130 if( next )
131 makeExpr( next );
133 else
134 makeExpr( tmp );
137 void Formula::makeExpr(Node *res)
139 if( !res ) return;
140 Node *tmp = res->child;
141 if( !tmp ) return;
142 switch( tmp->id ) {
143 case ID_PRIMARYEXPR:
144 if( tmp->next ){
145 #ifdef DEBUG
146 inds;
147 fprintf(stderr,"<math:mrow>\n");
148 #else
149 rstartEl(ascii("math:mrow"), rList);
150 #endif
153 makePrimary(tmp);
155 if( tmp->next ){
156 #ifdef DEBUG
157 inde; fprintf(stderr,"</math:mrow>\n");
158 #else
159 rendEl(ascii("math:mrow"));
160 #endif
162 break;
163 case ID_SUBEXPR:
164 case ID_SUPEXPR:
165 case ID_SUBSUPEXPR:
166 makeSubSup(tmp);
167 break;
168 case ID_FRACTIONEXPR:
169 case ID_OVER:
170 makeFraction(tmp);
171 break;
172 case ID_DECORATIONEXPR:
173 makeDecoration(tmp);
174 break;
175 case ID_SQRTEXPR:
176 case ID_ROOTEXPR:
177 makeRoot(tmp);
178 break;
179 case ID_ARROWEXPR:
180 makeArrow(tmp);
181 break;
182 case ID_ACCENTEXPR:
183 makeAccent(tmp);
184 break;
185 case ID_PARENTH:
186 case ID_ABS:
187 makeParenth(tmp);
188 break;
189 case ID_FENCE:
190 makeFence(tmp);
191 break;
192 case ID_BLOCK:
193 makeBlock(tmp);
194 case ID_BEGIN:
195 makeBegin(tmp);
196 case ID_END:
197 makeEnd(tmp);
198 break;
202 void Formula::makeIdentifier(Node *res)
204 Node *tmp = res;
205 if( !tmp ) return;
206 if( !tmp->value ) return;
207 switch( tmp->id ){
208 case ID_CHARACTER :
209 #ifdef DEBUG
210 inds;
211 fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value);
212 indo;
213 #else
214 rstartEl(ascii("math:mi"), rList);
215 rchars(tmp->value);
216 rendEl(ascii("math:mi"));
217 #endif
218 break;
219 case ID_STRING :
221 #ifdef DEBUG
222 #else
223 rstartEl(ascii("math:mi"), rList);
224 reucstr(tmp->value, strlen(tmp->value));
225 rendEl(ascii("math:mi"));
226 #endif
228 break;
229 case ID_IDENTIFIER :
230 #ifdef DEBUG
231 inds;
232 fprintf(stderr,"<math:mi>%s</math:mi>\n",
233 getMathMLEntity(tmp->value).c_str());
234 indo;
235 #else
236 rstartEl(ascii("math:mi"), rList);
237 runistr(getMathMLEntity(tmp->value).c_str());
238 rendEl(ascii("math:mi"));
239 #endif
240 break;
241 case ID_NUMBER :
242 #ifdef DEBUG
243 inds;
244 fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value);
245 indo;
246 #else
247 rstartEl(ascii("math:mn"), rList);
248 rchars(tmp->value);
249 rendEl(ascii("math:mn"));
250 #endif
251 break;
252 case ID_OPERATOR :
253 case ID_DELIMETER :
255 #ifdef DEBUG
256 inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value); indo;
257 #else
258 rstartEl(ascii("math:mo"), rList);
259 runistr(getMathMLEntity(tmp->value).c_str());
260 rendEl(ascii("math:mo"));
261 #endif
262 break;
266 void Formula::makePrimary(Node *res)
268 Node *tmp = res;
269 if( !tmp ) return ;
270 if( tmp->child ){
271 if( tmp->child->id == ID_PRIMARYEXPR ){
272 makePrimary(tmp->child);
274 else{
275 makeIdentifier(tmp->child);
278 if( tmp->next ){
279 makeIdentifier(tmp->next);
283 void Formula::makeSubSup(Node *res)
285 Node *tmp = res;
286 if( !tmp ) return;
288 #ifdef DEBUG
289 inds;
290 if( res->id == ID_SUBEXPR )
291 fprintf(stderr,"<math:msub>\n");
292 else if( res->id == ID_SUPEXPR )
293 fprintf(stderr,"<math:msup>\n");
294 else
295 fprintf(stderr,"<math:msubsup>\n");
296 #else
297 if( res->id == ID_SUBEXPR )
298 rstartEl(ascii("math:msub"), rList);
299 else if( res->id == ID_SUPEXPR )
300 rstartEl(ascii("math:msup"), rList);
301 else
302 rstartEl(ascii("math:msubsup"), rList);
303 #endif
305 tmp = tmp->child;
306 if( res->id == ID_SUBSUPEXPR ) {
307 makeExpr(tmp);
308 makeBlock(tmp->next);
309 makeBlock(tmp->next->next);
311 else{
312 makeExpr(tmp);
313 makeExpr(tmp->next);
316 #ifdef DEBUG
317 inde;
318 if( res->id == ID_SUBEXPR )
319 fprintf(stderr,"</math:msub>\n");
320 else if( res->id == ID_SUPEXPR )
321 fprintf(stderr,"</math:msup>\n");
322 else
323 fprintf(stderr,"</math:msubsup>\n");
324 #else
325 if( res->id == ID_SUBEXPR )
326 rendEl(ascii("math:msub"));
327 else if( res->id == ID_SUPEXPR )
328 rendEl(ascii("math:msup"));
329 else
330 rendEl(ascii("math:msubsup"));
331 #endif
334 void Formula::makeFraction(Node *res)
336 Node *tmp = res;
337 if( !tmp ) return;
339 #ifdef DEBUG
340 inds;
341 fprintf(stderr,"<math:mfrac>\n");
342 #else
343 rstartEl(ascii("math:mfrac"), rList);
344 #endif
346 tmp = tmp->child;
347 #ifdef DEBUG
348 inds;
349 fprintf(stderr,"<math:mrow>\n");
350 #else
351 rstartEl(ascii("math:mrow"), rList);
352 #endif
354 if( res->id == ID_FRACTIONEXPR )
355 makeBlock(tmp);
356 else
357 makeExprList(tmp);
359 #ifdef DEBUG
360 inde;
361 fprintf(stderr,"</math:mrow>\n");
362 inds;
363 fprintf(stderr,"<math:mrow>\n");
364 #else
365 rendEl(ascii("math:mrow"));
366 rstartEl(ascii("math:mrow"), rList);
367 #endif
369 if( res->id == ID_FRACTIONEXPR )
370 makeBlock(tmp->next);
371 else
372 makeExprList(tmp->next);
374 #ifdef DEBUG
375 inde;
376 fprintf(stderr,"</math:mrow>\n");
377 inde;
378 fprintf(stderr,"</math:mfrac>\n");
379 #else
380 rendEl(ascii("math:mrow"));
381 rendEl(ascii("math:mfrac"));
382 #endif
385 void Formula::makeDecoration(Node *res)
387 int isover = 1;
388 Node *tmp = res->child;
389 if( !tmp ) return;
390 if( !strncmp(tmp->value,"under", 5) )
391 isover = 0;
392 #ifdef DEBUG
393 inds;
394 if( isover )
395 fprintf(stderr,"<math:mover>\n");
396 else
397 fprintf(stderr,"<math:munder>\n");
398 #else
399 /* accent´Â ¾ðÁ¦ trueÀÌ°í, ¾ðÁ¦, falseÀÎÁö ¸ð¸£°Ú´Ù. */
400 if( isover ){
401 padd(ascii("accent"),ascii("CDATA"),ascii("true"));
402 rstartEl(ascii("math:mover"), rList);
404 else{
405 padd(ascii("accentunder"),ascii("CDATA"),ascii("true"));
406 rstartEl(ascii("math:munder"), rList);
408 pList->clear();
409 #endif
411 makeBlock(tmp->next);
413 #ifdef DEBUG
414 inds;
415 fprintf(stderr,"<math:mo>%s</math:mo>\n",
416 getMathMLEntity(tmp->value).c_str());
417 indo;
418 #else
419 rstartEl(ascii("math:mo"), rList);
420 runistr(getMathMLEntity(tmp->value).c_str());
421 rendEl(ascii("math:mo"));
422 #endif
424 #ifdef DEBUG
425 inde;
426 if( isover )
427 fprintf(stderr,"</math:mover>\n");
428 else
429 fprintf(stderr,"</math:munder>\n");
430 #else
431 if( isover )
432 rendEl(ascii("math:mover"));
433 else
434 rendEl(ascii("math:munder"));
435 #endif
438 void Formula::makeRoot(Node *res)
440 Node *tmp = res;
441 if( !tmp ) return;
442 #ifdef DEBUG
443 inds;
444 if( tmp->id == ID_SQRTEXPR )
445 fprintf(stderr,"<math:msqrt>\n");
446 else
447 fprintf(stderr,"<math:mroot>\n");
448 #else
449 if( tmp->id == ID_SQRTEXPR )
450 rstartEl(ascii("math:msqrt"), rList);
451 else
452 rstartEl(ascii("math:mroot"), rList);
453 #endif
455 if( tmp->id == ID_SQRTEXPR ){
456 makeBlock(tmp->child);
458 else{
459 makeBracket(tmp->child);
460 makeBlock(tmp->child->next);
463 #ifdef DEBUG
464 inde;
465 if( tmp->id == ID_SQRTEXPR )
466 fprintf(stderr,"</math:msqrt>\n");
467 else
468 fprintf(stderr,"</math:mroot>\n");
469 #else
470 if( tmp->id == ID_SQRTEXPR )
471 rendEl(ascii("math:msqrt"));
472 else
473 rendEl(ascii("math:mroot"));
474 #endif
476 // DVO: add space to avoid warning
477 void Formula::makeArrow(Node * /*res*/)
480 void Formula::makeAccent(Node *res)
482 makeDecoration( res );
484 void Formula::makeParenth(Node *res)
486 Node *tmp = res;
487 if( !tmp ) return;
488 #ifdef DEBUG
489 inds;
490 fprintf(stderr,"<math:mrow>\n");
491 inds;
492 if( tmp->id == ID_PARENTH ){
493 fprintf(stderr,"<math:mo>(</math:mo>\n");
495 else
496 fprintf(stderr,"<math:mo>|</math:mo>\n");
497 indo; inds;
498 fprintf(stderr,"<math:mrow>\n");
499 #else
500 rstartEl(ascii("math:mrow"), rList);
501 rstartEl(ascii("math:mo"), rList);
502 if( tmp->id == ID_PARENTH )
503 rchars("(");
504 else
505 rchars("|");
506 rendEl(ascii("math:mo"));
507 rstartEl(ascii("math:mrow"), rList);
508 #endif
510 if( tmp->child )
511 makeExprList(tmp->child);
513 #ifdef DEBUG
514 inde;
515 fprintf(stderr,"</math:mrow>\n");
516 inds;
517 if( tmp->id == ID_PARENTH )
518 fprintf(stderr,"<math:mo>)</math:mo>\n");
519 else
520 fprintf(stderr,"<math:mo>|</math:mo>\n");
521 indo;
522 inde;
523 fprintf(stderr,"</math:mrow>\n");
524 #else
525 rendEl(ascii("math:mrow"));
526 rstartEl(ascii("math:mo"), rList);
527 if( tmp->id == ID_PARENTH )
528 rchars(")");
529 else
530 rchars("|");
531 rendEl(ascii("math:mo"));
532 rendEl(ascii("math:mrow"));
533 #endif
536 void Formula::makeFence(Node *res)
538 Node *tmp = res->child;
539 #ifdef DEBUG
540 inds;
541 fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
542 getMathMLEntity(tmp->value).c_str(),
543 getMathMLEntity(tmp->next->next->value).c_str());
544 #else
545 padd(ascii("open"), ascii("CDATA"),
546 OUString(getMathMLEntity(tmp->value).c_str()) );
547 padd(ascii("close"), ascii("CDATA"),
548 OUString(getMathMLEntity(tmp->next->next->value).c_str()) );
549 rstartEl(ascii("math:mfenced"), rList);
550 pList->clear();
551 #endif
553 makeExprList(tmp->next);
555 #ifdef DEBUG
556 inde;
557 fprintf(stderr,"</math:mfenced>\n");
558 #else
559 rendEl(ascii("math:mfenced"));
560 #endif
563 void Formula::makeBracket(Node *res)
565 makeBlock(res);
568 void Formula::makeBlock(Node *res)
570 #ifdef DEBUG
571 inds;
572 fprintf(stderr,"<math:mrow>\n");
573 #else
574 rstartEl(ascii("math:mrow"), rList);
575 #endif
577 if( res->child )
578 makeExprList(res->child);
580 #ifdef DEBUG
581 inde;
582 fprintf(stderr,"</math:mrow>\n");
583 #else
584 rendEl(ascii("math:mrow"));
585 #endif
588 // DVO: add space to avoid warning
589 void Formula::makeBegin(Node * /*res*/)
593 // DVO: add space to avoid warning
594 void Formula::makeEnd(Node * /*res*/)
598 int Formula::parse()
600 Node *res = 0L;
601 if( !eq ) return 0;
602 if( isHwpEQ ){
603 MzString a;
604 // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
605 eq2latex(a,eq);
607 int idx=a.find(sal::static_int_cast<char>(0xff));
608 while(idx){
609 //printf("idx = [%d]\n",idx);
610 a.replace(idx,0x20);
611 if((idx = a.find(sal::static_int_cast<char>(0xff),idx+1)) < 0)
612 break;
615 char *buf = (char *)malloc(a.length()+1);
616 bool bStart = false;
617 int i, j;
618 for( i = 0, j=0 ; i < a.length() ; i++){ // rtrim and ltrim 32 10 13
619 if( bStart ){
620 buf[j++] = a[i];
622 else{
623 if( a[i] != 32 && a[i] != 10 && a[i] != 13){
624 bStart = true;
625 buf[j++] = a[i];
629 buf[j] = 0;
630 for( i = j-1 ; i >= 0 ; i++ ){
631 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
632 buf[i] = 0;
634 else
635 break;
637 // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
638 if( strlen(buf) > 0 )
639 res = mainParse( a.c_str() );
640 else
641 res = 0L;
642 free(buf);
644 else{
645 res = mainParse( eq );
648 if( res ){
649 makeMathML( res );
651 Node *tmpNode;
652 int count = nodelist.size();
653 for( int i = 0 ; i < count ; i++ ){
654 tmpNode = nodelist.front();
655 nodelist.pop_front();
656 delete tmpNode;
659 return 0;
662 void Formula::trim()
664 int len = strlen(eq);
665 char *buf = (char *)malloc(len+1);
666 bool bStart = false;
667 int i, j;
668 for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
669 if( bStart ){
670 buf[j++] = eq[i];
672 else{
673 if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
674 bStart = true;
675 buf[j++] = eq[i];
679 buf[j] = 0;
680 for( i = j-1 ; i >= 0 ; i++ ){
681 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
682 buf[i] = 0;
684 else
685 break;
687 if( strlen(buf) > 0 )
688 strcpy(eq, buf);
689 else
690 eq = 0L;
691 free(buf);
694 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */