1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "mathtype.hxx"
22 #include <filter/msfilter/classids.hxx>
23 #include <osl/diagnose.h>
24 #include <sfx2/docfile.hxx>
25 #include <sot/storage.hxx>
26 #include <sal/log.hxx>
28 #include "eqnolefilehdr.hxx"
33 //These are the default MathType sizes
34 aSizeTable
.push_back(12);
35 aSizeTable
.push_back(8);
36 aSizeTable
.push_back(6);
37 aSizeTable
.push_back(24);
38 aSizeTable
.push_back(10);
39 aSizeTable
.push_back(12);
40 aSizeTable
.push_back(12);
43 These are the default MathType italic/bold settings If mathtype is changed
44 from its defaults, there is nothing we can do, as this information is not
45 stored in the document
48 for(sal_uInt8 i
=1;i
<=11;i
++)
64 aUserStyles
.insert(aFont
);
69 /*ToDo replace with table rather than switch, returns
70 sal_True in the case that the char is just a char, and
71 sal_False if the character is an operator which must not be
72 placed inside the quote sequence designed to protect
73 against being parsed as a keyword
75 General solution required to force starmath to handle
76 unicode math chars the way it handles its own math
77 chars rather than handle them as text as it will do
78 for the default case below, i.e. incorrect spacing
79 between math symbols and ordinary text e.g. 1=2 rather
82 bool MathType::LookupChar(sal_Unicode nChar
,OUStringBuffer
&rRet
,sal_uInt8 nVersion
,
86 const char *pC
= nullptr;
114 if ((nVersion
< 3) && (nTypeFace
== 0x86))
118 rRet
.append(OUStringChar(nChar
));
123 if ((nVersion
< 3) && (nTypeFace
== 0x81))
125 rRet
.append(OUStringChar(nChar
));
129 if ((nVersion
< 3) && (nTypeFace
== 0x84))
131 rRet
.append(OUStringChar(nChar
));
135 if ((nVersion
< 3) && (nTypeFace
== 0x84))
137 rRet
.append(OUStringChar(nChar
));
141 if ((nVersion
< 3) && (nTypeFace
== 0x84))
143 rRet
.append(OUStringChar(nChar
));
147 if ((nVersion
< 3) && (nTypeFace
== 0x84))
149 rRet
.append(OUStringChar(nChar
));
153 if ((nVersion
< 3) && (nTypeFace
== 0x84))
155 rRet
.append(OUStringChar(nChar
));
159 if ((nVersion
< 3) && (nTypeFace
== 0x84))
161 rRet
.append(OUStringChar(nChar
));
165 if ((nVersion
< 3) && (nTypeFace
== 0x82))
167 rRet
.append(OUStringChar(nChar
));
171 if ((nVersion
< 3) && (nTypeFace
== 0x86))
175 rRet
.append(OUStringChar(nChar
));
180 if ((nVersion
< 3) && (nTypeFace
== 0x86))
184 rRet
.append(OUStringChar(nChar
));
189 if ((nVersion
< 3) && (nTypeFace
== 0x86))
193 rRet
.append(OUStringChar(nChar
));
198 if ((nVersion
< 3) && (nTypeFace
== 0x85))
202 rRet
.append(OUStringChar(nChar
));
318 case 0x2209: // notin
319 rRet
.append(" func ").append(OUStringChar(nChar
)).append(" ");
322 rRet
.append(u
" func \u220b ");
358 pC
= " intersection ";
407 pC
= " preccurlyeq ";
410 pC
= " succcurlyeq ";
425 case 0x2282: // subset
426 case 0x2283: // supset
427 case 0x2284: // nsubset
428 case 0x2285: // nsupset
429 case 0x2286: // subseteq
430 case 0x2287: // supseteq
431 case 0x2288: // nsubseteq
432 case 0x2289: // nsupseteq
433 case 0x22b2: // NORMAL SUBGROUP OF
434 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
435 rRet
.append(" func ").append(OUStringChar(nChar
)).append(" ");
489 case 0xeb01: //no space
490 case 0xeb08: //normal space
493 case 0xef04: //tiny space
494 case 0xef05: //tiny space
495 case 0xeb02: //small space
496 case 0xeb04: //medium space
499 case 0xeb05: //large space
506 rRet
.append(OUStringChar(nChar
));
511 rRet
.appendAscii(pC
);
515 void MathTypeFont::AppendStyleToText(OUString
&rRet
)
517 const char *pC
= nullptr;
534 rRet
+= OUString::createFromAscii( pC
);
537 void MathType::TypeFaceToString(OUString
&rTxt
,sal_uInt8 nFace
)
539 MathTypeFont
aFont(nFace
);
540 MathTypeFontSet::iterator aItr
= aUserStyles
.find(aFont
);
541 if (aItr
!= aUserStyles
.end())
542 aFont
.nStyle
= aItr
->nStyle
;
543 aFont
.AppendStyleToText(rTxt
);
546 bool MathType::Parse(SotStorage
*pStor
)
548 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(
550 StreamMode::STD_READ
);
551 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
553 return Parse(xSrc
.get());
556 bool MathType::Parse(SvStream
* pStream
)
559 pS
->SetEndian( SvStreamEndian::LITTLE
);
563 sal_uInt8 nProdVersion
;
564 sal_uInt8 nProdSubVersion
;
567 pS
->ReadUChar( nVersion
);
568 pS
->ReadUChar( nPlatform
);
569 pS
->ReadUChar( nProduct
);
570 pS
->ReadUChar( nProdVersion
);
571 pS
->ReadUChar( nProdSubVersion
);
573 if (nVersion
> 3) // allow only supported versions of MathType to be parsed
576 bool bRet
= HandleRecords(0);
577 //little crude hack to close occasionally open expressions
578 //a sophisticated system to determine what expressions are
579 //opened is required, but this is as much work as rewriting
580 //starmaths internals.
586 static void lcl_PrependDummyTerm(OUStringBuffer
&rRet
, sal_Int32
&rTextStart
)
588 if ((rTextStart
< rRet
.getLength()) &&
589 (rRet
[rTextStart
] == '=') &&
590 ((rTextStart
== 0) || (rRet
[ rTextStart
-1 ] == '{'))
593 rRet
.insert(rTextStart
, " {}");
598 static void lcl_AppendDummyTerm(OUStringBuffer
&rRet
)
601 for(int nI
=rRet
.getLength()-1;nI
>= 0; nI
--)
603 sal_Int32 nIdx
= sal::static_int_cast
< sal_Int32
>(nI
);
604 sal_Unicode nChar
= rRet
[nIdx
];
607 if (rRet
[nIdx
] != '{')
611 if (!bOk
) //No term, use dummy
615 void MathType::HandleNudge()
617 sal_uInt8
nXNudge(0);
618 pS
->ReadUChar(nXNudge
);
619 sal_uInt8
nYNudge(0);
620 pS
->ReadUChar(nYNudge
);
621 if (nXNudge
== 128 && nYNudge
== 128)
623 sal_uInt16
nXLongNudge(0);
624 sal_uInt16
nYLongNudge(0);
625 pS
->ReadUInt16(nXLongNudge
);
626 pS
->ReadUInt16(nYLongNudge
);
630 /* Fabulously complicated as many tokens have to be reordered and generally
631 * moved around from mathtypes paradigm to starmaths. */
632 bool MathType::HandleRecords(int nLevel
, sal_uInt8 nSelector
,
633 sal_uInt8 nVariation
, int nMatrixRows
, int nMatrixCols
)
639 sal_uInt8 nTag
,nRecord
;
640 sal_uInt8 nTabType
,nTabStops
;
641 sal_uInt16 nTabOffset
;
645 OUString sPush
,sMainTerm
;
646 int nSetSize
=0,nSetAlign
=0;
647 int nCurRow
=0,nCurCol
=0;
648 bool bOpenString
=false;
649 sal_Int32 nTextStart
= 0;
650 sal_Int32 nSubSupStartPos
= 0;
651 sal_Int32 nLastTemplateBracket
=-1;
657 pS
->ReadUChar( nTag
);
660 /*MathType strings can of course include words which
661 *are StarMath keywords, the simplest solution is
662 to escape strings of greater than len 1 with double
663 quotes to avoid scanning the TokenTable for matches
665 Unfortunately it may turn out that the string gets
666 split during the handling of a character emblishment
667 so this special case must be handled in the
668 character handler case 2:
670 if ((nRecord
== CHAR
) && (!bOpenString
))
673 nTextStart
= rRet
.getLength();
675 else if ((nRecord
!= CHAR
) && bOpenString
)
678 if ((rRet
.getLength() - nTextStart
) > 1)
681 TypeFaceToString(aStr
,nTypeFace
);
683 rRet
.insert(nTextStart
,aStr
);
686 else if (nRecord
== END
&& !rRet
.isEmpty())
688 sal_Unicode cChar
= 0;
689 sal_Int32 nI
= rRet
.getLength()-1;
697 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
710 rRet
.append("\nnewline\n");
717 rRet
.append(" langle ");
718 else if (nVariation
==1)
719 rRet
.append(" \\langle ");
723 rRet
.append(" left (");
724 else if (nVariation
==1)
728 if ((nVariation
==0) || (nVariation
==1))
729 rRet
.append(" left lbrace ");
731 rRet
.append(" left none ");
735 rRet
.append(" left [");
736 else if (nVariation
==1)
745 rRet
.append(" lline ");
746 else if (nVariation
==1)
747 rRet
.append(" \\lline ");
751 rRet
.append(" ldline ");
752 else if (nVariation
==1)
753 rRet
.append(" \\ldline ");
756 if (nVariation
== 0 || nVariation
& 0x01) // tvFENCE_L
757 rRet
.append(" left lfloor ");
759 rRet
.append(" left none ");
763 rRet
.append(" lceil ");
764 else if (nVariation
==1)
765 rRet
.append(" \\lceil ");
778 rRet
.append(" sqrt");
781 rRet
.append(" nroot");
782 sPush
= rRet
.makeStringAndClear();
793 rRet
.append(" over ");
797 nSubSupStartPos
= rRet
.getLength();
798 if ((nVariation
== 0) ||
799 ((nVariation
== 2) && (nPart
==1)))
801 lcl_AppendDummyTerm(rRet
);
802 rRet
.append(" rSup");
804 else if ((nVariation
== 1) ||
805 ((nVariation
== 2) && (nPart
==0)))
807 lcl_AppendDummyTerm(rRet
);
808 rRet
.append(" rSub");
814 rRet
.append(" {underline ");
815 else if (nVariation
== 1)
816 rRet
.append(" {underline underline ");
821 rRet
.append(" {overline ");
822 else if (nVariation
== 1)
823 rRet
.append(" {overline overline ");
830 rRet
.append(" widevec ");//left arrow above
831 else if (nVariation
== 1)
832 rRet
.append(" widevec ");//left arrow below
840 rRet
.append(" widevec ");//right arrow above
841 else if (nVariation
== 1)
842 rRet
.append(" widevec ");//right arrow below
850 rRet
.append(" widevec ");//double arrow above
851 else if (nVariation
== 1)
852 rRet
.append(" widevec ");//double arrow below
859 if ((nVariation
== 3) || (nVariation
== 4))
860 rRet
.append(" lInt");
863 if ( (nVariation
!= 0) && (nVariation
!= 3))
865 sPush
= rRet
.makeStringAndClear();
868 if (((nVariation
== 1) ||
869 (nVariation
== 4)) && (nPart
==1))
870 rRet
.append(" rSub");
871 else if ((nVariation
== 2) && (nPart
==2))
872 rRet
.append(" rSup");
873 else if ((nVariation
== 2) && (nPart
==1))
874 rRet
.append(" rSub");
880 if ((nVariation
== 2) || (nVariation
== 3))
881 rRet
.append(" llInt");
883 rRet
.append(" iInt");
884 if ( (nVariation
!= 0) && (nVariation
!= 2))
886 sPush
= rRet
.makeStringAndClear();
889 if (((nVariation
== 1) ||
890 (nVariation
== 3)) && (nPart
==1))
891 rRet
.append(" rSub");
897 if ((nVariation
== 2) || (nVariation
== 3))
898 rRet
.append(" lllInt");
900 rRet
.append(" iiInt");
901 if ( (nVariation
!= 0) && (nVariation
!= 2))
903 sPush
= rRet
.makeStringAndClear();
906 if (((nVariation
== 1) ||
907 (nVariation
== 3)) && (nPart
==1))
908 rRet
.append(" rSub");
915 rRet
.append(" lInt");
918 sPush
= rRet
.makeStringAndClear();
920 if (((nVariation
== 1) ||
921 (nVariation
== 2)) && (nPart
==1))
922 rRet
.append(" cSub");
923 else if ((nVariation
== 0) && (nPart
==2))
924 rRet
.append(" cSup");
925 else if ((nVariation
== 0) && (nPart
==1))
926 rRet
.append(" cSub");
933 rRet
.append(" llInt");
935 rRet
.append(" iInt");
936 sPush
= rRet
.makeStringAndClear();
939 rRet
.append(" cSub");
946 rRet
.append(" lllInt");
948 rRet
.append(" iiInt");
949 sPush
= rRet
.makeStringAndClear();
952 rRet
.append(" cSub");
965 sPush
= rRet
.makeStringAndClear();
968 if ((nVariation
== 0) && (nPart
==1))
969 rRet
.append(" cSub");
970 else if ((nVariation
== 1) && (nPart
==2))
971 rRet
.append(" cSup");
972 else if ((nVariation
== 1) && (nPart
==1))
973 rRet
.append(" cSub");
980 sPush
= rRet
.makeStringAndClear();
982 if ((nVariation
== 0) && (nPart
==1))
983 rRet
.append(" rSub");
984 else if ((nVariation
== 1) && (nPart
==2))
985 rRet
.append(" rSup");
986 else if ((nVariation
== 1) && (nPart
==1))
987 rRet
.append(" rSub");
993 rRet
.append(" Prod");
996 sPush
= rRet
.makeStringAndClear();
999 if ((nVariation
== 0) && (nPart
==1))
1000 rRet
.append(" cSub");
1001 else if ((nVariation
== 1) && (nPart
==2))
1002 rRet
.append(" cSup");
1003 else if ((nVariation
== 1) && (nPart
==1))
1004 rRet
.append(" cSub");
1010 rRet
.append(" Prod");
1011 sPush
= rRet
.makeStringAndClear();
1013 if ((nVariation
== 0) && (nPart
==1))
1014 rRet
.append(" rSub");
1015 else if ((nVariation
== 1) && (nPart
==2))
1016 rRet
.append(" rSup");
1017 else if ((nVariation
== 1) && (nPart
==1))
1018 rRet
.append(" rSub");
1024 rRet
.append(" coProd");
1025 if (nVariation
!= 2)
1027 sPush
= rRet
.makeStringAndClear();
1030 if ((nVariation
== 0) && (nPart
==1))
1031 rRet
.append(" cSub");
1032 else if ((nVariation
== 1) && (nPart
==2))
1033 rRet
.append(" cSup");
1034 else if ((nVariation
== 1) && (nPart
==1))
1035 rRet
.append(" cSub");
1041 rRet
.append(" coProd");
1042 sPush
= rRet
.makeStringAndClear();
1044 if ((nVariation
== 0) && (nPart
==1))
1045 rRet
.append(" rSub");
1046 else if ((nVariation
== 1) && (nPart
==2))
1047 rRet
.append(" rSup");
1048 else if ((nVariation
== 1) && (nPart
==1))
1049 rRet
.append(" rSub");
1055 rRet
.append(" union"); //union
1056 if (nVariation
!= 2)
1058 sPush
= rRet
.makeStringAndClear();
1061 if ((nVariation
== 0) && (nPart
==1))
1062 rRet
.append(" cSub");
1063 else if ((nVariation
== 1) && (nPart
==2))
1064 rRet
.append(" cSup");
1065 else if ((nVariation
== 1) && (nPart
==1))
1066 rRet
.append(" cSub");
1072 rRet
.append(" union"); //union
1073 sPush
= rRet
.makeStringAndClear();
1075 if ((nVariation
== 0) && (nPart
==1))
1076 rRet
.append(" rSub");
1077 else if ((nVariation
== 1) && (nPart
==2))
1078 rRet
.append(" rSup");
1079 else if ((nVariation
== 1) && (nPart
==1))
1080 rRet
.append(" rSub");
1086 rRet
.append(" intersect"); //intersect
1087 if (nVariation
!= 2)
1089 sPush
= rRet
.makeStringAndClear();
1092 if ((nVariation
== 0) && (nPart
==1))
1093 rRet
.append(" cSub");
1094 else if ((nVariation
== 1) && (nPart
==2))
1095 rRet
.append(" cSup");
1096 else if ((nVariation
== 1) && (nPart
==1))
1097 rRet
.append(" cSub");
1103 rRet
.append(" intersect"); //intersect
1104 sPush
= rRet
.makeStringAndClear();
1106 if ((nVariation
== 0) && (nPart
==1))
1107 rRet
.append(" rSub");
1108 else if ((nVariation
== 1) && (nPart
==2))
1109 rRet
.append(" rSup");
1110 else if ((nVariation
== 1) && (nPart
==1))
1111 rRet
.append(" rSub");
1115 if ((nVariation
== 0) && (nPart
==1))
1116 rRet
.append(" cSup");
1117 else if ((nVariation
== 1) && (nPart
==1))
1118 rRet
.append(" cSub");
1119 else if ((nVariation
== 2) && (nPart
==1))
1120 rRet
.append(" cSub");
1121 else if ((nVariation
== 2) && (nPart
==2))
1122 rRet
.append(" cSup");
1126 if (nVariation
== 0)
1130 sPush
= rRet
.makeStringAndClear();
1134 if (nVariation
== 0)
1137 rRet
.append("alignr ");
1140 rRet
.append("\\lline ");
1141 if (nVariation
== 1)
1142 rRet
.append("overline ");
1150 sPush
= rRet
.makeStringAndClear();
1152 if ((nVariation
== 0) && (nPart
==0))
1153 rRet
.append(" rSup");
1154 else if ((nVariation
== 2) && (nPart
==1))
1155 rRet
.append(" rSup");
1156 else if ((nVariation
== 1) && (nPart
==0))
1157 rRet
.append(" rSub");
1158 else if ((nVariation
== 2) && (nPart
==0))
1159 rRet
.append(" rSub");
1165 sPush
= rRet
.makeStringAndClear();
1167 if ((nVariation
== 0) && (nPart
==0))
1168 rRet
.append(" cSup");
1169 else if ((nVariation
== 2) && (nPart
==1))
1170 rRet
.append(" cSup");
1171 else if ((nVariation
== 1) && (nPart
==0))
1172 rRet
.append(" cSub");
1173 else if ((nVariation
== 2) && (nPart
==0))
1174 rRet
.append(" cSub");
1179 rRet
.append("\"\"");
1180 if ((nVariation
== 0)
1181 || ((nVariation
== 2) && (nPart
==1)))
1182 rRet
.append(" lSup");
1183 else if ((nVariation
== 1)
1184 || ((nVariation
== 2) && (nPart
==0)))
1185 rRet
.append(" lSub");
1192 rRet
.append(" langle ");
1194 else if (nVariation
==1)
1196 rRet
.append(" \\langle ");
1199 else if (nVariation
==2)
1201 rRet
.append(" \\lline ");
1206 if (nVariation
== 0)
1207 rRet
.append(" widevec ");//left below
1208 else if (nVariation
== 1)
1209 rRet
.append(" widevec ");//right below
1210 else if (nVariation
== 2)
1211 rRet
.append(" widevec ");//double headed below
1215 if (nVariation
== 0)
1216 rRet
.append(" widevec ");//left above
1217 else if (nVariation
== 1)
1218 rRet
.append(" widevec ");//right above
1219 else if (nVariation
== 2)
1220 rRet
.append(" widevec ");//double headed above
1226 sal_Int16 nOldCurSize
=nCurSize
;
1227 sal_Int32 nSizeStartPos
= rRet
.getLength();
1228 HandleSize( nLSize
, nDSize
, nSetSize
);
1229 bRet
= HandleRecords( nLevel
+1 );
1233 sal_Int32 nI
= rRet
.lastIndexOf('{');
1236 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1237 if (rRet
[nI
] != ' ')
1248 else if (rRet
.getLength() > nSizeStartPos
)
1249 rRet
= rRet
.truncate(nSizeStartPos
);
1251 nCurSize
=nOldCurSize
;
1255 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1262 rRet
.append(" rangle ");
1263 else if (nVariation
==2)
1264 rRet
.append(" \\rangle ");
1268 rRet
.append(" right )");
1269 else if (nVariation
==2)
1273 if ((nVariation
==0) || (nVariation
==2))
1274 rRet
.append(" right rbrace ");
1276 rRet
.append(" right none ");
1280 rRet
.append(" right ]");
1281 else if (nVariation
==2)
1286 rRet
.append(" rline ");
1287 else if (nVariation
==2)
1288 rRet
.append(" \\rline ");
1292 rRet
.append(" rdline ");
1293 else if (nVariation
==2)
1294 rRet
.append(" \\rdline ");
1297 if (nVariation
== 0 || nVariation
& 0x02) // tvFENCE_R
1298 rRet
.append(" right rfloor ");
1300 rRet
.append(" right none ");
1304 rRet
.append(" rceil ");
1305 else if (nVariation
==2)
1306 rRet
.append(" \\rceil ");
1318 if (nVariation
== 1)
1323 sMainTerm
= rRet
.makeStringAndClear();
1325 else if (nPart
== 1)
1327 rRet
.insert(0, sPush
);
1328 rRet
.append(sMainTerm
);
1354 ((nVariation
== 2) || (nVariation
== 1)))
1358 sal_Int32 nI
= rRet
.lastIndexOf('{');
1361 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1362 if (rRet
[nI
] != ' ')
1373 else if (rRet
.getLength() > nSubSupStartPos
)
1374 rRet
= rRet
.truncate(nSubSupStartPos
);
1380 ((nVariation
== 2) || (nVariation
== 1)))
1408 rRet
.append("overbrace");
1417 rRet
.append("underbrace");
1424 else if ((nPart
==1) &&
1425 ((nVariation
== 2) || (nVariation
== 1)))
1432 if (nVariation
== 0)
1436 sMainTerm
= rRet
.makeStringAndClear();
1438 else if (nPart
== 1)
1440 rRet
.insert(0, sPush
);
1441 rRet
.append(" over ").append(sMainTerm
);
1458 rRet
.append("slash");
1461 rRet
.append("wideslash");
1480 if (nVariation
!= 2)
1482 sMainTerm
= rRet
.makeStringAndClear();
1486 else if ((nPart
== 1) && (nVariation
== 0))
1488 rRet
.insert(0, sPush
);
1489 rRet
.append(sMainTerm
);
1494 else if ((nPart
== 1) && (nVariation
== 1))
1496 else if ((nPart
== 2) && (nVariation
== 1))
1498 rRet
.insert(0, sPush
);
1499 rRet
.append(sMainTerm
);
1510 if ((nVariation
!= 0) && (nVariation
!= 3))
1512 sMainTerm
= rRet
.makeStringAndClear();
1516 else if ((nPart
== 1) &&
1517 ((nVariation
== 1) || (nVariation
==4)))
1519 rRet
.insert(0, sPush
);
1520 rRet
.append(sMainTerm
);
1525 else if ((nPart
== 1) && (nVariation
== 2))
1527 else if ((nPart
== 2) && (nVariation
== 2))
1529 rRet
.insert(0, sPush
);
1530 rRet
.append(sMainTerm
);
1542 if ((nVariation
!= 0) && (nVariation
!= 2))
1544 sMainTerm
= rRet
.makeStringAndClear();
1548 else if ((nPart
== 1) &&
1549 ((nVariation
== 1) || (nVariation
==3)))
1551 rRet
.insert(0, sPush
);
1552 rRet
.append(sMainTerm
);
1563 sMainTerm
= rRet
.makeStringAndClear();
1566 else if ((nPart
== 1) &&
1567 ((nVariation
== 1) || (nVariation
==2)))
1569 rRet
.insert(0, sPush
);
1570 rRet
.append(sMainTerm
);
1575 else if ((nPart
== 1) && (nVariation
== 0))
1577 else if ((nPart
== 2) && (nVariation
== 0))
1579 rRet
.insert(0, sPush
);
1580 rRet
.append(sMainTerm
);
1592 sMainTerm
= rRet
.makeStringAndClear();
1595 else if (nPart
== 1)
1597 rRet
.insert(0, sPush
);
1598 rRet
.append(sMainTerm
);
1610 ((nVariation
== 0) || (nVariation
== 1)))
1612 sMainTerm
= rRet
.makeStringAndClear();
1615 else if ((nPart
== 0) && (nVariation
== 2))
1617 else if ((nPart
== 1) && (nVariation
== 2))
1619 sMainTerm
= rRet
.makeStringAndClear();
1622 else if ((nPart
== 2) || ((nPart
== 1) &&
1623 (nVariation
== 0 || nVariation
== 1)))
1625 rRet
.insert(0, sPush
);
1626 rRet
.append(sMainTerm
);
1637 newline
--; //there is another term to arrive
1638 rRet
.append(" mline ");
1641 rRet
.append(" rangle ");
1643 else if (nVariation
==1)
1644 rRet
.append(" \\lline ");
1645 else if (nVariation
==2)
1646 rRet
.append(" \\rangle ");
1652 bSilent
= true; //Skip the optional brackets and/or
1653 //symbols that follow some of these
1654 //records. Foo Data.
1656 /*In matrices and piles we cannot separate equation
1657 *lines with the newline keyword*/
1666 bRet
= HandleChar( nTextStart
, nSetSize
, nLevel
, nTag
, nSelector
, nVariation
, bSilent
);
1671 bRet
= HandleTemplate( nLevel
, nSelector
, nVariation
, nLastTemplateBracket
);
1676 bRet
= HandlePile( nSetAlign
, nLevel
, nSelector
, nVariation
);
1677 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1682 bRet
= HandleMatrix( nLevel
, nSelector
, nVariation
);
1683 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1688 HandleEmblishments();
1691 pS
->ReadUChar( nTabStops
);
1692 for (i
=0;i
<nTabStops
;i
++)
1694 pS
->ReadUChar( nTabType
);
1695 pS
->ReadUInt16( nTabOffset
);
1697 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1702 pS
->ReadUChar( aFont
.nTface
);
1704 The typeface number is the negative (which makes it
1705 positive) of the typeface value (unbiased) that appears in
1706 CHAR records that might follow a given FONT record
1708 aFont
.nTface
= 128-aFont
.nTface
;
1709 pS
->ReadUChar( aFont
.nStyle
);
1710 aUserStyles
.insert(aFont
);
1715 pS
->ReadChar( nChar8
);
1736 while (nRecord
!= END
&& !pS
->eof());
1745 /*Simply determine if we are at the end of a record or the end of a line,
1746 *with fiddly logic to see if we are in a matrix or a pile or neither
1748 Note we cannot tell until after the event that this is the last entry
1749 of a pile, so we must strip the last separator of a pile after this
1750 is detected in the PILE handler
1752 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1753 int &rCurCol
,int &rCurRow
)
1758 if (rCurCol
== nMatrixCols
-1)
1760 if (rCurRow
!= nMatrixRows
-1)
1761 rRet
.append(" {} ##\n");
1762 if (nMatrixRows
!=-1)
1770 rRet
.append(" {} # ");
1771 if (nMatrixRows
!=-1)
1778 /* set the alignment of the following term, but starmath currently
1779 * cannot handle vertical alignment */
1780 void MathType::HandleAlign(sal_uInt8 nHorAlign
, int &rSetAlign
)
1786 rRet
.append("alignl {");
1789 rRet
.append("alignc {");
1792 rRet
.append("alignr {");
1798 /* set size of text, complexity due to overuse of signedness as a flag
1799 * indicator by mathtype file format*/
1800 bool MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1805 const sal_Int16 nDefaultSize
= 12;
1806 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1814 if (-nLstSize
/32 != nLastSize
)
1816 nLastSize
= nCurSize
;
1817 rRet
.append(" size ");
1818 rRet
.append(OUString::number(-nLstSize
/32));
1823 nCurSize
= -nLstSize
/32;
1828 /*sizetable should theoretically be filled with the default sizes
1829 *of the various font groupings matching starmaths equivalents
1830 in aTypeFaces, and a test would be done to see if the new font
1831 size would be the same as what starmath would have chosen for
1832 itself anyway in which case the size setting could be ignored*/
1833 nLstSize
= aSizeTable
.at(nLstSize
);
1834 nLstSize
= nLstSize
+ nDefSize
;
1835 if (nLstSize
!= nCurSize
)
1843 if (nLstSize
!= nLastSize
)
1845 nLastSize
= nCurSize
;
1846 rRet
.append(" size ");
1847 rRet
.append(OUString::number(nLstSize
));
1852 nCurSize
= nLstSize
;
1858 bool MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1863 SvStream
*pStream
= rMedium
.GetOutStream();
1866 tools::SvRef
<SotStorage
> pStor
= new SotStorage( pStream
, false );
1868 SvGlobalName
aGName(MSO_EQUATION3_CLASSID
);
1869 pStor
->SetClass( aGName
, SotClipboardFormatId::NONE
, "Microsoft Equation 3.0");
1871 static sal_uInt8
const aCompObj
[] = {
1872 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1873 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1874 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1875 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1876 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1877 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1878 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1879 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1880 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1881 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1882 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1883 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1886 tools::SvRef
<SotStorageStream
> xStor( pStor
->OpenSotStream("\1CompObj"));
1887 xStor
->WriteBytes(aCompObj
, sizeof(aCompObj
));
1889 static sal_uInt8
const aOle
[] = {
1890 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00
1894 tools::SvRef
<SotStorageStream
> xStor2( pStor
->OpenSotStream("\1Ole"));
1895 xStor2
->WriteBytes(aOle
, sizeof(aOle
));
1899 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream("Equation Native");
1900 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
1904 pS
->SetEndian( SvStreamEndian::LITTLE
);
1906 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1907 pS
->WriteUChar( 0x03 );
1908 pS
->WriteUChar( 0x01 );
1909 pS
->WriteUChar( 0x01 );
1910 pS
->WriteUChar( 0x03 );
1911 pS
->WriteUChar( 0x00 );
1912 sal_uInt32 nSize
= pS
->Tell();
1913 nPendingAttributes
=0;
1915 HandleNodes(pTree
, 0);
1916 pS
->WriteUChar( END
);
1918 nSize
= pS
->Tell()-nSize
;
1920 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1930 void MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1932 switch(pNode
->GetType())
1934 case SmNodeType::Attribut
:
1935 HandleAttributes(pNode
,nLevel
);
1937 case SmNodeType::Text
:
1940 case SmNodeType::VerticalBrace
:
1941 HandleVerticalBrace(pNode
,nLevel
);
1943 case SmNodeType::Brace
:
1944 HandleBrace(pNode
,nLevel
);
1946 case SmNodeType::Oper
:
1947 HandleOperator(pNode
,nLevel
);
1949 case SmNodeType::BinVer
:
1950 HandleFractions(pNode
,nLevel
);
1952 case SmNodeType::Root
:
1953 HandleRoot(pNode
,nLevel
);
1955 case SmNodeType::Special
:
1957 SmTextNode
*pText
= static_cast<SmTextNode
*>(pNode
);
1958 //if the token str and the result text are the same then this
1959 //is to be seen as text, else assume it's a mathchar
1960 if (pText
->GetText() == pText
->GetToken().aText
)
1966 case SmNodeType::Math
:
1967 case SmNodeType::MathIdent
:
1970 case SmNodeType::SubSup
:
1971 HandleSubSupScript(pNode
,nLevel
);
1973 case SmNodeType::Expression
:
1975 size_t nSize
= pNode
->GetNumSubNodes();
1976 for (size_t i
= 0; i
< nSize
; ++i
)
1978 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1979 HandleNodes(pTemp
,nLevel
+1);
1983 case SmNodeType::Table
:
1984 //Root Node, PILE equivalent, i.e. vertical stack
1985 HandleTable(pNode
,nLevel
);
1987 case SmNodeType::Matrix
:
1988 HandleSmMatrix(static_cast<SmMatrixNode
*>(pNode
),nLevel
);
1990 case SmNodeType::Line
:
1992 pS
->WriteUChar( 0x0a );
1993 pS
->WriteUChar( LINE
);
1994 size_t nSize
= pNode
->GetNumSubNodes();
1995 for (size_t i
= 0; i
< nSize
; ++i
)
1997 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1998 HandleNodes(pTemp
,nLevel
+1);
2000 pS
->WriteUChar( END
);
2003 case SmNodeType::Align
:
2004 HandleMAlign(pNode
,nLevel
);
2006 case SmNodeType::Blank
:
2007 pS
->WriteUChar( CHAR
);
2008 pS
->WriteUChar( 0x98 );
2009 if (pNode
->GetToken().eType
== TSBLANK
)
2010 pS
->WriteUInt16( 0xEB04 );
2012 pS
->WriteUInt16( 0xEB05 );
2016 size_t nSize
= pNode
->GetNumSubNodes();
2017 for (size_t i
= 0; i
< nSize
; ++i
)
2019 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2020 HandleNodes(pTemp
,nLevel
+1);
2028 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2030 int nOldPending
=nPendingAttributes
;
2031 pS
->WriteUChar( TMPL
); //Template
2032 pS
->WriteUChar( nSelector
); //selector
2033 pS
->WriteUChar( nVariation
); //variation
2034 pS
->WriteUChar( 0x00 ); //options
2035 pS
->WriteUChar( LINE
);
2036 //there's just no way we can now handle any character
2037 //attributes (from mathtypes perspective) centered
2038 //over an expression but above template attribute
2039 //such as widevec and similar constructs
2040 //we have to drop them
2041 nPendingAttributes
=0;
2045 void MathType::EndTemplate(int nOldPendingAttributes
)
2047 pS
->WriteUChar( END
); //end line
2048 pS
->WriteUChar( END
); //end template
2049 nPendingAttributes
=nOldPendingAttributes
;
2053 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2055 pS
->WriteUChar( MATRIX
);
2056 pS
->WriteUChar( 0x00 ); //vAlign ?
2057 pS
->WriteUChar( 0x00 ); //h_just
2058 pS
->WriteUChar( 0x00 ); //v_just
2059 pS
->WriteUChar( pMatrix
->GetNumRows() ); //v_just
2060 pS
->WriteUChar( pMatrix
->GetNumCols() ); //v_just
2061 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2062 if (((pMatrix
->GetNumRows()+1)*2)%8)
2064 for (int j
= 0; j
< nBytes
; j
++)
2065 pS
->WriteUChar( 0x00 ); //row_parts
2066 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2067 if (((pMatrix
->GetNumCols()+1)*2)%8)
2069 for (int k
= 0; k
< nBytes
; k
++)
2070 pS
->WriteUChar( 0x00 ); //col_parts
2071 size_t nSize
= pMatrix
->GetNumSubNodes();
2072 for (size_t i
= 0; i
< nSize
; ++i
)
2074 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2076 pS
->WriteUChar( LINE
); //line
2077 HandleNodes(pTemp
,nLevel
+1);
2078 pS
->WriteUChar( END
); //end line
2081 pS
->WriteUChar( END
);
2085 //Root Node, PILE equivalent, i.e. vertical stack
2086 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2088 size_t nSize
= pNode
->GetNumSubNodes();
2089 //The root of the starmath is a table, if
2090 //we convert this them each iteration of
2091 //conversion from starmath to mathtype will
2092 //add an extra unnecessary level to the
2093 //mathtype output stack which would grow
2094 //without bound in a multi step conversion
2097 pS
->WriteUChar( 0x0A ); //initial size
2099 if ( nLevel
|| (nSize
>1))
2101 pS
->WriteUChar( PILE
);
2102 pS
->WriteUChar( nHAlign
); //vAlign ?
2103 pS
->WriteUChar( 0x01 ); //hAlign
2106 for (size_t i
= 0; i
< nSize
; ++i
)
2108 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2110 pS
->WriteUChar( LINE
);
2111 HandleNodes(pTemp
,nLevel
+1);
2112 pS
->WriteUChar( END
);
2115 if (nLevel
|| (nSize
>1))
2116 pS
->WriteUChar( END
);
2120 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2123 pS
->WriteUChar( TMPL
); //Template
2124 pS
->WriteUChar( 0x0D ); //selector
2125 if (pNode
->GetSubNode(0))
2126 pS
->WriteUChar( 0x01 ); //variation
2128 pS
->WriteUChar( 0x00 ); //variation
2129 pS
->WriteUChar( 0x00 ); //options
2131 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2133 pS
->WriteUChar( LINE
); //line
2134 HandleNodes(pTemp
,nLevel
+1);
2135 pS
->WriteUChar( END
);
2138 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2140 pS
->WriteUChar( LINE
); //line
2141 HandleNodes(pTemp
,nLevel
+1);
2142 pS
->WriteUChar( END
);
2145 pS
->WriteUChar( LINE
|0x10 ); //dummy line
2148 pS
->WriteUChar( END
);
2151 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2152 sal_uInt64
*pPos
,bool bTest
)
2154 sal_uInt8 nVariation2
=0xff;
2156 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2159 if (pNode
->GetSubNode(CSUB
+1))
2162 else if (pNode
->GetSubNode(CSUB
+1))
2165 if (nVariation2
!=0xff)
2169 pS
->WriteUChar( TMPL
); //Template
2170 pS
->WriteUChar( 0x2B ); //selector
2171 pS
->WriteUChar( nVariation2
);
2172 pS
->WriteUChar( 0x00 ); //options
2176 pS
->WriteUChar( LINE
); //line
2177 HandleNodes(pContent
,nLevel
+1);
2178 pS
->WriteUChar( END
); //line
2181 pS
->WriteUChar( LINE
|0x10 );
2183 pS
->WriteUChar( 0x0B );
2186 if (nullptr != (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2188 pS
->WriteUChar( LINE
); //line
2189 HandleNodes(pTemp
,nLevel
+1);
2190 pS
->WriteUChar( END
); //line
2193 pS
->WriteUChar( LINE
|0x10 );
2194 if (bTest
&& nullptr != (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2196 pS
->WriteUChar( LINE
); //line
2197 HandleNodes(pTemp
,nLevel
+1);
2198 pS
->WriteUChar( END
); //line
2201 pS
->WriteUChar( LINE
|0x10 );
2208 Sub and Sup scripts and another problem area, StarMath
2209 can have all possible options used at the same time, whereas
2210 Mathtype cannot. The ordering of the nodes for each system
2211 is quite different as well leading to some complexity
2213 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2215 sal_uInt8 nVariation
=0xff;
2216 if (pNode
->GetSubNode(LSUP
+1))
2219 if (pNode
->GetSubNode(LSUB
+1))
2222 else if ( nullptr != pNode
->GetSubNode(LSUB
+1) )
2226 if (nVariation
!=0xff)
2228 pS
->WriteUChar( TMPL
); //Template
2229 pS
->WriteUChar( 0x2c ); //selector
2230 pS
->WriteUChar( nVariation
);
2231 pS
->WriteUChar( 0x00 ); //options
2232 pS
->WriteUChar( 0x0B );
2234 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2236 pS
->WriteUChar( LINE
); //line
2237 HandleNodes(pTemp
,nLevel
+1);
2238 pS
->WriteUChar( END
); //line
2241 pS
->WriteUChar( LINE
|0x10 );
2242 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2244 pS
->WriteUChar( LINE
); //line
2245 HandleNodes(pTemp
,nLevel
+1);
2246 pS
->WriteUChar( END
); //line
2249 pS
->WriteUChar( LINE
|0x10 );
2250 pS
->WriteUChar( END
);
2255 sal_uInt8 nVariation2
=HandleCScript(pNode
,nullptr,nLevel
);
2257 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2259 HandleNodes(pTemp
,nLevel
+1);
2262 if (nVariation2
!= 0xff)
2263 pS
->WriteUChar( END
);
2265 if (nullptr != (pNode
->GetSubNode(RSUP
+1)))
2268 if (pNode
->GetSubNode(RSUB
+1))
2271 else if (nullptr != pNode
->GetSubNode(RSUB
+1))
2274 if (nVariation
!=0xff)
2276 pS
->WriteUChar( TMPL
); //Template
2277 pS
->WriteUChar( 0x0F ); //selector
2278 pS
->WriteUChar( nVariation
);
2279 pS
->WriteUChar( 0x00 ); //options
2280 pS
->WriteUChar( 0x0B );
2282 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2284 pS
->WriteUChar( LINE
); //line
2285 HandleNodes(pTemp
,nLevel
+1);
2286 pS
->WriteUChar( END
); //line
2289 pS
->WriteUChar( LINE
|0x10 );
2290 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2292 pS
->WriteUChar( LINE
); //line
2293 HandleNodes(pTemp
,nLevel
+1);
2294 pS
->WriteUChar( END
); //line
2297 pS
->WriteUChar( LINE
|0x10 );
2298 pS
->WriteUChar( END
); //line
2301 //After subscript mathtype will keep the size of
2302 //normal text at the subscript size, sigh.
2303 pS
->WriteUChar( 0x0A );
2307 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2310 pS
->WriteUChar( TMPL
); //Template
2311 pS
->WriteUChar( 0x0E ); //selector
2312 pS
->WriteUChar( 0x00 ); //variation
2313 pS
->WriteUChar( 0x00 ); //options
2315 pS
->WriteUChar( 0x0A );
2316 pS
->WriteUChar( LINE
); //line
2317 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2318 HandleNodes(pTemp
,nLevel
+1);
2319 pS
->WriteUChar( END
);
2321 pS
->WriteUChar( 0x0A );
2322 pS
->WriteUChar( LINE
); //line
2323 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2324 HandleNodes(pTemp
,nLevel
+1);
2325 pS
->WriteUChar( END
);
2327 pS
->WriteUChar( END
);
2331 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2334 SmNode
*pLeft
=pNode
->GetSubNode(0);
2335 SmNode
*pRight
=pNode
->GetSubNode(2);
2337 pS
->WriteUChar( TMPL
); //Template
2338 bIsReInterpBrace
=false;
2339 sal_uInt8 nBSpec
=0x10;
2340 auto nLoc
= pS
->Tell();
2343 switch (pLeft
->GetToken().eType
)
2346 pS
->WriteUChar( tmANGLE
); //selector
2347 pS
->WriteUChar( 0 ); //variation
2348 pS
->WriteUChar( 0 ); //options
2351 pS
->WriteUChar( tmBRACE
); //selector
2352 pS
->WriteUChar( 0 ); //variation
2353 pS
->WriteUChar( 0 ); //options
2357 pS
->WriteUChar( tmBRACK
); //selector
2358 pS
->WriteUChar( 0 ); //variation
2359 pS
->WriteUChar( 0 ); //options
2363 pS
->WriteUChar( tmFLOOR
); //selector
2364 pS
->WriteUChar( 0 ); //variation
2365 pS
->WriteUChar( 0 ); //options
2368 pS
->WriteUChar( tmBAR
); //selector
2369 pS
->WriteUChar( 0 ); //variation
2370 pS
->WriteUChar( 0 ); //options
2374 pS
->WriteUChar( tmDBAR
); //selector
2375 pS
->WriteUChar( 0 ); //variation
2376 pS
->WriteUChar( 0 ); //options
2379 pS
->WriteUChar( tmPAREN
); //selector
2380 pS
->WriteUChar( 0 ); //variation
2381 pS
->WriteUChar( 0 ); //options
2387 if (nullptr != (pTemp
= pNode
->GetSubNode(1)))
2389 pS
->WriteUChar( LINE
); //line
2390 HandleNodes(pTemp
,nLevel
+1);
2391 pS
->WriteUChar( END
); //options
2395 HandleNodes(pLeft
,nLevel
+1);
2396 if (bIsReInterpBrace
)
2398 auto nLoc2
= pS
->Tell();
2400 pS
->WriteUChar( 0x2D );
2402 pS
->WriteUChar( CHAR
);
2403 pS
->WriteUChar( 0x96 );
2404 pS
->WriteUInt16( 0xEC07 );
2405 bIsReInterpBrace
=false;
2408 HandleNodes(pRight
,nLevel
+1);
2410 pS
->WriteUChar( END
);
2414 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2417 pS
->WriteUChar( TMPL
); //Template
2418 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2419 pS
->WriteUChar( tmLHBRACE
); //selector
2421 pS
->WriteUChar( tmUHBRACE
); //selector
2422 pS
->WriteUChar( 0 ); //variation
2423 pS
->WriteUChar( 0 ); //options
2425 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2427 pS
->WriteUChar( LINE
); //line
2428 HandleNodes(pTemp
,nLevel
+1);
2429 pS
->WriteUChar( END
); //options
2432 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2434 pS
->WriteUChar( LINE
); //line
2435 HandleNodes(pTemp
,nLevel
+1);
2436 pS
->WriteUChar( END
); //options
2438 pS
->WriteUChar( END
);
2441 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2443 if (HandleLim(pNode
,nLevel
))
2447 sal_uInt8 nVariation
;
2449 switch (pNode
->GetToken().eType
)
2456 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2457 pNode
->GetSubNode(1),nLevel
,&nPos
,false);
2460 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2461 pNode
->GetSubNode(1),nLevel
,&nPos
);
2465 sal_uInt8 nOldVariation
=nVariation
;
2466 sal_uInt8 nIntVariation
=nVariation
;
2469 if (nVariation
!= 0xff)
2473 if (nVariation
== 2)
2478 else if (nVariation
== 0)
2480 else if (nVariation
== 1)
2488 pS
->WriteUChar( TMPL
);
2489 switch(pNode
->GetToken().eType
)
2493 if (nOldVariation
!= 0xff)
2494 pS
->WriteUChar( 0x18 ); //selector
2496 pS
->WriteUChar( 0x15 ); //selector
2497 pS
->WriteUChar( nIntVariation
); //variation
2500 if (nOldVariation
!= 0xff)
2502 pS
->WriteUChar( 0x19 );
2503 pS
->WriteUChar( 0x01 );
2507 pS
->WriteUChar( 0x16 );
2508 pS
->WriteUChar( 0x00 );
2512 if (nOldVariation
!= 0xff)
2514 pS
->WriteUChar( 0x1a );
2515 pS
->WriteUChar( 0x01 );
2519 pS
->WriteUChar( 0x17 );
2520 pS
->WriteUChar( 0x00 );
2524 if (nOldVariation
!= 0xff)
2526 pS
->WriteUChar( 0x18 );
2527 pS
->WriteUChar( 0x02 );
2531 pS
->WriteUChar( 0x15 );
2532 pS
->WriteUChar( 0x03 );
2536 if (nOldVariation
!= 0xff)
2538 pS
->WriteUChar( 0x19 );
2539 pS
->WriteUChar( 0x00 );
2543 pS
->WriteUChar( 0x16 );
2544 pS
->WriteUChar( 0x02 );
2548 if (nOldVariation
!= 0xff)
2550 pS
->WriteUChar( 0x1a );
2551 pS
->WriteUChar( 0x00 );
2555 pS
->WriteUChar( 0x17 );
2556 pS
->WriteUChar( 0x02 );
2561 pS
->WriteUChar( 0x1d );
2562 pS
->WriteUChar( nVariation
);
2565 pS
->WriteUChar( 0x1f );
2566 pS
->WriteUChar( nVariation
);
2569 pS
->WriteUChar( 0x21 );
2570 pS
->WriteUChar( nVariation
);
2573 pS
->WriteUChar( 0 ); //options
2579 pS
->WriteUChar( LINE
); //line
2580 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2581 pS
->WriteUChar( END
); //line
2582 pS
->WriteUChar( LINE
|0x10 );
2583 pS
->WriteUChar( LINE
|0x10 );
2586 pS
->WriteUChar( 0x0D );
2587 switch(pNode
->GetToken().eType
)
2591 pS
->WriteUChar( CHAR
);
2592 pS
->WriteUChar( 0x86 );
2593 pS
->WriteUInt16( 0x2211 );
2596 pS
->WriteUChar( CHAR
);
2597 pS
->WriteUChar( 0x86 );
2598 pS
->WriteUInt16( 0x220F );
2601 pS
->WriteUChar( CHAR
);
2602 pS
->WriteUChar( 0x8B );
2603 pS
->WriteUInt16( 0x2210 );
2607 pS
->WriteUChar( CHAR
);
2608 pS
->WriteUChar( 0x86 );
2609 pS
->WriteUInt16( 0x222B );
2613 pS
->WriteUChar( CHAR
);
2614 pS
->WriteUChar( 0x86 );
2615 pS
->WriteUInt16( 0x222B );
2620 pS
->WriteUChar( CHAR
);
2621 pS
->WriteUChar( 0x86 );
2622 pS
->WriteUInt16( 0x222B );
2625 pS
->WriteUChar( END
);
2626 pS
->WriteUChar( 0x0A );
2630 bool MathType::HandlePile(int &rSetAlign
, int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2633 pS
->ReadUChar( nHAlign
);
2634 pS
->ReadUChar( nVAlign
);
2636 HandleAlign(nHAlign
, rSetAlign
);
2638 rRet
.append(" stack {\n");
2639 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, -1, -1 );
2640 int nRemoveFrom
= rRet
.getLength() >= 3 ? rRet
.getLength() - 3 : 0;
2641 rRet
.remove(nRemoveFrom
, 2);
2652 bool MathType::HandleMatrix(int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2654 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
,nVAlign
;
2655 pS
->ReadUChar( nVAlign
);
2656 pS
->ReadUChar( nH_just
);
2657 pS
->ReadUChar( nV_just
);
2658 pS
->ReadUChar( nRows
);
2659 pS
->ReadUChar( nCols
);
2660 int nBytes
= ((nRows
+1)*2)/8;
2661 if (((nRows
+1)*2)%8)
2663 pS
->SeekRel(nBytes
);
2664 nBytes
= ((nCols
+1)*2)/8;
2665 if (((nCols
+1)*2)%8)
2667 pS
->SeekRel(nBytes
);
2668 rRet
.append(" matrix {\n");
2669 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, nRows
, nCols
);
2671 sal_Int32 nI
= rRet
.lastIndexOf('#');
2673 if (rRet
[nI
-1] != '#') //missing column
2676 rRet
.append("\n} ");
2680 bool MathType::HandleTemplate(int nLevel
, sal_uInt8
&rSelector
,
2681 sal_uInt8
&rVariation
, sal_Int32
&rLastTemplateBracket
)
2683 sal_uInt8 nOption
; //This appears utterly unused
2684 pS
->ReadUChar( rSelector
);
2685 pS
->ReadUChar( rVariation
);
2686 pS
->ReadUChar( nOption
);
2687 OSL_ENSURE(rSelector
< 48,"Selector out of range");
2688 if ((rSelector
>= 21) && (rSelector
<=26))
2690 OSL_ENSURE(nOption
< 2,"Option out of range");
2692 else if (rSelector
<= 12)
2694 OSL_ENSURE(nOption
< 3,"Option out of range");
2697 //For the (broken) case where one subscript template ends, and there is
2698 //another one after it, mathtype handles it as if the second one was
2699 //inside the first one and renders it as sub of sub
2701 if ( (rSelector
== 0xf) && (rLastTemplateBracket
!= -1) )
2704 for (sal_Int32 nI
= rLastTemplateBracket
+1; nI
< rRet
.getLength(); nI
++ )
2705 if (rRet
[nI
] != ' ')
2713 bool bRet
= HandleRecords( nLevel
+1, rSelector
, rVariation
);
2717 if (rLastTemplateBracket
< rRet
.getLength())
2718 rRet
.remove(rLastTemplateBracket
, 1);
2720 rLastTemplateBracket
= -1;
2722 if (rSelector
== 0xf)
2723 rLastTemplateBracket
= rRet
.lastIndexOf('}');
2725 rLastTemplateBracket
= -1;
2727 rSelector
= sal::static_int_cast
< sal_uInt8
>(-1);
2731 void MathType::HandleEmblishments()
2736 pS
->ReadUChar( nEmbel
);
2742 rRet
.append(" dot ");
2745 rRet
.append(" ddot ");
2748 rRet
.append(" dddot ");
2753 sPost
.append(" sup {}");
2754 nPostSup
= sPost
.getLength();
2756 sPost
.insert(nPostSup
-1," ' ");
2762 sPost
.append(" sup {}");
2763 nPostSup
= sPost
.getLength();
2765 sPost
.insert(nPostSup
-1," '' ");
2771 sPost
.append(" lsup {}");
2772 nPostlSup
= sPost
.getLength();
2774 sPost
.insert(nPostlSup
-1," ' ");
2778 rRet
.append(" tilde ");
2781 rRet
.append(" hat ");
2784 rRet
.append(" vec ");
2787 rRet
.append(" overstrike ");
2790 rRet
.append(" bar ");
2795 sPost
.append(" sup {}");
2796 nPostSup
= sPost
.getLength();
2798 sPost
.insert(nPostSup
-1," ''' ");
2802 rRet
.append(" breve ");
2805 OSL_ENSURE(nEmbel
< 21,"Embel out of range");
2813 void MathType::HandleSetSize()
2816 pS
->ReadUChar(nTemp
);
2820 pS
->ReadInt16( nLSize
);
2824 pS
->ReadUChar( nTemp
);
2826 pS
->ReadInt16( nDSize
);
2830 pS
->ReadUChar( nTemp
);
2836 bool MathType::HandleChar(sal_Int32
&rTextStart
, int &rSetSize
, int nLevel
,
2837 sal_uInt8 nTag
, sal_uInt8 nSelector
, sal_uInt8 nVariation
, bool bSilent
)
2839 sal_Unicode
nChar(0);
2844 //This is a candidate for function recognition, whatever
2848 sal_uInt8 nOldTypeFace
= nTypeFace
;
2849 pS
->ReadUChar( nTypeFace
);
2852 sal_uInt8
nChar8(0);
2853 pS
->ReadUChar( nChar8
);
2857 pS
->ReadUtf16( nChar
);
2860 bad character, old mathtype < 3 has these
2867 //A bit tricky, the character emblishments for
2868 //mathtype can all be listed after each other, in
2869 //starmath some must go before the character and some
2870 //must go after. In addition some of the emblishments
2871 //may repeated and in starmath some of these groups
2872 //must be gathered together. sPost is the portion that
2873 //follows the char and nPostSup and nPostlSup are the
2874 //indexes at which this class of emblishment is
2877 nPostSup
= nPostlSup
= 0;
2878 int nOriglen
=rRet
.getLength()-rTextStart
;
2879 rRet
.append(" {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2880 if ((!bSilent
) && (nOriglen
> 1))
2882 bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
);
2888 TypeFaceToString(aStr
,nOldTypeFace
);
2890 rRet
.insert(std::min(rTextStart
, rRet
.getLength()), aStr
);
2893 TypeFaceToString(aStr
,nTypeFace
);
2894 rRet
.append(aStr
).append("{");
2898 rTextStart
= rRet
.getLength();
2904 sal_Int32 nOldLen
= rRet
.getLength();
2906 HandleSize(nLSize
,nDSize
,rSetSize
) ||
2907 (nOldTypeFace
!= nTypeFace
)
2910 if ((nOldLen
- rTextStart
) > 1)
2912 rRet
.insert(nOldLen
, "\"");
2914 TypeFaceToString(aStr
,nOldTypeFace
);
2916 rRet
.insert(rTextStart
,aStr
);
2918 rTextStart
= rRet
.getLength();
2920 nOldLen
= rRet
.getLength();
2921 if (!LookupChar(nChar
,rRet
,nVersion
,nTypeFace
))
2923 if (nOldLen
- rTextStart
> 1)
2925 rRet
.insert(nOldLen
, "\"");
2927 TypeFaceToString(aStr
,nOldTypeFace
);
2929 rRet
.insert(rTextStart
, aStr
);
2931 rTextStart
= rRet
.getLength();
2933 lcl_PrependDummyTerm(rRet
, rTextStart
);
2936 if ((xfEMBELL(nTag
)) && (!bSilent
))
2938 rRet
.append("}}").append(sPost
); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2939 rTextStart
= rRet
.getLength();
2944 bool MathType::HandleLim(SmNode
*pNode
,int nLevel
)
2947 //Special case for the "lim" option in StarMath
2948 if ((pNode
->GetToken().eType
== TLIM
)
2949 || (pNode
->GetToken().eType
== TLIMSUP
)
2950 || (pNode
->GetToken().eType
== TLIMINF
)
2953 if (pNode
->GetSubNode(1))
2955 sal_uInt8 nVariation2
=HandleCScript(pNode
->GetSubNode(0),nullptr,
2958 pS
->WriteUChar( 0x0A );
2959 pS
->WriteUChar( LINE
); //line
2960 pS
->WriteUChar( CHAR
|0x10 );
2961 pS
->WriteUChar( 0x82 );
2962 pS
->WriteUInt16( 'l' );
2963 pS
->WriteUChar( CHAR
|0x10 );
2964 pS
->WriteUChar( 0x82 );
2965 pS
->WriteUInt16( 'i' );
2966 pS
->WriteUChar( CHAR
|0x10 );
2967 pS
->WriteUChar( 0x82 );
2968 pS
->WriteUInt16( 'm' );
2970 if (pNode
->GetToken().eType
== TLIMSUP
)
2972 pS
->WriteUChar( CHAR
); //some space
2973 pS
->WriteUChar( 0x98 );
2974 pS
->WriteUInt16( 0xEB04 );
2976 pS
->WriteUChar( CHAR
|0x10 );
2977 pS
->WriteUChar( 0x82 );
2978 pS
->WriteUInt16( 's' );
2979 pS
->WriteUChar( CHAR
|0x10 );
2980 pS
->WriteUChar( 0x82 );
2981 pS
->WriteUInt16( 'u' );
2982 pS
->WriteUChar( CHAR
|0x10 );
2983 pS
->WriteUChar( 0x82 );
2984 pS
->WriteUInt16( 'p' );
2986 else if (pNode
->GetToken().eType
== TLIMINF
)
2988 pS
->WriteUChar( CHAR
); //some space
2989 pS
->WriteUChar( 0x98 );
2990 pS
->WriteUInt16( 0xEB04 );
2992 pS
->WriteUChar( CHAR
|0x10 );
2993 pS
->WriteUChar( 0x82 );
2994 pS
->WriteUInt16( 'i' );
2995 pS
->WriteUChar( CHAR
|0x10 );
2996 pS
->WriteUChar( 0x82 );
2997 pS
->WriteUInt16( 'n' );
2998 pS
->WriteUChar( CHAR
|0x10 );
2999 pS
->WriteUChar( 0x82 );
3000 pS
->WriteUInt16( 'f' );
3004 pS
->WriteUChar( CHAR
); //some space
3005 pS
->WriteUChar( 0x98 );
3006 pS
->WriteUInt16( 0xEB04 );
3008 if (nVariation2
!= 0xff)
3010 pS
->WriteUChar( END
);
3011 pS
->WriteUChar( END
);
3013 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
3020 void MathType::HandleMAlign(SmNode
*pNode
,int nLevel
)
3022 sal_uInt8 nPushedHAlign
=nHAlign
;
3023 switch(pNode
->GetToken().eType
)
3035 size_t nSize
= pNode
->GetNumSubNodes();
3036 for (size_t i
= 0; i
< nSize
; ++i
)
3038 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
3039 HandleNodes(pTemp
,nLevel
+1);
3041 nHAlign
=nPushedHAlign
;
3044 void MathType::HandleMath(SmNode
*pNode
)
3046 if (pNode
->GetToken().eType
== TMLINE
)
3048 pS
->WriteUChar( END
);
3049 pS
->WriteUChar( LINE
);
3050 bIsReInterpBrace
=true;
3053 SmMathSymbolNode
*pTemp
= static_cast<SmMathSymbolNode
*>(pNode
);
3054 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3056 sal_Unicode nArse
= SmTextNode::ConvertSymbolToUnicode(pTemp
->GetText()[i
]);
3057 if ((nArse
== 0x2224) || (nArse
== 0x2288) || (nArse
== 0x2285) ||
3060 pS
->WriteUChar( CHAR
|0x20 );
3062 else if (nPendingAttributes
&&
3063 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3065 pS
->WriteUChar( 0x22 );
3068 pS
->WriteUChar( CHAR
); //char without formula recognition
3069 //The typeface seems to be MTEXTRA for unicode characters,
3070 //though how to determine when mathtype chooses one over
3071 //the other is unknown. This should do the trick
3074 if ( (nArse
== 0x2213) || (nArse
== 0x2218) ||
3075 (nArse
== 0x210F) || (
3076 (nArse
>= 0x22EE) && (nArse
<= 0x22FF)
3079 nBias
= 0xB; //typeface
3081 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3082 nBias
= 0x2; //typeface
3083 else if ((nArse
> 0x2000) || (nArse
== 0x00D7))
3084 nBias
= 0x6; //typeface
3085 else if (nArse
== 0x3d1)
3087 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3088 nBias
= 0xB; //typeface
3090 nBias
= 0x3; //typeface
3092 pS
->WriteUChar( nSpec
+nBias
+128 ); //typeface
3094 if (nArse
== 0x2224)
3096 pS
->WriteUInt16( 0x7C );
3097 pS
->WriteUChar( EMBEL
);
3098 pS
->WriteUChar( 0x0A );
3099 pS
->WriteUChar( END
); //end embel
3100 pS
->WriteUChar( END
); //end embel
3102 else if (nArse
== 0x2225)
3103 pS
->WriteUInt16( 0xEC09 );
3104 else if (nArse
== 0xE421)
3105 pS
->WriteUInt16( 0x2265 );
3106 else if (nArse
== 0x230A)
3107 pS
->WriteUInt16( 0xF8F0 );
3108 else if (nArse
== 0x230B)
3109 pS
->WriteUInt16( 0xF8FB );
3110 else if (nArse
== 0xE425)
3111 pS
->WriteUInt16( 0x2264 );
3112 else if (nArse
== 0x226A)
3114 pS
->WriteUInt16( 0x3C );
3115 pS
->WriteUChar( CHAR
);
3116 pS
->WriteUChar( 0x98 );
3117 pS
->WriteUInt16( 0xEB01 );
3118 pS
->WriteUChar( CHAR
);
3119 pS
->WriteUChar( 0x86 );
3120 pS
->WriteUInt16( 0x3c );
3122 else if (nArse
== 0x2288)
3124 pS
->WriteUInt16( 0x2286 );
3125 pS
->WriteUChar( EMBEL
);
3126 pS
->WriteUChar( 0x0A );
3127 pS
->WriteUChar( END
); //end embel
3128 pS
->WriteUChar( END
); //end embel
3130 else if (nArse
== 0x2289)
3132 pS
->WriteUInt16( 0x2287 );
3133 pS
->WriteUChar( EMBEL
);
3134 pS
->WriteUChar( 0x0A );
3135 pS
->WriteUChar( END
); //end embel
3136 pS
->WriteUChar( END
); //end embel
3138 else if (nArse
== 0x2285)
3140 pS
->WriteUInt16( 0x2283 );
3141 pS
->WriteUChar( EMBEL
);
3142 pS
->WriteUChar( 0x0A );
3143 pS
->WriteUChar( END
); //end embel
3144 pS
->WriteUChar( END
); //end embel
3147 pS
->WriteUInt16( nArse
);
3149 nPendingAttributes
= 0;
3152 void MathType::HandleAttributes(SmNode
*pNode
,int nLevel
)
3154 int nOldPending
= 0;
3155 SmNode
*pTemp
= nullptr;
3156 SmTextNode
*pIsText
= nullptr;
3158 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
3160 pIsText
= static_cast<SmTextNode
*>(pNode
->GetSubNode(1));
3162 switch (pTemp
->GetToken().eType
)
3165 //there's just no way we can now handle any character
3166 //attributes (from mathtypes perspective) centered
3167 //over an expression but above template attributes
3168 //such as widevec and similar constructs
3169 //we have to drop them
3170 nOldPending
= StartTemplate(0x2f,0x01);
3172 case TCHECK
: //Not Exportable
3173 case TACUTE
: //Not Exportable
3174 case TGRAVE
: //Not Exportable
3175 case TCIRCLE
: //Not Exportable
3176 case TWIDEHARPOON
: //Not Exportable
3177 case TWIDETILDE
: //Not Exportable
3178 case TWIDEHAT
: //Not Exportable
3181 nOldPending
= StartTemplate(0x10);
3183 case TOVERLINE
: //If the next node is not text
3184 //or text with more than one char
3185 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3186 (pIsText
->GetText().getLength() > 1))
3187 nOldPending
= StartTemplate(0x11);
3190 nPendingAttributes
++;
3196 HandleNodes(pIsText
,nLevel
+1);
3198 switch (pTemp
->GetToken().eType
)
3202 EndTemplate(nOldPending
);
3205 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3206 (pIsText
->GetText().getLength() > 1))
3207 EndTemplate(nOldPending
);
3213 //if there was no suitable place to put the attribute,
3214 //then we have to just give up on it
3215 if (nPendingAttributes
)
3216 nPendingAttributes
--;
3219 if ((nInsertion
!= 0) && nullptr != (pTemp
= pNode
->GetSubNode(0)))
3221 auto nPos
= pS
->Tell();
3223 pS
->Seek(nInsertion
);
3224 switch(pTemp
->GetToken().eType
)
3226 case TACUTE
: //Not Exportable
3227 case TGRAVE
: //Not Exportable
3228 case TCIRCLE
: //Not Exportable
3231 pS
->WriteUChar( 2 );
3234 pS
->WriteUChar( 3 );
3237 pS
->WriteUChar( 4 );
3240 pS
->WriteUChar( 8 );
3243 pS
->WriteUChar( 9 );
3246 pS
->WriteUChar( 11 );
3249 pS
->WriteUChar( 16 );
3252 if ((pIsText
->GetToken().eType
== TTEXT
) &&
3253 (pIsText
->GetText().getLength() == 1))
3254 pS
->WriteUChar( 17 );
3257 pS
->WriteUChar( 20 );
3266 pS
->WriteUChar( 17 );
3269 pS
->WriteUChar( 2 );
3277 void MathType::HandleText(SmNode
*pNode
)
3279 SmTextNode
*pTemp
= static_cast<SmTextNode
*>(pNode
);
3280 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3282 if (nPendingAttributes
&&
3283 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3285 pS
->WriteUChar( 0x22 ); //char, with attributes right
3286 //after the character
3289 pS
->WriteUChar( CHAR
);
3291 sal_uInt8 nFace
= 0x1;
3292 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3294 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3296 pS
->WriteUChar( nFace
+128 ); //typeface
3297 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3298 pS
->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar
) );
3300 //Mathtype can only have these sort of character
3301 //attributes on a single character, starmath can put them
3302 //anywhere, when the entity involved is a text run this is
3303 //a large effort to place the character attribute on the
3304 //central mathtype character so that it does pretty much
3305 //what the user probably has in mind. The attributes
3306 //filled in here are dummy ones which are replaced in the
3307 //ATTRIBUT handler if a suitable location for the
3308 //attributes was found here. Unfortunately it is
3309 //possible for starmath to place character attributes on
3310 //entities which cannot occur in mathtype e.g. a Summation
3311 //symbol so these attributes may be lost
3312 if (nPendingAttributes
&&
3313 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3315 pS
->WriteUChar( EMBEL
);
3316 while (nPendingAttributes
)
3318 pS
->WriteUChar( 2 );
3319 //wedge the attributes in here and clear
3321 nPendingAttributes
--;
3323 nInsertion
=pS
->Tell();
3324 pS
->WriteUChar( END
); //end embel
3325 pS
->WriteUChar( END
); //end embel
3330 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportMathType(SvStream
&rStream
)
3332 OUStringBuffer sText
;
3333 MathType
aEquation(sText
);
3337 bRet
= aEquation
.Parse(&rStream
);
3339 catch (const std::out_of_range
&)
3345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */