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