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
10 #include "rtfexport.hxx"
11 #include <node.hxx>
12
13 #include <svtools/rtfkeywd.hxx>
14 #include <filter/msfilter/rtfutil.hxx>
15 #include <sal/log.hxx>
16 #include <osl/diagnose.h>
17
SmRtfExport(const SmNode * pIn)18 SmRtfExport::SmRtfExport(const SmNode* pIn)
19 : SmWordExportBase(pIn)
20 , m_pBuffer(nullptr)
21 , m_nEncoding(RTL_TEXTENCODING_DONTKNOW)
22 {
23 }
24
ConvertFromStarMath(OStringBuffer & rBuffer,rtl_TextEncoding nEncoding)25 void SmRtfExport::ConvertFromStarMath(OStringBuffer& rBuffer, rtl_TextEncoding nEncoding)
26 {
27 if (!m_pTree)
28 return;
29 m_pBuffer = &rBuffer;
30 m_nEncoding = nEncoding;
31 m_pBuffer->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE LO_STRING_SVTOOLS_RTF_MOMATH " ");
32 HandleNode(m_pTree, 0);
33 m_pBuffer->append("}"); // moMath
34 }
35
36 // NOTE: This is still work in progress and unfinished, but it already covers a good
37 // part of the rtf math stuff.
38
HandleVerticalStack(const SmNode * pNode,int nLevel)39 void SmRtfExport::HandleVerticalStack(const SmNode* pNode, int nLevel)
40 {
41 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MEQARR " ");
42 int size = pNode->GetNumSubNodes();
43 for (int i = 0; i < size; ++i)
44 {
45 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
46 HandleNode(pNode->GetSubNode(i), nLevel + 1);
47 m_pBuffer->append("}"); // me
48 }
49 m_pBuffer->append("}"); // meqArr
50 }
51
HandleText(const SmNode * pNode,int)52 void SmRtfExport::HandleText(const SmNode* pNode, int /*nLevel*/)
53 {
54 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MR " ");
55
56 if (pNode->GetToken().eType == TTEXT) // literal text
57 m_pBuffer->append(LO_STRING_SVTOOLS_RTF_MNOR " ");
58
59 auto pTemp = static_cast<const SmTextNode*>(pNode);
60 SAL_INFO("starmath.rtf", "Text: " << pTemp->GetText());
61 for (sal_Int32 i = 0; i < pTemp->GetText().getLength(); i++)
62 {
63 sal_uInt16 nChar = pTemp->GetText()[i];
64 OUString aValue(SmTextNode::ConvertSymbolToUnicode(nChar));
65 m_pBuffer->append(msfilter::rtfutil::OutString(aValue, m_nEncoding));
66 }
67
68 m_pBuffer->append("}"); // mr
69 }
70
HandleFractions(const SmNode * pNode,int nLevel,const char * type)71 void SmRtfExport::HandleFractions(const SmNode* pNode, int nLevel, const char* type)
72 {
73 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MF " ");
74 if (type)
75 {
76 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFPR " ");
77 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MTYPE " ");
78 m_pBuffer->append(type);
79 m_pBuffer->append("}"); // mtype
80 m_pBuffer->append("}"); // mfPr
81 }
82 assert(pNode->GetNumSubNodes() == 3);
83 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNUM " ");
84 HandleNode(pNode->GetSubNode(0), nLevel + 1);
85 m_pBuffer->append("}"); // mnum
86 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEN " ");
87 HandleNode(pNode->GetSubNode(2), nLevel + 1);
88 m_pBuffer->append("}"); // mden
89 m_pBuffer->append("}"); // mf
90 }
91
HandleAttribute(const SmAttributNode * pNode,int nLevel)92 void SmRtfExport::HandleAttribute(const SmAttributNode* pNode, int nLevel)
93 {
94 switch (pNode->Attribute()->GetToken().eType)
95 {
96 case TCHECK:
97 case TACUTE:
98 case TGRAVE:
99 case TBREVE:
100 case TCIRCLE:
101 case TVEC:
102 case TTILDE:
103 case THAT:
104 case TDOT:
105 case TDDOT:
106 case TDDDOT:
107 case TWIDETILDE:
108 case TWIDEHAT:
109 case TWIDEHARPOON:
110 case TWIDEVEC:
111 case TBAR:
112 {
113 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MACC " ");
114 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MACCPR " ");
115 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
116 OUString aValue(pNode->Attribute()->GetToken().cMathChar);
117 m_pBuffer->append(msfilter::rtfutil::OutString(aValue, m_nEncoding));
118 m_pBuffer->append("}"); // mchr
119 m_pBuffer->append("}"); // maccPr
120 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
121 HandleNode(pNode->Body(), nLevel + 1);
122 m_pBuffer->append("}"); // me
123 m_pBuffer->append("}"); // macc
124 break;
125 }
126 case TOVERLINE:
127 case TUNDERLINE:
128 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBAR " ");
129 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBARPR " ");
130 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MPOS " ");
131 m_pBuffer->append((pNode->Attribute()->GetToken().eType == TUNDERLINE) ? "bot" : "top");
132 m_pBuffer->append("}"); // mpos
133 m_pBuffer->append("}"); // mbarPr
134 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
135 HandleNode(pNode->Body(), nLevel + 1);
136 m_pBuffer->append("}"); // me
137 m_pBuffer->append("}"); // mbar
138 break;
139 case TOVERSTRIKE:
140 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBORDERBOX " ");
141 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBORDERBOXPR " ");
142 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDETOP " 1}");
143 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDEBOT " 1}");
144 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDELEFT " 1}");
145 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDERIGHT " 1}");
146 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSTRIKEH " 1}");
147 m_pBuffer->append("}"); // mborderBoxPr
148 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
149 HandleNode(pNode->Body(), nLevel + 1);
150 m_pBuffer->append("}"); // me
151 m_pBuffer->append("}"); // mborderBox
152 break;
153 default:
154 HandleAllSubNodes(pNode, nLevel);
155 break;
156 }
157 }
158
HandleRoot(const SmRootNode * pNode,int nLevel)159 void SmRtfExport::HandleRoot(const SmRootNode* pNode, int nLevel)
160 {
161 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MRAD " ");
162 if (const SmNode* argument = pNode->Argument())
163 {
164 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEG " ");
165 HandleNode(argument, nLevel + 1);
166 m_pBuffer->append("}"); // mdeg
167 }
168 else
169 {
170 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MRADPR " ");
171 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEGHIDE " 1}");
172 m_pBuffer->append("}"); // mradPr
173 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEG " }"); // empty but present
174 }
175 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
176 HandleNode(pNode->Body(), nLevel + 1);
177 m_pBuffer->append("}"); // me
178 m_pBuffer->append("}"); // mrad
179 }
180
181 namespace
182 {
mathSymbolToString(const SmNode * node,rtl_TextEncoding nEncoding)183 OString mathSymbolToString(const SmNode* node, rtl_TextEncoding nEncoding)
184 {
185 assert(node->GetType() == SmNodeType::Math || node->GetType() == SmNodeType::MathIdent);
186 auto txtnode = static_cast<const SmTextNode*>(node);
187 if (txtnode->GetText().isEmpty())
188 return OString();
189 assert(txtnode->GetText().getLength() == 1);
190 sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode(txtnode->GetText()[0]);
191 OUString aValue(chr);
192 return msfilter::rtfutil::OutString(aValue, nEncoding);
193 }
194 }
195
HandleOperator(const SmOperNode * pNode,int nLevel)196 void SmRtfExport::HandleOperator(const SmOperNode* pNode, int nLevel)
197 {
198 SAL_INFO("starmath.rtf", "Operator: " << int(pNode->GetToken().eType));
199 switch (pNode->GetToken().eType)
200 {
201 case TINT:
202 case TINTD:
203 case TIINT:
204 case TIIINT:
205 case TLINT:
206 case TLLINT:
207 case TLLLINT:
208 case TPROD:
209 case TCOPROD:
210 case TSUM:
211 {
212 const SmSubSupNode* subsup
213 = pNode->GetSubNode(0)->GetType() == SmNodeType::SubSup
214 ? static_cast<const SmSubSupNode*>(pNode->GetSubNode(0))
215 : nullptr;
216 const SmNode* operation = subsup ? subsup->GetBody() : pNode->GetSubNode(0);
217 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNARY " ");
218 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNARYPR " ");
219 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
220 m_pBuffer->append(mathSymbolToString(operation, m_nEncoding));
221 m_pBuffer->append("}"); // mchr
222 if (!subsup || !subsup->GetSubSup(CSUB))
223 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUBHIDE " 1}");
224 if (!subsup || !subsup->GetSubSup(CSUP))
225 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUPHIDE " 1}");
226 m_pBuffer->append("}"); // mnaryPr
227 if (!subsup || !subsup->GetSubSup(CSUB))
228 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " }");
229 else
230 {
231 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
232 HandleNode(subsup->GetSubSup(CSUB), nLevel + 1);
233 m_pBuffer->append("}"); // msub
234 }
235 if (!subsup || !subsup->GetSubSup(CSUP))
236 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " }");
237 else
238 {
239 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
240 HandleNode(subsup->GetSubSup(CSUP), nLevel + 1);
241 m_pBuffer->append("}"); // msup
242 }
243 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
244 HandleNode(pNode->GetSubNode(1), nLevel + 1); // body
245 m_pBuffer->append("}"); // me
246 m_pBuffer->append("}"); // mnary
247 break;
248 }
249 case TLIM:
250 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFUNC " ");
251 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFNAME " ");
252 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
253 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
254 HandleNode(pNode->GetSymbol(), nLevel + 1);
255 m_pBuffer->append("}"); // me
256 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
257 if (const SmSubSupNode* subsup
258 = pNode->GetSubNode(0)->GetType() == SmNodeType::SubSup
259 ? static_cast<const SmSubSupNode*>(pNode->GetSubNode(0))
260 : nullptr)
261 if (subsup->GetSubSup(CSUB))
262 HandleNode(subsup->GetSubSup(CSUB), nLevel + 1);
263 m_pBuffer->append("}"); // mlim
264 m_pBuffer->append("}"); // mlimLow
265 m_pBuffer->append("}"); // mfName
266 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
267 HandleNode(pNode->GetSubNode(1), nLevel + 1); // body
268 m_pBuffer->append("}"); // me
269 m_pBuffer->append("}"); // mfunc
270 break;
271 default:
272 SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled oper type");
273 break;
274 }
275 }
276
HandleSubSupScriptInternal(const SmSubSupNode * pNode,int nLevel,int flags)277 void SmRtfExport::HandleSubSupScriptInternal(const SmSubSupNode* pNode, int nLevel, int flags)
278 {
279 // rtf supports only a certain combination of sub/super scripts, but LO can have any,
280 // so try to merge it using several tags if necessary
281 if (flags == 0) // none
282 return;
283 if ((flags & (1 << RSUP | 1 << RSUB)) == (1 << RSUP | 1 << RSUB))
284 {
285 // m:sSubSup
286 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUBSUP " ");
287 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
288 flags &= ~(1 << RSUP | 1 << RSUB);
289 if (flags == 0)
290 HandleNode(pNode->GetBody(), nLevel + 1);
291 else
292 HandleSubSupScriptInternal(pNode, nLevel, flags);
293 m_pBuffer->append("}"); // me
294 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
295 HandleNode(pNode->GetSubSup(RSUB), nLevel + 1);
296 m_pBuffer->append("}"); // msub
297 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
298 HandleNode(pNode->GetSubSup(RSUP), nLevel + 1);
299 m_pBuffer->append("}"); // msup
300 m_pBuffer->append("}"); // msubSup
301 }
302 else if ((flags & (1 << RSUB)) == 1 << RSUB)
303 {
304 // m:sSub
305 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUB " ");
306 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
307 flags &= ~(1 << RSUB);
308 if (flags == 0)
309 HandleNode(pNode->GetBody(), nLevel + 1);
310 else
311 HandleSubSupScriptInternal(pNode, nLevel, flags);
312 m_pBuffer->append("}"); // me
313 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
314 HandleNode(pNode->GetSubSup(RSUB), nLevel + 1);
315 m_pBuffer->append("}"); // msub
316 m_pBuffer->append("}"); // msSub
317 }
318 else if ((flags & (1 << RSUP)) == 1 << RSUP)
319 {
320 // m:sSup
321 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUP " ");
322 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
323 flags &= ~(1 << RSUP);
324 if (flags == 0)
325 HandleNode(pNode->GetBody(), nLevel + 1);
326 else
327 HandleSubSupScriptInternal(pNode, nLevel, flags);
328 m_pBuffer->append("}"); // me
329 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
330 HandleNode(pNode->GetSubSup(RSUP), nLevel + 1);
331 m_pBuffer->append("}"); // msup
332 m_pBuffer->append("}"); // msSup
333 }
334 else if ((flags & (1 << LSUP | 1 << LSUB)) == (1 << LSUP | 1 << LSUB))
335 {
336 // m:sPre
337 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSPRE " ");
338 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
339 HandleNode(pNode->GetSubSup(LSUB), nLevel + 1);
340 m_pBuffer->append("}"); // msub
341 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
342 HandleNode(pNode->GetSubSup(LSUP), nLevel + 1);
343 m_pBuffer->append("}"); // msup
344 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
345 flags &= ~(1 << LSUP | 1 << LSUB);
346 if (flags == 0)
347 HandleNode(pNode->GetBody(), nLevel + 1);
348 else
349 HandleSubSupScriptInternal(pNode, nLevel, flags);
350 m_pBuffer->append("}"); // me
351 m_pBuffer->append("}"); // msPre
352 }
353 else if ((flags & (1 << CSUB)) == (1 << CSUB))
354 {
355 // m:limLow looks like a good element for central superscript
356 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
357 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
358 flags &= ~(1 << CSUB);
359 if (flags == 0)
360 HandleNode(pNode->GetBody(), nLevel + 1);
361 else
362 HandleSubSupScriptInternal(pNode, nLevel, flags);
363 m_pBuffer->append("}"); // me
364 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
365 HandleNode(pNode->GetSubSup(CSUB), nLevel + 1);
366 m_pBuffer->append("}"); // mlim
367 m_pBuffer->append("}"); // mlimLow
368 }
369 else if ((flags & (1 << CSUP)) == (1 << CSUP))
370 {
371 // m:limUpp looks like a good element for central superscript
372 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMUPP " ");
373 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
374 flags &= ~(1 << CSUP);
375 if (flags == 0)
376 HandleNode(pNode->GetBody(), nLevel + 1);
377 else
378 HandleSubSupScriptInternal(pNode, nLevel, flags);
379 m_pBuffer->append("}"); // me
380 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
381 HandleNode(pNode->GetSubSup(CSUP), nLevel + 1);
382 m_pBuffer->append("}"); // mlim
383 m_pBuffer->append("}"); // mlimUpp
384 }
385 else
386 SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled subsup type");
387 }
388
HandleMatrix(const SmMatrixNode * pNode,int nLevel)389 void SmRtfExport::HandleMatrix(const SmMatrixNode* pNode, int nLevel)
390 {
391 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MM " ");
392 for (size_t row = 0; row < pNode->GetNumRows(); ++row)
393 {
394 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MMR " ");
395 for (size_t col = 0; col < pNode->GetNumCols(); ++col)
396 {
397 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
398 if (const SmNode* node = pNode->GetSubNode(row * pNode->GetNumCols() + col))
399 HandleNode(node, nLevel + 1);
400 m_pBuffer->append("}"); // me
401 }
402 m_pBuffer->append("}"); // mmr
403 }
404 m_pBuffer->append("}"); // mm
405 }
406
HandleBrace(const SmBraceNode * pNode,int nLevel)407 void SmRtfExport::HandleBrace(const SmBraceNode* pNode, int nLevel)
408 {
409 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MD " ");
410 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDPR " ");
411 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBEGCHR " ");
412 m_pBuffer->append(mathSymbolToString(pNode->OpeningBrace(), m_nEncoding));
413 m_pBuffer->append("}"); // mbegChr
414 std::vector<const SmNode*> subnodes;
415 if (pNode->Body()->GetType() == SmNodeType::Bracebody)
416 {
417 auto body = static_cast<const SmBracebodyNode*>(pNode->Body());
418 bool separatorWritten = false; // assume all separators are the same
419 for (size_t i = 0; i < body->GetNumSubNodes(); ++i)
420 {
421 const SmNode* subnode = body->GetSubNode(i);
422 if (subnode->GetType() == SmNodeType::Math
423 || subnode->GetType() == SmNodeType::MathIdent)
424 {
425 // do not write, but write what separator it is
426 auto math = static_cast<const SmMathSymbolNode*>(subnode);
427 if (!separatorWritten)
428 {
429 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSEPCHR " ");
430 m_pBuffer->append(mathSymbolToString(math, m_nEncoding));
431 m_pBuffer->append("}"); // msepChr
432 separatorWritten = true;
433 }
434 }
435 else
436 subnodes.push_back(subnode);
437 }
438 }
439 else
440 subnodes.push_back(pNode->Body());
441 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MENDCHR " ");
442 m_pBuffer->append(mathSymbolToString(pNode->ClosingBrace(), m_nEncoding));
443 m_pBuffer->append("}"); // mendChr
444 m_pBuffer->append("}"); // mdPr
445 for (const SmNode* subnode : subnodes)
446 {
447 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
448 HandleNode(subnode, nLevel + 1);
449 m_pBuffer->append("}"); // me
450 }
451 m_pBuffer->append("}"); // md
452 }
453
HandleVerticalBrace(const SmVerticalBraceNode * pNode,int nLevel)454 void SmRtfExport::HandleVerticalBrace(const SmVerticalBraceNode* pNode, int nLevel)
455 {
456 SAL_INFO("starmath.rtf", "Vertical: " << int(pNode->GetToken().eType));
457 switch (pNode->GetToken().eType)
458 {
459 case TOVERBRACE:
460 case TUNDERBRACE:
461 {
462 bool top = (pNode->GetToken().eType == TOVERBRACE);
463 if (top)
464 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMUPP " ");
465 else
466 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
467 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
468 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MGROUPCHR " ");
469 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MGROUPCHRPR " ");
470 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
471 m_pBuffer->append(mathSymbolToString(pNode->Brace(), m_nEncoding));
472 m_pBuffer->append("}"); // mchr
473 // TODO not sure if pos and vertJc are correct
474 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MPOS " ")
475 .append(top ? "top" : "bot")
476 .append("}");
477 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MVERTJC " ")
478 .append(top ? "bot" : "top")
479 .append("}");
480 m_pBuffer->append("}"); // mgroupChrPr
481 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
482 HandleNode(pNode->Body(), nLevel + 1);
483 m_pBuffer->append("}"); // me
484 m_pBuffer->append("}"); // mgroupChr
485 m_pBuffer->append("}"); // me
486 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
487 HandleNode(pNode->Script(), nLevel + 1);
488 m_pBuffer->append("}"); // mlim
489 m_pBuffer->append("}"); // mlimUpp or mlimLow
490 break;
491 }
492 default:
493 SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled vertical brace type");
494 break;
495 }
496 }
497
HandleBlank()498 void SmRtfExport::HandleBlank()
499 {
500 m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MR " ");
501 m_pBuffer->append(" ");
502 m_pBuffer->append("}"); // mr
503 }
504
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
506