LibreOffice Module hwpfilter (master) 1
formula.cxx
Go to the documentation of this file.
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#include "grammar.hxx"
22
23#include "nodes.h"
24#include "mapping.h"
25#include "hwpeq.h"
26#include <iostream>
27
28#ifndef DEBUG
29
30#include "hcode.h"
31
32#define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
33#define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
34#define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
35#define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
36#define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(false)
37#define padd(x,y,z) mxList->addAttribute(x,y,z)
38#else
39static int indent = 0;
40#define inds indent++; for(int i = 0 ; i < indent ; i++) fprintf(stderr," ")
41#define inde for(int i = 0 ; i < indent ; i++) fprintf(stderr," "); indent--
42#define indo indent--;
43#endif
44
46{
47 Node *tmp = res;
48 if( !tmp ) return;
49#ifdef DEBUG
50 inds;
51 fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
52#else
53 padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
54 rstartEl("math:math", mxList);
55 mxList->clear();
56 rstartEl("math:semantics", mxList);
57#endif
58 if( tmp->child )
59 makeLines( tmp->child );
60
61#ifdef DEBUG
62 inds;
63 fprintf(stderr,"<math:semantics/>\n");
64 indo;
65 inde;
66 fprintf(stderr,"</math:math>\n");
67#else
68 rendEl("math:semantics");
69 rendEl("math:math");
70#endif
71}
72
74{
75 Node *tmp = res;
76 if( !tmp ) return;
77
78 if( tmp->child ){
79 if( tmp->child->id == ID_LINES )
80 makeLines( tmp->child );
81 else
82 makeLine( tmp->child );
83 }
84 if( tmp->next )
85 makeLine( tmp->next );
86}
87
89{
90 if( !res ) return;
91#ifdef DEBUG
92 inds; fprintf(stderr,"<math:mrow>\n");
93#else
94 rstartEl("math:mrow", mxList);
95#endif
96 if( res->child )
97 makeExprList( res->child );
98#ifdef DEBUG
99 inde; fprintf(stderr,"</math:mrow>\n");
100#else
101 rendEl("math:mrow");
102#endif
103}
104
106{
107 if( !res ) return;
108 Node *tmp = res->child;
109 if( !tmp ) return ;
110
111 if( tmp->id == ID_EXPRLIST ){
112 Node *next = tmp->next;
113 makeExprList( tmp ) ;
114 if( next )
115 makeExpr( next );
116 }
117 else
118 makeExpr( tmp );
119}
120
122{
123 if( !res ) return;
124 Node *tmp = res->child;
125 if( !tmp ) return;
126 switch( tmp->id ) {
127 case ID_PRIMARYEXPR:
128 if( tmp->next ){
129#ifdef DEBUG
130 inds;
131 fprintf(stderr,"<math:mrow>\n");
132#else
133 rstartEl("math:mrow", mxList);
134#endif
135 }
136
137 makePrimary(tmp);
138
139 if( tmp->next ){
140#ifdef DEBUG
141 inde; fprintf(stderr,"</math:mrow>\n");
142#else
143 rendEl("math:mrow");
144#endif
145 }
146 break;
147 case ID_SUBEXPR:
148 case ID_SUPEXPR:
149 case ID_SUBSUPEXPR:
150 makeSubSup(tmp);
151 break;
152 case ID_FRACTIONEXPR:
153 case ID_OVER:
154 makeFraction(tmp);
155 break;
157 makeDecoration(tmp);
158 break;
159 case ID_SQRTEXPR:
160 case ID_ROOTEXPR:
161 makeRoot(tmp);
162 break;
163 case ID_ARROWEXPR:
164 break;
165 case ID_ACCENTEXPR:
166 makeAccent(tmp);
167 break;
168 case ID_PARENTH:
169 case ID_ABS:
170 makeParenth(tmp);
171 break;
172 case ID_FENCE:
173 makeFence(tmp);
174 break;
175 case ID_BLOCK:
176 makeBlock(tmp);
177 break;
178 case ID_BEGIN:
179 case ID_END:
180 break;
181 }
182}
183
185{
186 Node *tmp = res;
187 if( !tmp ) return;
188 if( !tmp->value ) return;
189 switch( tmp->id ){
190 case ID_CHARACTER :
191#ifdef DEBUG
192 inds;
193 fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value.get());
194 indo;
195#else
196 rstartEl("math:mi", mxList);
197 rchars(OUString::createFromAscii(tmp->value.get()));
198 rendEl("math:mi");
199#endif
200 break;
201 case ID_STRING :
202 {
203#ifdef DEBUG
204#else
205 rstartEl("math:mi", mxList);
206 reucstr(tmp->value.get(), strlen(tmp->value.get()));
207 rendEl("math:mi");
208#endif
209 }
210 break;
211 case ID_IDENTIFIER :
212#ifdef DEBUG
213 inds;
214 fprintf(stderr,"<math:mi>%s</math:mi>\n",
215 getMathMLEntity(tmp->value.get()).c_str());
216 indo;
217#else
218 rstartEl("math:mi", mxList);
219 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
220 rendEl("math:mi");
221#endif
222 break;
223 case ID_NUMBER :
224#ifdef DEBUG
225 inds;
226 fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value.get());
227 indo;
228#else
229 rstartEl("math:mn", mxList);
230 rchars(OUString::createFromAscii(tmp->value.get()));
231 rendEl("math:mn");
232#endif
233 break;
234 case ID_OPERATOR :
235 case ID_DELIMITER :
236 {
237#ifdef DEBUG
238 inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value.get()); indo;
239#else
240 rstartEl("math:mo", mxList);
241 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
242 rendEl("math:mo");
243#endif
244 break;
245 }
246 }
247}
249{
250 Node *tmp = res;
251 if( !tmp ) return ;
252 if( tmp->child ){
253 if( tmp->child->id == ID_PRIMARYEXPR ){
254 makePrimary(tmp->child);
255 }
256 else{
257 makeIdentifier(tmp->child);
258 }
259 }
260 if( tmp->next ){
261 makeIdentifier(tmp->next);
262 }
263}
264
266{
267 Node *tmp = res;
268 if( !tmp ) return;
269
270#ifdef DEBUG
271 inds;
272 if( res->id == ID_SUBEXPR )
273 fprintf(stderr,"<math:msub>\n");
274 else if( res->id == ID_SUPEXPR )
275 fprintf(stderr,"<math:msup>\n");
276 else
277 fprintf(stderr,"<math:msubsup>\n");
278#else
279 if( res->id == ID_SUBEXPR )
280 rstartEl("math:msub", mxList);
281 else if( res->id == ID_SUPEXPR )
282 rstartEl("math:msup", mxList);
283 else
284 rstartEl("math:msubsup", mxList);
285#endif
286
287 tmp = tmp->child;
288 if( res->id == ID_SUBSUPEXPR ) {
289 makeExpr(tmp);
290 makeBlock(tmp->next);
291 makeBlock(tmp->next->next);
292 }
293 else{
294 makeExpr(tmp);
295 makeExpr(tmp->next);
296 }
297
298#ifdef DEBUG
299 inde;
300 if( res->id == ID_SUBEXPR )
301 fprintf(stderr,"</math:msub>\n");
302 else if( res->id == ID_SUPEXPR )
303 fprintf(stderr,"</math:msup>\n");
304 else
305 fprintf(stderr,"</math:msubsup>\n");
306#else
307 if( res->id == ID_SUBEXPR )
308 rendEl("math:msub");
309 else if( res->id == ID_SUPEXPR )
310 rendEl("math:msup");
311 else
312 rendEl("math:msubsup");
313#endif
314}
315
317{
318 Node *tmp = res;
319 if( !tmp ) return;
320
321#ifdef DEBUG
322 inds;
323 fprintf(stderr,"<math:mfrac>\n");
324#else
325 rstartEl("math:mfrac", mxList);
326#endif
327
328 tmp = tmp->child;
329#ifdef DEBUG
330 inds;
331 fprintf(stderr,"<math:mrow>\n");
332#else
333 rstartEl("math:mrow", mxList);
334#endif
335
336 if( res->id == ID_FRACTIONEXPR )
337 makeBlock(tmp);
338 else
339 makeExprList(tmp);
340
341#ifdef DEBUG
342 inde;
343 fprintf(stderr,"</math:mrow>\n");
344 inds;
345 fprintf(stderr,"<math:mrow>\n");
346#else
347 rendEl("math:mrow");
348 rstartEl("math:mrow", mxList);
349#endif
350
351 if( res->id == ID_FRACTIONEXPR )
352 makeBlock(tmp->next);
353 else
354 makeExprList(tmp->next);
355
356#ifdef DEBUG
357 inde;
358 fprintf(stderr,"</math:mrow>\n");
359 inde;
360 fprintf(stderr,"</math:mfrac>\n");
361#else
362 rendEl("math:mrow");
363 rendEl("math:mfrac");
364#endif
365}
366
368{
369 int isover = 1;
370 Node *tmp = res->child;
371 if( !tmp ) return;
372 if( !strncmp(tmp->value.get(),"under", 5) )
373 isover = 0;
374#ifdef DEBUG
375 inds;
376 if( isover )
377 fprintf(stderr,"<math:mover>\n");
378 else
379 fprintf(stderr,"<math:munder>\n");
380#else
381 /* FIXME: no idea when 'accent' is true or false. */
382 if( isover ){
383 padd("accent","CDATA","true");
384 rstartEl("math:mover", mxList);
385 }
386 else{
387 padd("accentunder","CDATA","true");
388 rstartEl("math:munder", mxList);
389 }
390 mxList->clear();
391#endif
392
393 makeBlock(tmp->next);
394
395#ifdef DEBUG
396 inds;
397 fprintf(stderr,"<math:mo>%s</math:mo>\n",
398 getMathMLEntity(tmp->value.get()).c_str());
399 indo;
400#else
401 rstartEl("math:mo", mxList);
402 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
403 rendEl("math:mo");
404#endif
405
406#ifdef DEBUG
407 inde;
408 if( isover )
409 fprintf(stderr,"</math:mover>\n");
410 else
411 fprintf(stderr,"</math:munder>\n");
412#else
413 if( isover )
414 rendEl("math:mover");
415 else
416 rendEl("math:munder");
417#endif
418}
419
421{
422 Node *tmp = res;
423 if( !tmp ) return;
424#ifdef DEBUG
425 inds;
426 if( tmp->id == ID_SQRTEXPR )
427 fprintf(stderr,"<math:msqrt>\n");
428 else
429 fprintf(stderr,"<math:mroot>\n");
430#else
431 if( tmp->id == ID_SQRTEXPR )
432 rstartEl("math:msqrt", mxList);
433 else
434 rstartEl("math:mroot", mxList);
435#endif
436
437 if( tmp->id == ID_SQRTEXPR ){
438 makeBlock(tmp->child);
439 }
440 else{
441 makeBracket(tmp->child);
442 makeBlock(tmp->child->next);
443 }
444
445#ifdef DEBUG
446 inde;
447 if( tmp->id == ID_SQRTEXPR )
448 fprintf(stderr,"</math:msqrt>\n");
449 else
450 fprintf(stderr,"</math:mroot>\n");
451#else
452 if( tmp->id == ID_SQRTEXPR )
453 rendEl("math:msqrt");
454 else
455 rendEl("math:mroot");
456#endif
457}
459{
460 makeDecoration( res );
461}
463{
464 Node *tmp = res;
465 if( !tmp ) return;
466#ifdef DEBUG
467 inds;
468 fprintf(stderr,"<math:mrow>\n");
469 inds;
470 if( tmp->id == ID_PARENTH ){
471 fprintf(stderr,"<math:mo>(</math:mo>\n");
472 }
473 else
474 fprintf(stderr,"<math:mo>|</math:mo>\n");
475 indo; inds;
476 fprintf(stderr,"<math:mrow>\n");
477#else
478 rstartEl("math:mrow", mxList);
479 rstartEl("math:mo", mxList);
480 if( tmp->id == ID_PARENTH )
481 rchars("(");
482 else
483 rchars("|");
484 rendEl("math:mo");
485 rstartEl("math:mrow", mxList);
486#endif
487
488 if( tmp->child )
489 makeExprList(tmp->child);
490
491#ifdef DEBUG
492 inde;
493 fprintf(stderr,"</math:mrow>\n");
494 inds;
495 if( tmp->id == ID_PARENTH )
496 fprintf(stderr,"<math:mo>)</math:mo>\n");
497 else
498 fprintf(stderr,"<math:mo>|</math:mo>\n");
499 indo;
500 inde;
501 fprintf(stderr,"</math:mrow>\n");
502#else
503 rendEl("math:mrow");
504 rstartEl("math:mo", mxList);
505 if( tmp->id == ID_PARENTH )
506 rchars(")");
507 else
508 rchars("|");
509 rendEl("math:mo");
510 rendEl("math:mrow");
511#endif
512}
513
515{
516 Node *tmp = res->child;
517#ifdef DEBUG
518 inds;
519 fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
520 getMathMLEntity(tmp->value.get()).c_str(),
521 getMathMLEntity(tmp->next->next->value.get()).c_str());
522#else
523 padd("open", "CDATA",
524 OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->value.get()).c_str())));
525 padd("close", "CDATA",
526 OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->next->next->value.get()).c_str())));
527 rstartEl("math:mfenced", mxList);
528 mxList->clear();
529#endif
530
531 makeExprList(tmp->next);
532
533#ifdef DEBUG
534 inde;
535 fprintf(stderr,"</math:mfenced>\n");
536#else
537 rendEl("math:mfenced");
538#endif
539}
540
542{
543 makeBlock(res);
544}
545
547{
548#ifdef DEBUG
549 inds;
550 fprintf(stderr,"<math:mrow>\n");
551#else
552 rstartEl("math:mrow", mxList);
553#endif
554
555 if( res->child )
556 makeExprList(res->child);
557
558#ifdef DEBUG
559 inde;
560 fprintf(stderr,"</math:mrow>\n");
561#else
562 rendEl("math:mrow");
563#endif
564}
565
567{
568 Node *res = nullptr;
569 if( !eq ) return;
570
571 OString a;
572 // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
573 eq2latex(a,eq);
574
575 int idx=a.indexOf('\xff');
576 while(idx >= 0){
577 //printf("idx = [%d]\n",idx);
578 a = a.replaceAt(idx, 1, "\x20");
579 idx = a.indexOf('\xff', idx + 1);
580 }
581
582 char *buf = static_cast<char *>(malloc(a.getLength()+1));
583 bool bStart = false;
584 int i, j;
585 for( i = 0, j=0 ; i < a.getLength() ; i++){ // rtrim and ltrim 32 10 13
586 if( bStart ){
587 buf[j++] = a[i];
588 }
589 else{
590 if( a[i] != 32 && a[i] != 10 && a[i] != 13){
591 bStart = true;
592 buf[j++] = a[i];
593 }
594 }
595 }
596 buf[j] = 0;
597 for( i = j-1 ; i >= 0 ; i++ ){
598 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
599 buf[i] = 0;
600 }
601 else
602 break;
603 }
604 // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
605 if( buf[0] != '\0' )
606 res = mainParse( a.getStr() );
607 else
608 res = nullptr;
609 free(buf);
610
611 if( res ){
612 makeMathML( res );
613 }
614 nodelist.clear();
615}
616
618{
619 int len = strlen(eq);
620 char *buf = static_cast<char *>(malloc(len+1));
621 bool bStart = false;
622 int i, j;
623 for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
624 if( bStart ){
625 buf[j++] = eq[i];
626 }
627 else{
628 if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
629 bStart = true;
630 buf[j++] = eq[i];
631 }
632 }
633 }
634 buf[j] = 0;
635 for( i = j-1 ; i >= 0 ; i++ ){
636 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
637 buf[i] = 0;
638 }
639 else
640 break;
641 }
642 if( buf[0] != '\0' )
643 strcpy(eq, buf);
644 else
645 eq = nullptr;
646 free(buf);
647}
648
649/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
rtl::Reference< AttributeListImpl > mxList
Definition: formula.h:70
void makeSubSup(Node *res)
Definition: formula.cxx:265
void makeDecoration(Node *res)
Definition: formula.cxx:367
void makeLine(Node *res)
Definition: formula.cxx:88
void parse()
Definition: formula.cxx:566
char * eq
Definition: formula.h:71
void trim()
Definition: formula.cxx:617
void makeIdentifier(Node *res)
Definition: formula.cxx:184
void makeBracket(Node *res)
Definition: formula.cxx:541
void makeLines(Node *res)
Definition: formula.cxx:73
void makePrimary(Node *res)
Definition: formula.cxx:248
void makeParenth(Node *res)
Definition: formula.cxx:462
void makeFence(Node *res)
Definition: formula.cxx:514
void makeAccent(Node *res)
Definition: formula.cxx:458
void makeExpr(Node *res)
Definition: formula.cxx:121
void makeMathML(Node *res)
Definition: formula.cxx:45
void makeBlock(Node *res)
Definition: formula.cxx:546
void makeFraction(Node *res)
Definition: formula.cxx:316
void makeRoot(Node *res)
Definition: formula.cxx:420
void makeExprList(Node *res)
Definition: formula.cxx:105
#define inde
Definition: formula.cxx:41
#define indo
Definition: formula.cxx:42
static int indent
Definition: formula.cxx:39
#define inds
Definition: formula.cxx:40
std::vector< std::unique_ptr< Node > > nodelist
Definition: grammar.cxx:40
Node * mainParse(const char *_code)
Definition: grammar.cxx:890
void eq2latex(OString &outs, char const *s)
Definition: hwpeq.cxx:768
OUString fromHcharStringToOUString(hchar_string const &s)
Definition: hwplib.h:46
const sal_uInt16 idx[]
uno_Any a
::std::string getMathMLEntity(const char *tex)
Definition: mapping.h:385
int i
@ ID_OPERATOR
Definition: nodes.h:63
@ ID_DELIMITER
Definition: nodes.h:65
@ ID_PRIMARYEXPR
Definition: nodes.h:53
@ ID_NUMBER
Definition: nodes.h:62
@ ID_LINES
Definition: nodes.h:34
@ ID_ROOTEXPR
Definition: nodes.h:49
@ ID_ARROWEXPR
Definition: nodes.h:50
@ ID_FRACTIONEXPR
Definition: nodes.h:45
@ ID_SUBEXPR
Definition: nodes.h:42
@ ID_DECORATIONEXPR
Definition: nodes.h:47
@ ID_END
Definition: nodes.h:39
@ ID_FENCE
Definition: nodes.h:57
@ ID_PARENTH
Definition: nodes.h:56
@ ID_STRING
Definition: nodes.h:60
@ ID_SUPEXPR
Definition: nodes.h:43
@ ID_SQRTEXPR
Definition: nodes.h:48
@ ID_IDENTIFIER
Definition: nodes.h:59
@ ID_ACCENTEXPR
Definition: nodes.h:51
@ ID_ABS
Definition: nodes.h:58
@ ID_OVER
Definition: nodes.h:46
@ ID_SUBSUPEXPR
Definition: nodes.h:44
@ ID_EXPRLIST
Definition: nodes.h:36
@ ID_CHARACTER
Definition: nodes.h:61
@ ID_BLOCK
Definition: nodes.h:55
@ ID_BEGIN
Definition: nodes.h:38
sal_uInt16 sal_Unicode