update credits
[LibreOffice.git] / hwpfilter / source / formula.cxx
blob03e6be282134cf76df95d03febb097d1733bf519
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "formula.h"
22 #include "mzstring.h"
23 #include "nodes.h"
24 #include "mapping.h"
25 #include "hwpeq.h"
26 #include <iostream>
27 #include <list>
29 extern std::list<Node*> nodelist;
31 #ifndef DEBUG
33 #include "hcode.h"
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
49 extern Node *mainParse(const char *);
52 void Formula::makeMathML(Node *res)
54 Node *tmp = res;
55 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 padd(ascii("xmlns:math"), ascii("CDATA"), ascii("http://www.w3.org/1998/Math/MathML"));
61 rstartEl(ascii("math:math"), rList);
62 pList->clear();
63 rstartEl(ascii("math:semantics"), rList);
64 #endif
65 if( tmp->child )
66 makeLines( tmp->child );
68 #ifdef DEBUG
69 inds;
70 fprintf(stderr,"<math:semantics/>\n");
71 indo;
72 inde;
73 fprintf(stderr,"</math:math>\n");
74 #else
75 rendEl(ascii("math:semantics"));
76 rendEl(ascii("math:math"));
77 #endif
80 void Formula::makeLines(Node *res)
82 Node *tmp = res;
83 if( !tmp ) return;
85 if( tmp->child ){
86 if( tmp->child->id == ID_LINES )
87 makeLines( tmp->child );
88 else
89 makeLine( tmp->child );
91 if( tmp->next )
92 makeLine( tmp->next );
95 void Formula::makeLine(Node *res)
97 if( !res ) return;
98 #ifdef DEBUG
99 inds; fprintf(stderr,"<math:mrow>\n");
100 #else
101 rstartEl(ascii("math:mrow"), rList);
102 #endif
103 if( res->child )
104 makeExprList( res->child );
105 #ifdef DEBUG
106 inde; fprintf(stderr,"</math:mrow>\n");
107 #else
108 rendEl(ascii("math:mrow"));
109 #endif
112 void Formula::makeExprList(Node *res)
114 if( !res ) return;
115 Node *tmp = res->child;
116 if( !tmp ) return ;
118 if( tmp->id == ID_EXPRLIST ){
119 Node *next = tmp->next;
120 makeExprList( tmp ) ;
121 if( next )
122 makeExpr( next );
124 else
125 makeExpr( tmp );
128 void Formula::makeExpr(Node *res)
130 if( !res ) return;
131 Node *tmp = res->child;
132 if( !tmp ) return;
133 switch( tmp->id ) {
134 case ID_PRIMARYEXPR:
135 if( tmp->next ){
136 #ifdef DEBUG
137 inds;
138 fprintf(stderr,"<math:mrow>\n");
139 #else
140 rstartEl(ascii("math:mrow"), rList);
141 #endif
144 makePrimary(tmp);
146 if( tmp->next ){
147 #ifdef DEBUG
148 inde; fprintf(stderr,"</math:mrow>\n");
149 #else
150 rendEl(ascii("math:mrow"));
151 #endif
153 break;
154 case ID_SUBEXPR:
155 case ID_SUPEXPR:
156 case ID_SUBSUPEXPR:
157 makeSubSup(tmp);
158 break;
159 case ID_FRACTIONEXPR:
160 case ID_OVER:
161 makeFraction(tmp);
162 break;
163 case ID_DECORATIONEXPR:
164 makeDecoration(tmp);
165 break;
166 case ID_SQRTEXPR:
167 case ID_ROOTEXPR:
168 makeRoot(tmp);
169 break;
170 case ID_ARROWEXPR:
171 makeArrow(tmp);
172 break;
173 case ID_ACCENTEXPR:
174 makeAccent(tmp);
175 break;
176 case ID_PARENTH:
177 case ID_ABS:
178 makeParenth(tmp);
179 break;
180 case ID_FENCE:
181 makeFence(tmp);
182 break;
183 case ID_BLOCK:
184 makeBlock(tmp);
185 case ID_BEGIN:
186 makeBegin(tmp);
187 case ID_END:
188 makeEnd(tmp);
189 break;
193 void Formula::makeIdentifier(Node *res)
195 Node *tmp = res;
196 if( !tmp ) return;
197 if( !tmp->value ) return;
198 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 rstartEl(ascii("math:mi"), rList);
206 rchars(tmp->value);
207 rendEl(ascii("math:mi"));
208 #endif
209 break;
210 case ID_STRING :
212 #ifdef DEBUG
213 #else
214 rstartEl(ascii("math:mi"), rList);
215 reucstr(tmp->value, strlen(tmp->value));
216 rendEl(ascii("math:mi"));
217 #endif
219 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 rstartEl(ascii("math:mi"), rList);
228 runistr(getMathMLEntity(tmp->value).c_str());
229 rendEl(ascii("math:mi"));
230 #endif
231 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 rstartEl(ascii("math:mn"), rList);
239 rchars(tmp->value);
240 rendEl(ascii("math:mn"));
241 #endif
242 break;
243 case ID_OPERATOR :
244 case ID_DELIMETER :
246 #ifdef DEBUG
247 inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value); indo;
248 #else
249 rstartEl(ascii("math:mo"), rList);
250 runistr(getMathMLEntity(tmp->value).c_str());
251 rendEl(ascii("math:mo"));
252 #endif
253 break;
257 void Formula::makePrimary(Node *res)
259 Node *tmp = res;
260 if( !tmp ) return ;
261 if( tmp->child ){
262 if( tmp->child->id == ID_PRIMARYEXPR ){
263 makePrimary(tmp->child);
265 else{
266 makeIdentifier(tmp->child);
269 if( tmp->next ){
270 makeIdentifier(tmp->next);
274 void Formula::makeSubSup(Node *res)
276 Node *tmp = res;
277 if( !tmp ) return;
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 if( res->id == ID_SUBEXPR )
289 rstartEl(ascii("math:msub"), rList);
290 else if( res->id == ID_SUPEXPR )
291 rstartEl(ascii("math:msup"), rList);
292 else
293 rstartEl(ascii("math:msubsup"), rList);
294 #endif
296 tmp = tmp->child;
297 if( res->id == ID_SUBSUPEXPR ) {
298 makeExpr(tmp);
299 makeBlock(tmp->next);
300 makeBlock(tmp->next->next);
302 else{
303 makeExpr(tmp);
304 makeExpr(tmp->next);
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 if( res->id == ID_SUBEXPR )
317 rendEl(ascii("math:msub"));
318 else if( res->id == ID_SUPEXPR )
319 rendEl(ascii("math:msup"));
320 else
321 rendEl(ascii("math:msubsup"));
322 #endif
325 void Formula::makeFraction(Node *res)
327 Node *tmp = res;
328 if( !tmp ) return;
330 #ifdef DEBUG
331 inds;
332 fprintf(stderr,"<math:mfrac>\n");
333 #else
334 rstartEl(ascii("math:mfrac"), rList);
335 #endif
337 tmp = tmp->child;
338 #ifdef DEBUG
339 inds;
340 fprintf(stderr,"<math:mrow>\n");
341 #else
342 rstartEl(ascii("math:mrow"), rList);
343 #endif
345 if( res->id == ID_FRACTIONEXPR )
346 makeBlock(tmp);
347 else
348 makeExprList(tmp);
350 #ifdef DEBUG
351 inde;
352 fprintf(stderr,"</math:mrow>\n");
353 inds;
354 fprintf(stderr,"<math:mrow>\n");
355 #else
356 rendEl(ascii("math:mrow"));
357 rstartEl(ascii("math:mrow"), rList);
358 #endif
360 if( res->id == ID_FRACTIONEXPR )
361 makeBlock(tmp->next);
362 else
363 makeExprList(tmp->next);
365 #ifdef DEBUG
366 inde;
367 fprintf(stderr,"</math:mrow>\n");
368 inde;
369 fprintf(stderr,"</math:mfrac>\n");
370 #else
371 rendEl(ascii("math:mrow"));
372 rendEl(ascii("math:mfrac"));
373 #endif
376 void Formula::makeDecoration(Node *res)
378 int isover = 1;
379 Node *tmp = res->child;
380 if( !tmp ) return;
381 if( !strncmp(tmp->value,"under", 5) )
382 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 if( isover ){
392 padd(ascii("accent"),ascii("CDATA"),ascii("true"));
393 rstartEl(ascii("math:mover"), rList);
395 else{
396 padd(ascii("accentunder"),ascii("CDATA"),ascii("true"));
397 rstartEl(ascii("math:munder"), rList);
399 pList->clear();
400 #endif
402 makeBlock(tmp->next);
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 rstartEl(ascii("math:mo"), rList);
411 runistr(getMathMLEntity(tmp->value).c_str());
412 rendEl(ascii("math:mo"));
413 #endif
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 if( isover )
423 rendEl(ascii("math:mover"));
424 else
425 rendEl(ascii("math:munder"));
426 #endif
429 void Formula::makeRoot(Node *res)
431 Node *tmp = res;
432 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 if( tmp->id == ID_SQRTEXPR )
441 rstartEl(ascii("math:msqrt"), rList);
442 else
443 rstartEl(ascii("math:mroot"), rList);
444 #endif
446 if( tmp->id == ID_SQRTEXPR ){
447 makeBlock(tmp->child);
449 else{
450 makeBracket(tmp->child);
451 makeBlock(tmp->child->next);
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 if( tmp->id == ID_SQRTEXPR )
462 rendEl(ascii("math:msqrt"));
463 else
464 rendEl(ascii("math:mroot"));
465 #endif
467 // DVO: add space to avoid warning
468 void Formula::makeArrow(Node * /*res*/)
471 void Formula::makeAccent(Node *res)
473 makeDecoration( res );
475 void Formula::makeParenth(Node *res)
477 Node *tmp = res;
478 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");
486 else
487 fprintf(stderr,"<math:mo>|</math:mo>\n");
488 indo; inds;
489 fprintf(stderr,"<math:mrow>\n");
490 #else
491 rstartEl(ascii("math:mrow"), rList);
492 rstartEl(ascii("math:mo"), rList);
493 if( tmp->id == ID_PARENTH )
494 rchars("(");
495 else
496 rchars("|");
497 rendEl(ascii("math:mo"));
498 rstartEl(ascii("math:mrow"), rList);
499 #endif
501 if( tmp->child )
502 makeExprList(tmp->child);
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 rendEl(ascii("math:mrow"));
517 rstartEl(ascii("math:mo"), rList);
518 if( tmp->id == ID_PARENTH )
519 rchars(")");
520 else
521 rchars("|");
522 rendEl(ascii("math:mo"));
523 rendEl(ascii("math:mrow"));
524 #endif
527 void Formula::makeFence(Node *res)
529 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 padd(ascii("open"), ascii("CDATA"),
537 OUString(getMathMLEntity(tmp->value).c_str()) );
538 padd(ascii("close"), ascii("CDATA"),
539 OUString(getMathMLEntity(tmp->next->next->value).c_str()) );
540 rstartEl(ascii("math:mfenced"), rList);
541 pList->clear();
542 #endif
544 makeExprList(tmp->next);
546 #ifdef DEBUG
547 inde;
548 fprintf(stderr,"</math:mfenced>\n");
549 #else
550 rendEl(ascii("math:mfenced"));
551 #endif
554 void Formula::makeBracket(Node *res)
556 makeBlock(res);
559 void Formula::makeBlock(Node *res)
561 #ifdef DEBUG
562 inds;
563 fprintf(stderr,"<math:mrow>\n");
564 #else
565 rstartEl(ascii("math:mrow"), rList);
566 #endif
568 if( res->child )
569 makeExprList(res->child);
571 #ifdef DEBUG
572 inde;
573 fprintf(stderr,"</math:mrow>\n");
574 #else
575 rendEl(ascii("math:mrow"));
576 #endif
579 // DVO: add space to avoid warning
580 void Formula::makeBegin(Node * /*res*/)
584 // DVO: add space to avoid warning
585 void Formula::makeEnd(Node * /*res*/)
589 int Formula::parse()
591 Node *res = 0L;
592 if( !eq ) return 0;
593 if( isHwpEQ ){
594 MzString a;
595 // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
596 eq2latex(a,eq);
598 int idx=a.find(sal::static_int_cast<char>(0xff));
599 while(idx){
600 //printf("idx = [%d]\n",idx);
601 a.replace(idx,0x20);
602 if((idx = a.find(sal::static_int_cast<char>(0xff),idx+1)) < 0)
603 break;
606 char *buf = (char *)malloc(a.length()+1);
607 bool bStart = false;
608 int i, j;
609 for( i = 0, j=0 ; i < a.length() ; i++){ // rtrim and ltrim 32 10 13
610 if( bStart ){
611 buf[j++] = a[i];
613 else{
614 if( a[i] != 32 && a[i] != 10 && a[i] != 13){
615 bStart = true;
616 buf[j++] = a[i];
620 buf[j] = 0;
621 for( i = j-1 ; i >= 0 ; i++ ){
622 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
623 buf[i] = 0;
625 else
626 break;
628 // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
629 if( strlen(buf) > 0 )
630 res = mainParse( a.c_str() );
631 else
632 res = 0L;
633 free(buf);
635 else{
636 res = mainParse( eq );
639 if( res ){
640 makeMathML( res );
642 Node *tmpNode;
643 int count = nodelist.size();
644 for( int i = 0 ; i < count ; i++ ){
645 tmpNode = nodelist.front();
646 nodelist.pop_front();
647 delete tmpNode;
650 return 0;
653 void Formula::trim()
655 int len = strlen(eq);
656 char *buf = (char *)malloc(len+1);
657 bool bStart = false;
658 int i, j;
659 for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
660 if( bStart ){
661 buf[j++] = eq[i];
663 else{
664 if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
665 bStart = true;
666 buf[j++] = eq[i];
670 buf[j] = 0;
671 for( i = j-1 ; i >= 0 ; i++ ){
672 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
673 buf[i] = 0;
675 else
676 break;
678 if( strlen(buf) > 0 )
679 strcpy(eq, buf);
680 else
681 eq = 0L;
682 free(buf);
685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */