fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / hwpfilter / source / formula.cxx
blobbb48aef6a6ffb49e3e687aad4995414f79164a28
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"
21 #include "grammar.hxx"
23 #include "mzstring.h"
24 #include "nodes.h"
25 #include "mapping.h"
26 #include "hwpeq.h"
27 #include <iostream>
28 #include <list>
30 extern std::list<Node*> nodelist;
32 #ifndef DEBUG
34 #include "hcode.h"
36 #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
37 #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
38 #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
39 #define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x)); } while(false)
40 #define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(false)
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 void Formula::makeMathML(Node *res)
51 Node *tmp = res;
52 if( !tmp ) return;
53 #ifdef DEBUG
54 inds;
55 fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
56 #else
57 padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
58 rstartEl("math:math", rList);
59 pList->clear();
60 rstartEl("math:semantics", rList);
61 #endif
62 if( tmp->child )
63 makeLines( tmp->child );
65 #ifdef DEBUG
66 inds;
67 fprintf(stderr,"<math:semantics/>\n");
68 indo;
69 inde;
70 fprintf(stderr,"</math:math>\n");
71 #else
72 rendEl("math:semantics");
73 rendEl("math:math");
74 #endif
77 void Formula::makeLines(Node *res)
79 Node *tmp = res;
80 if( !tmp ) return;
82 if( tmp->child ){
83 if( tmp->child->id == ID_LINES )
84 makeLines( tmp->child );
85 else
86 makeLine( tmp->child );
88 if( tmp->next )
89 makeLine( tmp->next );
92 void Formula::makeLine(Node *res)
94 if( !res ) return;
95 #ifdef DEBUG
96 inds; fprintf(stderr,"<math:mrow>\n");
97 #else
98 rstartEl("math:mrow", rList);
99 #endif
100 if( res->child )
101 makeExprList( res->child );
102 #ifdef DEBUG
103 inde; fprintf(stderr,"</math:mrow>\n");
104 #else
105 rendEl("math:mrow");
106 #endif
109 void Formula::makeExprList(Node *res)
111 if( !res ) return;
112 Node *tmp = res->child;
113 if( !tmp ) return ;
115 if( tmp->id == ID_EXPRLIST ){
116 Node *next = tmp->next;
117 makeExprList( tmp ) ;
118 if( next )
119 makeExpr( next );
121 else
122 makeExpr( tmp );
125 void Formula::makeExpr(Node *res)
127 if( !res ) return;
128 Node *tmp = res->child;
129 if( !tmp ) return;
130 switch( tmp->id ) {
131 case ID_PRIMARYEXPR:
132 if( tmp->next ){
133 #ifdef DEBUG
134 inds;
135 fprintf(stderr,"<math:mrow>\n");
136 #else
137 rstartEl("math:mrow", rList);
138 #endif
141 makePrimary(tmp);
143 if( tmp->next ){
144 #ifdef DEBUG
145 inde; fprintf(stderr,"</math:mrow>\n");
146 #else
147 rendEl("math:mrow");
148 #endif
150 break;
151 case ID_SUBEXPR:
152 case ID_SUPEXPR:
153 case ID_SUBSUPEXPR:
154 makeSubSup(tmp);
155 break;
156 case ID_FRACTIONEXPR:
157 case ID_OVER:
158 makeFraction(tmp);
159 break;
160 case ID_DECORATIONEXPR:
161 makeDecoration(tmp);
162 break;
163 case ID_SQRTEXPR:
164 case ID_ROOTEXPR:
165 makeRoot(tmp);
166 break;
167 case ID_ARROWEXPR:
168 break;
169 case ID_ACCENTEXPR:
170 makeAccent(tmp);
171 break;
172 case ID_PARENTH:
173 case ID_ABS:
174 makeParenth(tmp);
175 break;
176 case ID_FENCE:
177 makeFence(tmp);
178 break;
179 case ID_BLOCK:
180 makeBlock(tmp);
181 //fall-through
182 case ID_BEGIN:
183 //fall-through
184 case ID_END:
185 break;
189 void Formula::makeIdentifier(Node *res)
191 Node *tmp = res;
192 if( !tmp ) return;
193 if( !tmp->value ) return;
194 switch( tmp->id ){
195 case ID_CHARACTER :
196 #ifdef DEBUG
197 inds;
198 fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value);
199 indo;
200 #else
201 rstartEl("math:mi", rList);
202 rchars(OUString::createFromAscii(tmp->value));
203 rendEl("math:mi");
204 #endif
205 break;
206 case ID_STRING :
208 #ifdef DEBUG
209 #else
210 rstartEl("math:mi", rList);
211 reucstr(tmp->value, strlen(tmp->value));
212 rendEl("math:mi");
213 #endif
215 break;
216 case ID_IDENTIFIER :
217 #ifdef DEBUG
218 inds;
219 fprintf(stderr,"<math:mi>%s</math:mi>\n",
220 getMathMLEntity(tmp->value).c_str());
221 indo;
222 #else
223 rstartEl("math:mi", rList);
224 runistr(getMathMLEntity(tmp->value).c_str());
225 rendEl("math:mi");
226 #endif
227 break;
228 case ID_NUMBER :
229 #ifdef DEBUG
230 inds;
231 fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value);
232 indo;
233 #else
234 rstartEl("math:mn", rList);
235 rchars(OUString::createFromAscii(tmp->value));
236 rendEl("math:mn");
237 #endif
238 break;
239 case ID_OPERATOR :
240 case ID_DELIMETER :
242 #ifdef DEBUG
243 inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value); indo;
244 #else
245 rstartEl("math:mo", rList);
246 runistr(getMathMLEntity(tmp->value).c_str());
247 rendEl("math:mo");
248 #endif
249 break;
253 void Formula::makePrimary(Node *res)
255 Node *tmp = res;
256 if( !tmp ) return ;
257 if( tmp->child ){
258 if( tmp->child->id == ID_PRIMARYEXPR ){
259 makePrimary(tmp->child);
261 else{
262 makeIdentifier(tmp->child);
265 if( tmp->next ){
266 makeIdentifier(tmp->next);
270 void Formula::makeSubSup(Node *res)
272 Node *tmp = res;
273 if( !tmp ) return;
275 #ifdef DEBUG
276 inds;
277 if( res->id == ID_SUBEXPR )
278 fprintf(stderr,"<math:msub>\n");
279 else if( res->id == ID_SUPEXPR )
280 fprintf(stderr,"<math:msup>\n");
281 else
282 fprintf(stderr,"<math:msubsup>\n");
283 #else
284 if( res->id == ID_SUBEXPR )
285 rstartEl("math:msub", rList);
286 else if( res->id == ID_SUPEXPR )
287 rstartEl("math:msup", rList);
288 else
289 rstartEl("math:msubsup", rList);
290 #endif
292 tmp = tmp->child;
293 if( res->id == ID_SUBSUPEXPR ) {
294 makeExpr(tmp);
295 makeBlock(tmp->next);
296 makeBlock(tmp->next->next);
298 else{
299 makeExpr(tmp);
300 makeExpr(tmp->next);
303 #ifdef DEBUG
304 inde;
305 if( res->id == ID_SUBEXPR )
306 fprintf(stderr,"</math:msub>\n");
307 else if( res->id == ID_SUPEXPR )
308 fprintf(stderr,"</math:msup>\n");
309 else
310 fprintf(stderr,"</math:msubsup>\n");
311 #else
312 if( res->id == ID_SUBEXPR )
313 rendEl("math:msub");
314 else if( res->id == ID_SUPEXPR )
315 rendEl("math:msup");
316 else
317 rendEl("math:msubsup");
318 #endif
321 void Formula::makeFraction(Node *res)
323 Node *tmp = res;
324 if( !tmp ) return;
326 #ifdef DEBUG
327 inds;
328 fprintf(stderr,"<math:mfrac>\n");
329 #else
330 rstartEl("math:mfrac", rList);
331 #endif
333 tmp = tmp->child;
334 #ifdef DEBUG
335 inds;
336 fprintf(stderr,"<math:mrow>\n");
337 #else
338 rstartEl("math:mrow", rList);
339 #endif
341 if( res->id == ID_FRACTIONEXPR )
342 makeBlock(tmp);
343 else
344 makeExprList(tmp);
346 #ifdef DEBUG
347 inde;
348 fprintf(stderr,"</math:mrow>\n");
349 inds;
350 fprintf(stderr,"<math:mrow>\n");
351 #else
352 rendEl("math:mrow");
353 rstartEl("math:mrow", rList);
354 #endif
356 if( res->id == ID_FRACTIONEXPR )
357 makeBlock(tmp->next);
358 else
359 makeExprList(tmp->next);
361 #ifdef DEBUG
362 inde;
363 fprintf(stderr,"</math:mrow>\n");
364 inde;
365 fprintf(stderr,"</math:mfrac>\n");
366 #else
367 rendEl("math:mrow");
368 rendEl("math:mfrac");
369 #endif
372 void Formula::makeDecoration(Node *res)
374 int isover = 1;
375 Node *tmp = res->child;
376 if( !tmp ) return;
377 if( !strncmp(tmp->value,"under", 5) )
378 isover = 0;
379 #ifdef DEBUG
380 inds;
381 if( isover )
382 fprintf(stderr,"<math:mover>\n");
383 else
384 fprintf(stderr,"<math:munder>\n");
385 #else
386 /* accent는 언제 true이고, 언제, false인지 모르겠다. */
387 if( isover ){
388 padd("accent","CDATA","true");
389 rstartEl("math:mover", rList);
391 else{
392 padd("accentunder","CDATA","true");
393 rstartEl("math:munder", rList);
395 pList->clear();
396 #endif
398 makeBlock(tmp->next);
400 #ifdef DEBUG
401 inds;
402 fprintf(stderr,"<math:mo>%s</math:mo>\n",
403 getMathMLEntity(tmp->value).c_str());
404 indo;
405 #else
406 rstartEl("math:mo", rList);
407 runistr(getMathMLEntity(tmp->value).c_str());
408 rendEl("math:mo");
409 #endif
411 #ifdef DEBUG
412 inde;
413 if( isover )
414 fprintf(stderr,"</math:mover>\n");
415 else
416 fprintf(stderr,"</math:munder>\n");
417 #else
418 if( isover )
419 rendEl("math:mover");
420 else
421 rendEl("math:munder");
422 #endif
425 void Formula::makeRoot(Node *res)
427 Node *tmp = res;
428 if( !tmp ) return;
429 #ifdef DEBUG
430 inds;
431 if( tmp->id == ID_SQRTEXPR )
432 fprintf(stderr,"<math:msqrt>\n");
433 else
434 fprintf(stderr,"<math:mroot>\n");
435 #else
436 if( tmp->id == ID_SQRTEXPR )
437 rstartEl("math:msqrt", rList);
438 else
439 rstartEl("math:mroot", rList);
440 #endif
442 if( tmp->id == ID_SQRTEXPR ){
443 makeBlock(tmp->child);
445 else{
446 makeBracket(tmp->child);
447 makeBlock(tmp->child->next);
450 #ifdef DEBUG
451 inde;
452 if( tmp->id == ID_SQRTEXPR )
453 fprintf(stderr,"</math:msqrt>\n");
454 else
455 fprintf(stderr,"</math:mroot>\n");
456 #else
457 if( tmp->id == ID_SQRTEXPR )
458 rendEl("math:msqrt");
459 else
460 rendEl("math:mroot");
461 #endif
463 void Formula::makeAccent(Node *res)
465 makeDecoration( res );
467 void Formula::makeParenth(Node *res)
469 Node *tmp = res;
470 if( !tmp ) return;
471 #ifdef DEBUG
472 inds;
473 fprintf(stderr,"<math:mrow>\n");
474 inds;
475 if( tmp->id == ID_PARENTH ){
476 fprintf(stderr,"<math:mo>(</math:mo>\n");
478 else
479 fprintf(stderr,"<math:mo>|</math:mo>\n");
480 indo; inds;
481 fprintf(stderr,"<math:mrow>\n");
482 #else
483 rstartEl("math:mrow", rList);
484 rstartEl("math:mo", rList);
485 if( tmp->id == ID_PARENTH )
486 rchars("(");
487 else
488 rchars("|");
489 rendEl("math:mo");
490 rstartEl("math:mrow", rList);
491 #endif
493 if( tmp->child )
494 makeExprList(tmp->child);
496 #ifdef DEBUG
497 inde;
498 fprintf(stderr,"</math:mrow>\n");
499 inds;
500 if( tmp->id == ID_PARENTH )
501 fprintf(stderr,"<math:mo>)</math:mo>\n");
502 else
503 fprintf(stderr,"<math:mo>|</math:mo>\n");
504 indo;
505 inde;
506 fprintf(stderr,"</math:mrow>\n");
507 #else
508 rendEl("math:mrow");
509 rstartEl("math:mo", rList);
510 if( tmp->id == ID_PARENTH )
511 rchars(")");
512 else
513 rchars("|");
514 rendEl("math:mo");
515 rendEl("math:mrow");
516 #endif
519 void Formula::makeFence(Node *res)
521 Node *tmp = res->child;
522 #ifdef DEBUG
523 inds;
524 fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
525 getMathMLEntity(tmp->value).c_str(),
526 getMathMLEntity(tmp->next->next->value).c_str());
527 #else
528 padd("open", "CDATA",
529 OUString(getMathMLEntity(tmp->value).c_str()) );
530 padd("close", "CDATA",
531 OUString(getMathMLEntity(tmp->next->next->value).c_str()) );
532 rstartEl("math:mfenced", rList);
533 pList->clear();
534 #endif
536 makeExprList(tmp->next);
538 #ifdef DEBUG
539 inde;
540 fprintf(stderr,"</math:mfenced>\n");
541 #else
542 rendEl("math:mfenced");
543 #endif
546 void Formula::makeBracket(Node *res)
548 makeBlock(res);
551 void Formula::makeBlock(Node *res)
553 #ifdef DEBUG
554 inds;
555 fprintf(stderr,"<math:mrow>\n");
556 #else
557 rstartEl("math:mrow", rList);
558 #endif
560 if( res->child )
561 makeExprList(res->child);
563 #ifdef DEBUG
564 inde;
565 fprintf(stderr,"</math:mrow>\n");
566 #else
567 rendEl("math:mrow");
568 #endif
571 int Formula::parse()
573 Node *res = 0L;
574 if( !eq ) return 0;
575 if( isHwpEQ ){
576 MzString a;
577 // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
578 eq2latex(a,eq);
580 int idx=a.find(sal::static_int_cast<char>(0xff));
581 while(idx){
582 //printf("idx = [%d]\n",idx);
583 a.replace(idx,0x20);
584 if((idx = a.find(sal::static_int_cast<char>(0xff),idx+1)) < 0)
585 break;
588 char *buf = static_cast<char *>(malloc(a.length()+1));
589 bool bStart = false;
590 int i, j;
591 for( i = 0, j=0 ; i < a.length() ; i++){ // rtrim and ltrim 32 10 13
592 if( bStart ){
593 buf[j++] = a[i];
595 else{
596 if( a[i] != 32 && a[i] != 10 && a[i] != 13){
597 bStart = true;
598 buf[j++] = a[i];
602 buf[j] = 0;
603 for( i = j-1 ; i >= 0 ; i++ ){
604 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
605 buf[i] = 0;
607 else
608 break;
610 // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
611 if( buf[0] != '\0' )
612 res = mainParse( a.c_str() );
613 else
614 res = 0L;
615 free(buf);
617 else{
618 res = mainParse( eq );
621 if( res ){
622 makeMathML( res );
624 int count = nodelist.size();
625 for( int i = 0 ; i < count ; i++ ){
626 const Node *tmpNode = nodelist.front();
627 nodelist.pop_front();
628 delete tmpNode;
631 return 0;
634 void Formula::trim()
636 int len = strlen(eq);
637 char *buf = static_cast<char *>(malloc(len+1));
638 bool bStart = false;
639 int i, j;
640 for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
641 if( bStart ){
642 buf[j++] = eq[i];
644 else{
645 if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
646 bStart = true;
647 buf[j++] = eq[i];
651 buf[j] = 0;
652 for( i = j-1 ; i >= 0 ; i++ ){
653 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
654 buf[i] = 0;
656 else
657 break;
659 if( buf[0] != '\0' )
660 strcpy(eq, buf);
661 else
662 eq = 0L;
663 free(buf);
666 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */