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"
21 #include "eqnolefilehdr.hxx"
23 #include <filter/msfilter/classids.hxx>
24 #include <osl/diagnose.h>
25 #include <sfx2/docfile.hxx>
26 #include <sot/storage.hxx>
29 //These are the default MathType sizes
30 constexpr std::array
<sal_Int16
, 7> aSizeTable
{
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 aUserStyles
.reserve(11);
49 for(sal_uInt8 i
=1;i
<=11;i
++)
65 aUserStyles
.insert(aFont
);
70 /*ToDo replace with table rather than switch, returns
71 sal_True in the case that the char is just a char, and
72 sal_False if the character is an operator which must not be
73 placed inside the quote sequence designed to protect
74 against being parsed as a keyword
76 General solution required to force starmath to handle
77 unicode math chars the way it handles its own math
78 chars rather than handle them as text as it will do
79 for the default case below, i.e. incorrect spacing
80 between math symbols and ordinary text e.g. 1=2 rather
83 bool MathType::LookupChar(sal_Unicode nChar
,OUStringBuffer
&rRet
,sal_uInt8 nVersion
,
87 const char *pC
= nullptr;
115 if ((nVersion
< 3) && (nTypeFace
== 0x86))
119 rRet
.append(OUStringChar(nChar
));
124 if ((nVersion
< 3) && (nTypeFace
== 0x81))
126 rRet
.append(OUStringChar(nChar
));
130 if ((nVersion
< 3) && (nTypeFace
== 0x84))
132 rRet
.append(OUStringChar(nChar
));
136 if ((nVersion
< 3) && (nTypeFace
== 0x84))
138 rRet
.append(OUStringChar(nChar
));
142 if ((nVersion
< 3) && (nTypeFace
== 0x84))
144 rRet
.append(OUStringChar(nChar
));
148 if ((nVersion
< 3) && (nTypeFace
== 0x84))
150 rRet
.append(OUStringChar(nChar
));
154 if ((nVersion
< 3) && (nTypeFace
== 0x84))
156 rRet
.append(OUStringChar(nChar
));
160 if ((nVersion
< 3) && (nTypeFace
== 0x84))
162 rRet
.append(OUStringChar(nChar
));
166 if ((nVersion
< 3) && (nTypeFace
== 0x82))
168 rRet
.append(OUStringChar(nChar
));
172 if ((nVersion
< 3) && (nTypeFace
== 0x86))
176 rRet
.append(OUStringChar(nChar
));
181 if ((nVersion
< 3) && (nTypeFace
== 0x86))
185 rRet
.append(OUStringChar(nChar
));
190 if ((nVersion
< 3) && (nTypeFace
== 0x86))
194 rRet
.append(OUStringChar(nChar
));
199 if ((nVersion
< 3) && (nTypeFace
== 0x85))
203 rRet
.append(OUStringChar(nChar
));
319 pC
= " backepsilon ";
322 case 0x2209: // notin
323 rRet
.append(" func " + OUStringChar(nChar
) + " ");
326 rRet
.append(u
" func \u220b ");
362 pC
= " intersection ";
411 pC
= " preccurlyeq ";
414 pC
= " succcurlyeq ";
429 case 0x2282: // subset
430 case 0x2283: // supset
431 case 0x2284: // nsubset
432 case 0x2285: // nsupset
433 case 0x2286: // subseteq
434 case 0x2287: // supseteq
435 case 0x2288: // nsubseteq
436 case 0x2289: // nsupseteq
437 case 0x22b2: // NORMAL SUBGROUP OF
438 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
439 rRet
.append(" func " + OUStringChar(nChar
) + " ");
493 case 0xeb01: //no space
494 case 0xeb08: //normal space
497 case 0xef04: //tiny space
498 case 0xef05: //tiny space
499 case 0xeb02: //small space
500 case 0xeb04: //medium space
503 case 0xeb05: //large space
510 rRet
.append(OUStringChar(nChar
));
515 rRet
.appendAscii(pC
);
519 void MathTypeFont::AppendStyleToText(OUString
&rRet
)
521 const char *pC
= nullptr;
538 rRet
+= OUString::createFromAscii( pC
);
541 void MathType::TypeFaceToString(OUString
&rTxt
,sal_uInt8 nFace
)
543 MathTypeFont
aFont(nFace
);
544 auto aItr
= aUserStyles
.find(aFont
);
545 if (aItr
!= aUserStyles
.end())
546 aFont
.nStyle
= aItr
->nStyle
;
547 aFont
.AppendStyleToText(rTxt
);
550 bool MathType::Parse(SotStorage
*pStor
)
552 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(
554 StreamMode::STD_READ
);
555 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
557 return Parse(xSrc
.get());
560 bool MathType::Parse(SvStream
* pStream
)
563 pS
->SetEndian( SvStreamEndian::LITTLE
);
567 sal_uInt8 nProdVersion
;
568 sal_uInt8 nProdSubVersion
;
571 pS
->ReadUChar( nVersion
);
572 pS
->ReadUChar( nPlatform
);
573 pS
->ReadUChar( nProduct
);
574 pS
->ReadUChar( nProdVersion
);
575 pS
->ReadUChar( nProdSubVersion
);
577 if (!pS
->good() || nVersion
> 3) // allow only supported versions of MathType to be parsed
580 bool bRet
= HandleRecords(0);
581 //little crude hack to close occasionally open expressions
582 //a sophisticated system to determine what expressions are
583 //opened is required, but this is as much work as rewriting
584 //starmaths internals.
590 static void lcl_PrependDummyTerm(OUStringBuffer
&rRet
, sal_Int32
&rTextStart
)
592 if ((rTextStart
< rRet
.getLength()) &&
593 (rRet
[rTextStart
] == '=') &&
594 ((rTextStart
== 0) || (rRet
[ rTextStart
-1 ] == '{'))
597 rRet
.insert(rTextStart
, " {}");
602 static void lcl_AppendDummyTerm(OUStringBuffer
&rRet
)
605 for(int nI
=rRet
.getLength()-1;nI
>= 0; nI
--)
607 sal_Int32 nIdx
= sal::static_int_cast
< sal_Int32
>(nI
);
608 sal_Unicode nChar
= rRet
[nIdx
];
611 if (rRet
[nIdx
] != '{')
615 if (!bOk
) //No term, use dummy
619 void MathType::HandleNudge()
621 sal_uInt8
nXNudge(0);
622 pS
->ReadUChar(nXNudge
);
623 sal_uInt8
nYNudge(0);
624 pS
->ReadUChar(nYNudge
);
625 if (nXNudge
== 128 && nYNudge
== 128)
627 sal_uInt16
nXLongNudge(0);
628 sal_uInt16
nYLongNudge(0);
629 pS
->ReadUInt16(nXLongNudge
);
630 pS
->ReadUInt16(nYLongNudge
);
634 /* Fabulously complicated as many tokens have to be reordered and generally
635 * moved around from mathtypes paradigm to starmaths. */
636 bool MathType::HandleRecords(int nLevel
, sal_uInt8 nSelector
,
637 sal_uInt8 nVariation
, int nMatrixRows
, int nMatrixCols
)
643 sal_uInt8 nTag
,nRecord
;
645 sal_uInt16 nTabOffset
;
649 OUString sPush
,sMainTerm
;
650 int nSetSize
=0,nSetAlign
=0;
651 int nCurRow
=0,nCurCol
=0;
652 bool bOpenString
=false;
653 sal_Int32 nTextStart
= 0;
654 sal_Int32 nSubSupStartPos
= 0;
655 sal_Int32 nLastTemplateBracket
=-1;
661 pS
->ReadUChar( nTag
);
664 /*MathType strings can of course include words which
665 *are StarMath keywords, the simplest solution is
666 to escape strings of greater than len 1 with double
667 quotes to avoid scanning the TokenTable for matches
669 Unfortunately it may turn out that the string gets
670 split during the handling of a character emblishment
671 so this special case must be handled in the
672 character handler case 2:
674 if ((nRecord
== CHAR
) && (!bOpenString
))
677 nTextStart
= rRet
.getLength();
679 else if ((nRecord
!= CHAR
) && bOpenString
)
682 if ((rRet
.getLength() - nTextStart
) > 1)
685 TypeFaceToString(aStr
,nTypeFace
);
687 rRet
.insert(nTextStart
,aStr
);
690 else if (nRecord
== END
&& !rRet
.isEmpty())
692 sal_Unicode cChar
= 0;
693 sal_Int32 nI
= rRet
.getLength()-1;
701 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
714 rRet
.append("\nnewline\n");
721 rRet
.append(" langle ");
722 else if (nVariation
==1)
723 rRet
.append(" \\langle ");
727 rRet
.append(" left (");
728 else if (nVariation
==1)
732 if ((nVariation
==0) || (nVariation
==1))
733 rRet
.append(" left lbrace ");
735 rRet
.append(" left none ");
739 rRet
.append(" left [");
740 else if (nVariation
==1)
749 rRet
.append(" lline ");
750 else if (nVariation
==1)
751 rRet
.append(" \\lline ");
755 rRet
.append(" ldline ");
756 else if (nVariation
==1)
757 rRet
.append(" \\ldline ");
760 if (nVariation
== 0 || nVariation
& 0x01) // tvFENCE_L
761 rRet
.append(" left lfloor ");
763 rRet
.append(" left none ");
767 rRet
.append(" lceil ");
768 else if (nVariation
==1)
769 rRet
.append(" \\lceil ");
782 rRet
.append(" sqrt");
785 rRet
.append(" nroot");
786 sPush
= rRet
.makeStringAndClear();
797 rRet
.append(" over ");
801 nSubSupStartPos
= rRet
.getLength();
802 if ((nVariation
== 0) ||
803 ((nVariation
== 2) && (nPart
==1)))
805 lcl_AppendDummyTerm(rRet
);
806 rRet
.append(" rSup");
808 else if ((nVariation
== 1) ||
809 ((nVariation
== 2) && (nPart
==0)))
811 lcl_AppendDummyTerm(rRet
);
812 rRet
.append(" rSub");
818 rRet
.append(" {underline ");
819 else if (nVariation
== 1)
820 rRet
.append(" {underline underline ");
825 rRet
.append(" {overline ");
826 else if (nVariation
== 1)
827 rRet
.append(" {overline overline ");
834 rRet
.append(" widevec ");//left arrow above
835 else if (nVariation
== 1)
836 rRet
.append(" widevec ");//left arrow below
844 rRet
.append(" widevec ");//right arrow above
845 else if (nVariation
== 1)
846 rRet
.append(" widevec ");//right arrow below
854 rRet
.append(" widevec ");//double arrow above
855 else if (nVariation
== 1)
856 rRet
.append(" widevec ");//double arrow below
863 if ((nVariation
== 3) || (nVariation
== 4))
864 rRet
.append(" lInt");
867 if ( (nVariation
!= 0) && (nVariation
!= 3))
869 sPush
= rRet
.makeStringAndClear();
872 if (((nVariation
== 1) ||
873 (nVariation
== 4)) && (nPart
==1))
874 rRet
.append(" rSub");
875 else if ((nVariation
== 2) && (nPart
==2))
876 rRet
.append(" rSup");
877 else if ((nVariation
== 2) && (nPart
==1))
878 rRet
.append(" rSub");
884 if ((nVariation
== 2) || (nVariation
== 3))
885 rRet
.append(" llInt");
887 rRet
.append(" iInt");
888 if ( (nVariation
!= 0) && (nVariation
!= 2))
890 sPush
= rRet
.makeStringAndClear();
893 if (((nVariation
== 1) ||
894 (nVariation
== 3)) && (nPart
==1))
895 rRet
.append(" rSub");
901 if ((nVariation
== 2) || (nVariation
== 3))
902 rRet
.append(" lllInt");
904 rRet
.append(" iiInt");
905 if ( (nVariation
!= 0) && (nVariation
!= 2))
907 sPush
= rRet
.makeStringAndClear();
910 if (((nVariation
== 1) ||
911 (nVariation
== 3)) && (nPart
==1))
912 rRet
.append(" rSub");
919 rRet
.append(" lInt");
922 sPush
= rRet
.makeStringAndClear();
924 if (((nVariation
== 1) ||
925 (nVariation
== 2)) && (nPart
==1))
926 rRet
.append(" cSub");
927 else if ((nVariation
== 0) && (nPart
==2))
928 rRet
.append(" cSup");
929 else if ((nVariation
== 0) && (nPart
==1))
930 rRet
.append(" cSub");
937 rRet
.append(" llInt");
939 rRet
.append(" iInt");
940 sPush
= rRet
.makeStringAndClear();
943 rRet
.append(" cSub");
950 rRet
.append(" lllInt");
952 rRet
.append(" iiInt");
953 sPush
= rRet
.makeStringAndClear();
956 rRet
.append(" cSub");
969 sPush
= rRet
.makeStringAndClear();
972 if ((nVariation
== 0) && (nPart
==1))
973 rRet
.append(" cSub");
974 else if ((nVariation
== 1) && (nPart
==2))
975 rRet
.append(" cSup");
976 else if ((nVariation
== 1) && (nPart
==1))
977 rRet
.append(" cSub");
984 sPush
= rRet
.makeStringAndClear();
986 if ((nVariation
== 0) && (nPart
==1))
987 rRet
.append(" rSub");
988 else if ((nVariation
== 1) && (nPart
==2))
989 rRet
.append(" rSup");
990 else if ((nVariation
== 1) && (nPart
==1))
991 rRet
.append(" rSub");
997 rRet
.append(" Prod");
1000 sPush
= rRet
.makeStringAndClear();
1003 if ((nVariation
== 0) && (nPart
==1))
1004 rRet
.append(" cSub");
1005 else if ((nVariation
== 1) && (nPart
==2))
1006 rRet
.append(" cSup");
1007 else if ((nVariation
== 1) && (nPart
==1))
1008 rRet
.append(" cSub");
1014 rRet
.append(" Prod");
1015 sPush
= rRet
.makeStringAndClear();
1017 if ((nVariation
== 0) && (nPart
==1))
1018 rRet
.append(" rSub");
1019 else if ((nVariation
== 1) && (nPart
==2))
1020 rRet
.append(" rSup");
1021 else if ((nVariation
== 1) && (nPart
==1))
1022 rRet
.append(" rSub");
1028 rRet
.append(" coProd");
1029 if (nVariation
!= 2)
1031 sPush
= rRet
.makeStringAndClear();
1034 if ((nVariation
== 0) && (nPart
==1))
1035 rRet
.append(" cSub");
1036 else if ((nVariation
== 1) && (nPart
==2))
1037 rRet
.append(" cSup");
1038 else if ((nVariation
== 1) && (nPart
==1))
1039 rRet
.append(" cSub");
1045 rRet
.append(" coProd");
1046 sPush
= rRet
.makeStringAndClear();
1048 if ((nVariation
== 0) && (nPart
==1))
1049 rRet
.append(" rSub");
1050 else if ((nVariation
== 1) && (nPart
==2))
1051 rRet
.append(" rSup");
1052 else if ((nVariation
== 1) && (nPart
==1))
1053 rRet
.append(" rSub");
1059 rRet
.append(" union"); //union
1060 if (nVariation
!= 2)
1062 sPush
= rRet
.makeStringAndClear();
1065 if ((nVariation
== 0) && (nPart
==1))
1066 rRet
.append(" cSub");
1067 else if ((nVariation
== 1) && (nPart
==2))
1068 rRet
.append(" cSup");
1069 else if ((nVariation
== 1) && (nPart
==1))
1070 rRet
.append(" cSub");
1076 rRet
.append(" union"); //union
1077 sPush
= rRet
.makeStringAndClear();
1079 if ((nVariation
== 0) && (nPart
==1))
1080 rRet
.append(" rSub");
1081 else if ((nVariation
== 1) && (nPart
==2))
1082 rRet
.append(" rSup");
1083 else if ((nVariation
== 1) && (nPart
==1))
1084 rRet
.append(" rSub");
1090 rRet
.append(" intersect"); //intersect
1091 if (nVariation
!= 2)
1093 sPush
= rRet
.makeStringAndClear();
1096 if ((nVariation
== 0) && (nPart
==1))
1097 rRet
.append(" cSub");
1098 else if ((nVariation
== 1) && (nPart
==2))
1099 rRet
.append(" cSup");
1100 else if ((nVariation
== 1) && (nPart
==1))
1101 rRet
.append(" cSub");
1107 rRet
.append(" intersect"); //intersect
1108 sPush
= rRet
.makeStringAndClear();
1110 if ((nVariation
== 0) && (nPart
==1))
1111 rRet
.append(" rSub");
1112 else if ((nVariation
== 1) && (nPart
==2))
1113 rRet
.append(" rSup");
1114 else if ((nVariation
== 1) && (nPart
==1))
1115 rRet
.append(" rSub");
1119 if ((nVariation
== 0) && (nPart
==1))
1120 rRet
.append(" cSup");
1121 else if ((nVariation
== 1) && (nPart
==1))
1122 rRet
.append(" cSub");
1123 else if ((nVariation
== 2) && (nPart
==1))
1124 rRet
.append(" cSub");
1125 else if ((nVariation
== 2) && (nPart
==2))
1126 rRet
.append(" cSup");
1130 if (nVariation
== 0)
1134 sPush
= rRet
.makeStringAndClear();
1138 if (nVariation
== 0)
1141 rRet
.append("alignr ");
1144 rRet
.append("\\lline ");
1145 if (nVariation
== 1)
1146 rRet
.append("overline ");
1154 sPush
= rRet
.makeStringAndClear();
1156 if ((nVariation
== 0) && (nPart
==0))
1157 rRet
.append(" rSup");
1158 else if ((nVariation
== 2) && (nPart
==1))
1159 rRet
.append(" rSup");
1160 else if ((nVariation
== 1) && (nPart
==0))
1161 rRet
.append(" rSub");
1162 else if ((nVariation
== 2) && (nPart
==0))
1163 rRet
.append(" rSub");
1169 sPush
= rRet
.makeStringAndClear();
1171 if ((nVariation
== 0) && (nPart
==0))
1172 rRet
.append(" cSup");
1173 else if ((nVariation
== 2) && (nPart
==1))
1174 rRet
.append(" cSup");
1175 else if ((nVariation
== 1) && (nPart
==0))
1176 rRet
.append(" cSub");
1177 else if ((nVariation
== 2) && (nPart
==0))
1178 rRet
.append(" cSub");
1183 rRet
.append("\"\"");
1184 if ((nVariation
== 0)
1185 || ((nVariation
== 2) && (nPart
==1)))
1186 rRet
.append(" lSup");
1187 else if ((nVariation
== 1)
1188 || ((nVariation
== 2) && (nPart
==0)))
1189 rRet
.append(" lSub");
1196 rRet
.append(" langle ");
1198 else if (nVariation
==1)
1200 rRet
.append(" \\langle ");
1203 else if (nVariation
==2)
1205 rRet
.append(" \\lline ");
1210 if (nVariation
== 0)
1211 rRet
.append(" widevec ");//left below
1212 else if (nVariation
== 1)
1213 rRet
.append(" widevec ");//right below
1214 else if (nVariation
== 2)
1215 rRet
.append(" widevec ");//double headed below
1219 if (nVariation
== 0)
1220 rRet
.append(" widevec ");//left above
1221 else if (nVariation
== 1)
1222 rRet
.append(" widevec ");//right above
1223 else if (nVariation
== 2)
1224 rRet
.append(" widevec ");//double headed above
1230 sal_Int16 nOldCurSize
=nCurSize
;
1231 sal_Int32 nSizeStartPos
= rRet
.getLength();
1232 HandleSize( nLSize
, nDSize
, nSetSize
);
1233 bRet
= HandleRecords( nLevel
+1 );
1237 sal_Int32 nI
= rRet
.lastIndexOf('{');
1240 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1241 if (rRet
[nI
] != ' ')
1252 else if (rRet
.getLength() > nSizeStartPos
)
1253 rRet
= rRet
.truncate(nSizeStartPos
);
1255 nCurSize
=nOldCurSize
;
1259 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1266 rRet
.append(" rangle ");
1267 else if (nVariation
==2)
1268 rRet
.append(" \\rangle ");
1272 rRet
.append(" right )");
1273 else if (nVariation
==2)
1277 if ((nVariation
==0) || (nVariation
==2))
1278 rRet
.append(" right rbrace ");
1280 rRet
.append(" right none ");
1284 rRet
.append(" right ]");
1285 else if (nVariation
==2)
1290 rRet
.append(" rline ");
1291 else if (nVariation
==2)
1292 rRet
.append(" \\rline ");
1296 rRet
.append(" rdline ");
1297 else if (nVariation
==2)
1298 rRet
.append(" \\rdline ");
1301 if (nVariation
== 0 || nVariation
& 0x02) // tvFENCE_R
1302 rRet
.append(" right rfloor ");
1304 rRet
.append(" right none ");
1308 rRet
.append(" rceil ");
1309 else if (nVariation
==2)
1310 rRet
.append(" \\rceil ");
1322 if (nVariation
== 1)
1327 sMainTerm
= rRet
.makeStringAndClear();
1329 else if (nPart
== 1)
1331 rRet
.insert(0, sPush
);
1332 rRet
.append(sMainTerm
);
1358 ((nVariation
== 2) || (nVariation
== 1)))
1362 sal_Int32 nI
= rRet
.lastIndexOf('{');
1365 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1366 if (rRet
[nI
] != ' ')
1377 else if (rRet
.getLength() > nSubSupStartPos
)
1378 rRet
= rRet
.truncate(nSubSupStartPos
);
1384 ((nVariation
== 2) || (nVariation
== 1)))
1412 rRet
.append("overbrace");
1421 rRet
.append("underbrace");
1428 else if ((nPart
==1) &&
1429 ((nVariation
== 2) || (nVariation
== 1)))
1436 if (nVariation
== 0)
1440 sMainTerm
= rRet
.makeStringAndClear();
1442 else if (nPart
== 1)
1444 rRet
.insert(0, sPush
);
1445 rRet
.append(" over " + sMainTerm
);
1462 rRet
.append("slash");
1465 rRet
.append("wideslash");
1484 if (nVariation
!= 2)
1486 sMainTerm
= rRet
.makeStringAndClear();
1490 else if ((nPart
== 1) && (nVariation
== 0))
1492 rRet
.insert(0, sPush
);
1493 rRet
.append(sMainTerm
);
1498 else if ((nPart
== 1) && (nVariation
== 1))
1500 else if ((nPart
== 2) && (nVariation
== 1))
1502 rRet
.insert(0, sPush
);
1503 rRet
.append(sMainTerm
);
1514 if ((nVariation
!= 0) && (nVariation
!= 3))
1516 sMainTerm
= rRet
.makeStringAndClear();
1520 else if ((nPart
== 1) &&
1521 ((nVariation
== 1) || (nVariation
==4)))
1523 rRet
.insert(0, sPush
);
1524 rRet
.append(sMainTerm
);
1529 else if ((nPart
== 1) && (nVariation
== 2))
1531 else if ((nPart
== 2) && (nVariation
== 2))
1533 rRet
.insert(0, sPush
);
1534 rRet
.append(sMainTerm
);
1546 if ((nVariation
!= 0) && (nVariation
!= 2))
1548 sMainTerm
= rRet
.makeStringAndClear();
1552 else if ((nPart
== 1) &&
1553 ((nVariation
== 1) || (nVariation
==3)))
1555 rRet
.insert(0, sPush
);
1556 rRet
.append(sMainTerm
);
1567 sMainTerm
= rRet
.makeStringAndClear();
1570 else if ((nPart
== 1) &&
1571 ((nVariation
== 1) || (nVariation
==2)))
1573 rRet
.insert(0, sPush
);
1574 rRet
.append(sMainTerm
);
1579 else if ((nPart
== 1) && (nVariation
== 0))
1581 else if ((nPart
== 2) && (nVariation
== 0))
1583 rRet
.insert(0, sPush
);
1584 rRet
.append(sMainTerm
);
1596 sMainTerm
= rRet
.makeStringAndClear();
1599 else if (nPart
== 1)
1601 rRet
.insert(0, sPush
);
1602 rRet
.append(sMainTerm
);
1614 ((nVariation
== 0) || (nVariation
== 1)))
1616 sMainTerm
= rRet
.makeStringAndClear();
1619 else if ((nPart
== 0) && (nVariation
== 2))
1621 else if ((nPart
== 1) && (nVariation
== 2))
1623 sMainTerm
= rRet
.makeStringAndClear();
1626 else if ((nPart
== 2) || ((nPart
== 1) &&
1627 (nVariation
== 0 || nVariation
== 1)))
1629 rRet
.insert(0, sPush
);
1630 rRet
.append(sMainTerm
);
1641 newline
--; //there is another term to arrive
1642 rRet
.append(" mline ");
1645 rRet
.append(" rangle ");
1647 else if (nVariation
==1)
1648 rRet
.append(" \\lline ");
1649 else if (nVariation
==2)
1650 rRet
.append(" \\rangle ");
1656 bSilent
= true; //Skip the optional brackets and/or
1657 //symbols that follow some of these
1658 //records. Foo Data.
1660 /*In matrices and piles we cannot separate equation
1661 *lines with the newline keyword*/
1670 bRet
= HandleChar( nTextStart
, nSetSize
, nLevel
, nTag
, nSelector
, nVariation
, bSilent
);
1675 bRet
= HandleTemplate( nLevel
, nSelector
, nVariation
, nLastTemplateBracket
);
1680 bRet
= HandlePile( nSetAlign
, nLevel
, nSelector
, nVariation
);
1681 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1686 bRet
= HandleMatrix( nLevel
, nSelector
, nVariation
);
1687 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1692 HandleEmblishments();
1696 sal_uInt8
nTabStops(0);
1697 pS
->ReadUChar( nTabStops
);
1698 for (i
=0;i
<nTabStops
;i
++)
1700 pS
->ReadUChar( nTabType
);
1701 pS
->ReadUInt16( nTabOffset
);
1703 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1709 pS
->ReadUChar( aFont
.nTface
);
1711 The typeface number is the negative (which makes it
1712 positive) of the typeface value (unbiased) that appears in
1713 CHAR records that might follow a given FONT record
1715 aFont
.nTface
= 128-aFont
.nTface
;
1716 pS
->ReadUChar( aFont
.nStyle
);
1717 aUserStyles
.insert(aFont
);
1722 pS
->ReadChar( nChar8
);
1743 while (nRecord
!= END
&& !pS
->eof());
1752 /*Simply determine if we are at the end of a record or the end of a line,
1753 *with fiddly logic to see if we are in a matrix or a pile or neither
1755 Note we cannot tell until after the event that this is the last entry
1756 of a pile, so we must strip the last separator of a pile after this
1757 is detected in the PILE handler
1759 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1760 int &rCurCol
,int &rCurRow
)
1765 if (rCurCol
== nMatrixCols
-1)
1767 if (rCurRow
!= nMatrixRows
-1)
1768 rRet
.append(" {} ##\n");
1769 if (nMatrixRows
!=-1)
1777 rRet
.append(" {} # ");
1778 if (nMatrixRows
!=-1)
1785 /* set the alignment of the following term, but starmath currently
1786 * cannot handle vertical alignment */
1787 void MathType::HandleAlign(sal_uInt8 nHorAlign
, int &rSetAlign
)
1793 rRet
.append("alignl {");
1796 rRet
.append("alignc {");
1799 rRet
.append("alignr {");
1805 /* set size of text, complexity due to overuse of signedness as a flag
1806 * indicator by mathtype file format*/
1807 bool MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1812 const sal_Int16 nDefaultSize
= 12;
1813 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1821 if (-nLstSize
/32 != nLastSize
)
1823 nLastSize
= nCurSize
;
1824 rRet
.append(" size ");
1825 rRet
.append(static_cast<sal_Int32
>(-nLstSize
/32));
1830 nCurSize
= -nLstSize
/32;
1835 /*sizetable should theoretically be filled with the default sizes
1836 *of the various font groupings matching starmaths equivalents
1837 in aTypeFaces, and a test would be done to see if the new font
1838 size would be the same as what starmath would have chosen for
1839 itself anyway in which case the size setting could be ignored*/
1840 nLstSize
= aSizeTable
.at(nLstSize
);
1841 nLstSize
= nLstSize
+ nDefSize
;
1842 if (nLstSize
!= nCurSize
)
1850 if (nLstSize
!= nLastSize
)
1852 nLastSize
= nCurSize
;
1853 rRet
.append(" size ");
1854 rRet
.append(static_cast<sal_Int32
>(nLstSize
));
1859 nCurSize
= nLstSize
;
1865 bool MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1870 SvStream
*pStream
= rMedium
.GetOutStream();
1873 tools::SvRef
<SotStorage
> pStor
= new SotStorage( pStream
, false );
1875 SvGlobalName
aGName(MSO_EQUATION3_CLASSID
);
1876 pStor
->SetClass( aGName
, SotClipboardFormatId::NONE
, "Microsoft Equation 3.0");
1878 static sal_uInt8
const aCompObj
[] = {
1879 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1880 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1883 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1884 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1885 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1886 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1887 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1888 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1889 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1890 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1893 tools::SvRef
<SotStorageStream
> xStor( pStor
->OpenSotStream("\1CompObj"));
1894 xStor
->WriteBytes(aCompObj
, sizeof(aCompObj
));
1896 static sal_uInt8
const aOle
[] = {
1897 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1899 0x00, 0x00, 0x00, 0x00
1901 tools::SvRef
<SotStorageStream
> xStor2( pStor
->OpenSotStream("\1Ole"));
1902 xStor2
->WriteBytes(aOle
, sizeof(aOle
));
1906 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream("Equation Native");
1907 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
1911 pS
->SetEndian( SvStreamEndian::LITTLE
);
1913 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1914 pS
->WriteUChar( 0x03 );
1915 pS
->WriteUChar( 0x01 );
1916 pS
->WriteUChar( 0x01 );
1917 pS
->WriteUChar( 0x03 );
1918 pS
->WriteUChar( 0x00 );
1919 sal_uInt32 nSize
= pS
->Tell();
1920 nPendingAttributes
=0;
1922 HandleNodes(pTree
, 0);
1923 pS
->WriteUChar( END
);
1925 nSize
= pS
->Tell()-nSize
;
1927 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1937 void MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1939 switch(pNode
->GetType())
1941 case SmNodeType::Attribute
:
1942 HandleAttributes(pNode
,nLevel
);
1944 case SmNodeType::Text
:
1947 case SmNodeType::VerticalBrace
:
1948 HandleVerticalBrace(pNode
,nLevel
);
1950 case SmNodeType::Brace
:
1951 HandleBrace(pNode
,nLevel
);
1953 case SmNodeType::Oper
:
1954 HandleOperator(pNode
,nLevel
);
1956 case SmNodeType::BinVer
:
1957 HandleFractions(pNode
,nLevel
);
1959 case SmNodeType::Root
:
1960 HandleRoot(pNode
,nLevel
);
1962 case SmNodeType::Special
:
1964 SmTextNode
*pText
= static_cast<SmTextNode
*>(pNode
);
1965 //if the token str and the result text are the same then this
1966 //is to be seen as text, else assume it's a mathchar
1967 if (pText
->GetText() == pText
->GetToken().aText
)
1973 case SmNodeType::Math
:
1974 case SmNodeType::MathIdent
:
1977 case SmNodeType::SubSup
:
1978 HandleSubSupScript(pNode
,nLevel
);
1980 case SmNodeType::Expression
:
1982 size_t nSize
= pNode
->GetNumSubNodes();
1983 for (size_t i
= 0; i
< nSize
; ++i
)
1985 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1986 HandleNodes(pTemp
,nLevel
+1);
1990 case SmNodeType::Table
:
1991 //Root Node, PILE equivalent, i.e. vertical stack
1992 HandleTable(pNode
,nLevel
);
1994 case SmNodeType::Matrix
:
1995 HandleSmMatrix(static_cast<SmMatrixNode
*>(pNode
),nLevel
);
1997 case SmNodeType::Line
:
1999 pS
->WriteUChar( 0x0a );
2000 pS
->WriteUChar( LINE
);
2001 size_t nSize
= pNode
->GetNumSubNodes();
2002 for (size_t i
= 0; i
< nSize
; ++i
)
2004 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2005 HandleNodes(pTemp
,nLevel
+1);
2007 pS
->WriteUChar( END
);
2010 case SmNodeType::Align
:
2011 HandleMAlign(pNode
,nLevel
);
2013 case SmNodeType::Blank
:
2014 pS
->WriteUChar( CHAR
);
2015 pS
->WriteUChar( 0x98 );
2016 if (pNode
->GetToken().eType
== TSBLANK
)
2017 pS
->WriteUInt16( 0xEB04 );
2019 pS
->WriteUInt16( 0xEB05 );
2023 size_t nSize
= pNode
->GetNumSubNodes();
2024 for (size_t i
= 0; i
< nSize
; ++i
)
2026 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2027 HandleNodes(pTemp
,nLevel
+1);
2035 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2037 int nOldPending
=nPendingAttributes
;
2038 pS
->WriteUChar( TMPL
); //Template
2039 pS
->WriteUChar( nSelector
); //selector
2040 pS
->WriteUChar( nVariation
); //variation
2041 pS
->WriteUChar( 0x00 ); //options
2042 pS
->WriteUChar( LINE
);
2043 //there's just no way we can now handle any character
2044 //attributes (from mathtypes perspective) centered
2045 //over an expression but above template attribute
2046 //such as widevec and similar constructs
2047 //we have to drop them
2048 nPendingAttributes
=0;
2052 void MathType::EndTemplate(int nOldPendingAttributes
)
2054 pS
->WriteUChar( END
); //end line
2055 pS
->WriteUChar( END
); //end template
2056 nPendingAttributes
=nOldPendingAttributes
;
2060 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2062 pS
->WriteUChar( MATRIX
);
2063 pS
->WriteUChar( 0x00 ); //vAlign ?
2064 pS
->WriteUChar( 0x00 ); //h_just
2065 pS
->WriteUChar( 0x00 ); //v_just
2066 pS
->WriteUChar( pMatrix
->GetNumRows() ); //v_just
2067 pS
->WriteUChar( pMatrix
->GetNumCols() ); //v_just
2068 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2069 if (((pMatrix
->GetNumRows()+1)*2)%8)
2071 for (int j
= 0; j
< nBytes
; j
++)
2072 pS
->WriteUChar( 0x00 ); //row_parts
2073 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2074 if (((pMatrix
->GetNumCols()+1)*2)%8)
2076 for (int k
= 0; k
< nBytes
; k
++)
2077 pS
->WriteUChar( 0x00 ); //col_parts
2078 size_t nSize
= pMatrix
->GetNumSubNodes();
2079 for (size_t i
= 0; i
< nSize
; ++i
)
2081 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2083 pS
->WriteUChar( LINE
); //line
2084 HandleNodes(pTemp
,nLevel
+1);
2085 pS
->WriteUChar( END
); //end line
2088 pS
->WriteUChar( END
);
2092 //Root Node, PILE equivalent, i.e. vertical stack
2093 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2095 size_t nSize
= pNode
->GetNumSubNodes();
2096 //The root of the starmath is a table, if
2097 //we convert this them each iteration of
2098 //conversion from starmath to mathtype will
2099 //add an extra unnecessary level to the
2100 //mathtype output stack which would grow
2101 //without bound in a multi step conversion
2104 pS
->WriteUChar( 0x0A ); //initial size
2106 if ( nLevel
|| (nSize
>1))
2108 pS
->WriteUChar( PILE
);
2109 pS
->WriteUChar( nHAlign
); //vAlign ?
2110 pS
->WriteUChar( 0x01 ); //hAlign
2113 for (size_t i
= 0; i
< nSize
; ++i
)
2115 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2117 pS
->WriteUChar( LINE
);
2118 HandleNodes(pTemp
,nLevel
+1);
2119 pS
->WriteUChar( END
);
2122 if (nLevel
|| (nSize
>1))
2123 pS
->WriteUChar( END
);
2127 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2130 pS
->WriteUChar( TMPL
); //Template
2131 pS
->WriteUChar( 0x0D ); //selector
2132 if (pNode
->GetSubNode(0))
2133 pS
->WriteUChar( 0x01 ); //variation
2135 pS
->WriteUChar( 0x00 ); //variation
2136 pS
->WriteUChar( 0x00 ); //options
2138 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2140 pS
->WriteUChar( LINE
); //line
2141 HandleNodes(pTemp
,nLevel
+1);
2142 pS
->WriteUChar( END
);
2145 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2147 pS
->WriteUChar( LINE
); //line
2148 HandleNodes(pTemp
,nLevel
+1);
2149 pS
->WriteUChar( END
);
2152 pS
->WriteUChar( LINE
|0x10 ); //dummy line
2155 pS
->WriteUChar( END
);
2158 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2159 sal_uInt64
*pPos
,bool bTest
)
2161 sal_uInt8 nVariation2
=0xff;
2163 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2166 if (pNode
->GetSubNode(CSUB
+1))
2169 else if (pNode
->GetSubNode(CSUB
+1))
2172 if (nVariation2
!=0xff)
2176 pS
->WriteUChar( TMPL
); //Template
2177 pS
->WriteUChar( 0x2B ); //selector
2178 pS
->WriteUChar( nVariation2
);
2179 pS
->WriteUChar( 0x00 ); //options
2183 pS
->WriteUChar( LINE
); //line
2184 HandleNodes(pContent
,nLevel
+1);
2185 pS
->WriteUChar( END
); //line
2188 pS
->WriteUChar( LINE
|0x10 );
2190 pS
->WriteUChar( 0x0B );
2193 if (nullptr != (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2195 pS
->WriteUChar( LINE
); //line
2196 HandleNodes(pTemp
,nLevel
+1);
2197 pS
->WriteUChar( END
); //line
2200 pS
->WriteUChar( LINE
|0x10 );
2201 if (bTest
&& nullptr != (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2203 pS
->WriteUChar( LINE
); //line
2204 HandleNodes(pTemp
,nLevel
+1);
2205 pS
->WriteUChar( END
); //line
2208 pS
->WriteUChar( LINE
|0x10 );
2215 Sub and Sup scripts and another problem area, StarMath
2216 can have all possible options used at the same time, whereas
2217 Mathtype cannot. The ordering of the nodes for each system
2218 is quite different as well leading to some complexity
2220 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2222 sal_uInt8 nVariation
=0xff;
2223 if (pNode
->GetSubNode(LSUP
+1))
2226 if (pNode
->GetSubNode(LSUB
+1))
2229 else if ( nullptr != pNode
->GetSubNode(LSUB
+1) )
2233 if (nVariation
!=0xff)
2235 pS
->WriteUChar( TMPL
); //Template
2236 pS
->WriteUChar( 0x2c ); //selector
2237 pS
->WriteUChar( nVariation
);
2238 pS
->WriteUChar( 0x00 ); //options
2239 pS
->WriteUChar( 0x0B );
2241 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2243 pS
->WriteUChar( LINE
); //line
2244 HandleNodes(pTemp
,nLevel
+1);
2245 pS
->WriteUChar( END
); //line
2248 pS
->WriteUChar( LINE
|0x10 );
2249 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2251 pS
->WriteUChar( LINE
); //line
2252 HandleNodes(pTemp
,nLevel
+1);
2253 pS
->WriteUChar( END
); //line
2256 pS
->WriteUChar( LINE
|0x10 );
2257 pS
->WriteUChar( END
);
2262 sal_uInt8 nVariation2
=HandleCScript(pNode
,nullptr,nLevel
);
2264 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2266 HandleNodes(pTemp
,nLevel
+1);
2269 if (nVariation2
!= 0xff)
2270 pS
->WriteUChar( END
);
2272 if (nullptr != (pNode
->GetSubNode(RSUP
+1)))
2275 if (pNode
->GetSubNode(RSUB
+1))
2278 else if (nullptr != pNode
->GetSubNode(RSUB
+1))
2281 if (nVariation
!=0xff)
2283 pS
->WriteUChar( TMPL
); //Template
2284 pS
->WriteUChar( 0x0F ); //selector
2285 pS
->WriteUChar( nVariation
);
2286 pS
->WriteUChar( 0x00 ); //options
2287 pS
->WriteUChar( 0x0B );
2289 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2291 pS
->WriteUChar( LINE
); //line
2292 HandleNodes(pTemp
,nLevel
+1);
2293 pS
->WriteUChar( END
); //line
2296 pS
->WriteUChar( LINE
|0x10 );
2297 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2299 pS
->WriteUChar( LINE
); //line
2300 HandleNodes(pTemp
,nLevel
+1);
2301 pS
->WriteUChar( END
); //line
2304 pS
->WriteUChar( LINE
|0x10 );
2305 pS
->WriteUChar( END
); //line
2308 //After subscript mathtype will keep the size of
2309 //normal text at the subscript size, sigh.
2310 pS
->WriteUChar( 0x0A );
2314 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2317 pS
->WriteUChar( TMPL
); //Template
2318 pS
->WriteUChar( 0x0E ); //selector
2319 pS
->WriteUChar( 0x00 ); //variation
2320 pS
->WriteUChar( 0x00 ); //options
2322 pS
->WriteUChar( 0x0A );
2323 pS
->WriteUChar( LINE
); //line
2324 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2325 HandleNodes(pTemp
,nLevel
+1);
2326 pS
->WriteUChar( END
);
2328 pS
->WriteUChar( 0x0A );
2329 pS
->WriteUChar( LINE
); //line
2330 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2331 HandleNodes(pTemp
,nLevel
+1);
2332 pS
->WriteUChar( END
);
2334 pS
->WriteUChar( END
);
2338 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2341 SmNode
*pLeft
=pNode
->GetSubNode(0);
2342 SmNode
*pRight
=pNode
->GetSubNode(2);
2344 pS
->WriteUChar( TMPL
); //Template
2345 bIsReInterpBrace
=false;
2346 sal_uInt8 nBSpec
=0x10;
2347 auto nLoc
= pS
->Tell();
2350 switch (pLeft
->GetToken().eType
)
2353 pS
->WriteUChar( tmANGLE
); //selector
2354 pS
->WriteUChar( 0 ); //variation
2355 pS
->WriteUChar( 0 ); //options
2358 pS
->WriteUChar( tmBRACE
); //selector
2359 pS
->WriteUChar( 0 ); //variation
2360 pS
->WriteUChar( 0 ); //options
2364 pS
->WriteUChar( tmBRACK
); //selector
2365 pS
->WriteUChar( 0 ); //variation
2366 pS
->WriteUChar( 0 ); //options
2370 pS
->WriteUChar( tmFLOOR
); //selector
2371 pS
->WriteUChar( 0 ); //variation
2372 pS
->WriteUChar( 0 ); //options
2375 pS
->WriteUChar( tmBAR
); //selector
2376 pS
->WriteUChar( 0 ); //variation
2377 pS
->WriteUChar( 0 ); //options
2381 pS
->WriteUChar( tmDBAR
); //selector
2382 pS
->WriteUChar( 0 ); //variation
2383 pS
->WriteUChar( 0 ); //options
2386 pS
->WriteUChar( tmPAREN
); //selector
2387 pS
->WriteUChar( 0 ); //variation
2388 pS
->WriteUChar( 0 ); //options
2394 if (nullptr != (pTemp
= pNode
->GetSubNode(1)))
2396 pS
->WriteUChar( LINE
); //line
2397 HandleNodes(pTemp
,nLevel
+1);
2398 pS
->WriteUChar( END
); //options
2402 HandleNodes(pLeft
,nLevel
+1);
2403 if (bIsReInterpBrace
)
2405 auto nLoc2
= pS
->Tell();
2407 pS
->WriteUChar( 0x2D );
2409 pS
->WriteUChar( CHAR
);
2410 pS
->WriteUChar( 0x96 );
2411 pS
->WriteUInt16( 0xEC07 );
2412 bIsReInterpBrace
=false;
2415 HandleNodes(pRight
,nLevel
+1);
2417 pS
->WriteUChar( END
);
2421 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2424 pS
->WriteUChar( TMPL
); //Template
2425 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2426 pS
->WriteUChar( tmLHBRACE
); //selector
2428 pS
->WriteUChar( tmUHBRACE
); //selector
2429 pS
->WriteUChar( 0 ); //variation
2430 pS
->WriteUChar( 0 ); //options
2432 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2434 pS
->WriteUChar( LINE
); //line
2435 HandleNodes(pTemp
,nLevel
+1);
2436 pS
->WriteUChar( END
); //options
2439 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2441 pS
->WriteUChar( LINE
); //line
2442 HandleNodes(pTemp
,nLevel
+1);
2443 pS
->WriteUChar( END
); //options
2445 pS
->WriteUChar( END
);
2448 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2450 if (HandleLim(pNode
,nLevel
))
2454 sal_uInt8 nVariation
;
2456 switch (pNode
->GetToken().eType
)
2463 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2464 pNode
->GetSubNode(1),nLevel
,&nPos
,false);
2467 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2468 pNode
->GetSubNode(1),nLevel
,&nPos
);
2472 sal_uInt8 nOldVariation
=nVariation
;
2473 sal_uInt8 nIntVariation
=nVariation
;
2476 if (nVariation
!= 0xff)
2480 if (nVariation
== 2)
2485 else if (nVariation
== 0)
2487 else if (nVariation
== 1)
2495 pS
->WriteUChar( TMPL
);
2496 switch(pNode
->GetToken().eType
)
2500 if (nOldVariation
!= 0xff)
2501 pS
->WriteUChar( 0x18 ); //selector
2503 pS
->WriteUChar( 0x15 ); //selector
2504 pS
->WriteUChar( nIntVariation
); //variation
2507 if (nOldVariation
!= 0xff)
2509 pS
->WriteUChar( 0x19 );
2510 pS
->WriteUChar( 0x01 );
2514 pS
->WriteUChar( 0x16 );
2515 pS
->WriteUChar( 0x00 );
2519 if (nOldVariation
!= 0xff)
2521 pS
->WriteUChar( 0x1a );
2522 pS
->WriteUChar( 0x01 );
2526 pS
->WriteUChar( 0x17 );
2527 pS
->WriteUChar( 0x00 );
2531 if (nOldVariation
!= 0xff)
2533 pS
->WriteUChar( 0x18 );
2534 pS
->WriteUChar( 0x02 );
2538 pS
->WriteUChar( 0x15 );
2539 pS
->WriteUChar( 0x03 );
2543 if (nOldVariation
!= 0xff)
2545 pS
->WriteUChar( 0x19 );
2546 pS
->WriteUChar( 0x00 );
2550 pS
->WriteUChar( 0x16 );
2551 pS
->WriteUChar( 0x02 );
2555 if (nOldVariation
!= 0xff)
2557 pS
->WriteUChar( 0x1a );
2558 pS
->WriteUChar( 0x00 );
2562 pS
->WriteUChar( 0x17 );
2563 pS
->WriteUChar( 0x02 );
2568 pS
->WriteUChar( 0x1d );
2569 pS
->WriteUChar( nVariation
);
2572 pS
->WriteUChar( 0x1f );
2573 pS
->WriteUChar( nVariation
);
2576 pS
->WriteUChar( 0x21 );
2577 pS
->WriteUChar( nVariation
);
2580 pS
->WriteUChar( 0 ); //options
2586 pS
->WriteUChar( LINE
); //line
2587 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2588 pS
->WriteUChar( END
); //line
2589 pS
->WriteUChar( LINE
|0x10 );
2590 pS
->WriteUChar( LINE
|0x10 );
2593 pS
->WriteUChar( 0x0D );
2594 switch(pNode
->GetToken().eType
)
2598 pS
->WriteUChar( CHAR
);
2599 pS
->WriteUChar( 0x86 );
2600 pS
->WriteUInt16( 0x2211 );
2603 pS
->WriteUChar( CHAR
);
2604 pS
->WriteUChar( 0x86 );
2605 pS
->WriteUInt16( 0x220F );
2608 pS
->WriteUChar( CHAR
);
2609 pS
->WriteUChar( 0x8B );
2610 pS
->WriteUInt16( 0x2210 );
2614 pS
->WriteUChar( CHAR
);
2615 pS
->WriteUChar( 0x86 );
2616 pS
->WriteUInt16( 0x222B );
2620 pS
->WriteUChar( CHAR
);
2621 pS
->WriteUChar( 0x86 );
2622 pS
->WriteUInt16( 0x222B );
2627 pS
->WriteUChar( CHAR
);
2628 pS
->WriteUChar( 0x86 );
2629 pS
->WriteUInt16( 0x222B );
2632 pS
->WriteUChar( END
);
2633 pS
->WriteUChar( 0x0A );
2637 bool MathType::HandlePile(int &rSetAlign
, int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2640 pS
->ReadUChar( nHAlign
);
2641 pS
->ReadUChar( nVAlign
);
2643 HandleAlign(nHAlign
, rSetAlign
);
2645 rRet
.append(" stack {\n");
2646 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, -1, -1 );
2647 int nRemoveFrom
= rRet
.getLength() >= 3 ? rRet
.getLength() - 3 : 0;
2648 rRet
.remove(nRemoveFrom
, 2);
2659 bool MathType::HandleMatrix(int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2661 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
,nVAlign
;
2662 pS
->ReadUChar( nVAlign
);
2663 pS
->ReadUChar( nH_just
);
2664 pS
->ReadUChar( nV_just
);
2665 pS
->ReadUChar( nRows
);
2666 pS
->ReadUChar( nCols
);
2669 int nBytes
= ((nRows
+1)*2)/8;
2670 if (((nRows
+1)*2)%8)
2672 pS
->SeekRel(nBytes
);
2673 nBytes
= ((nCols
+1)*2)/8;
2674 if (((nCols
+1)*2)%8)
2676 pS
->SeekRel(nBytes
);
2677 rRet
.append(" matrix {\n");
2678 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, nRows
, nCols
);
2680 sal_Int32 nI
= rRet
.lastIndexOf('#');
2682 if (rRet
[nI
-1] != '#') //missing column
2685 rRet
.append("\n} ");
2689 bool MathType::HandleTemplate(int nLevel
, sal_uInt8
&rSelector
,
2690 sal_uInt8
&rVariation
, sal_Int32
&rLastTemplateBracket
)
2692 sal_uInt8 nOption
; //This appears utterly unused
2693 pS
->ReadUChar( rSelector
);
2694 pS
->ReadUChar( rVariation
);
2695 pS
->ReadUChar( nOption
);
2696 OSL_ENSURE(rSelector
< 48,"Selector out of range");
2697 if ((rSelector
>= 21) && (rSelector
<=26))
2699 OSL_ENSURE(nOption
< 2,"Option out of range");
2701 else if (rSelector
<= 12)
2703 OSL_ENSURE(nOption
< 3,"Option out of range");
2706 //For the (broken) case where one subscript template ends, and there is
2707 //another one after it, mathtype handles it as if the second one was
2708 //inside the first one and renders it as sub of sub
2710 if ( (rSelector
== 0xf) && (rLastTemplateBracket
!= -1) )
2713 for (sal_Int32 nI
= rLastTemplateBracket
+1; nI
< rRet
.getLength(); nI
++ )
2714 if (rRet
[nI
] != ' ')
2722 bool bRet
= HandleRecords( nLevel
+1, rSelector
, rVariation
);
2726 if (rLastTemplateBracket
< rRet
.getLength())
2727 rRet
.remove(rLastTemplateBracket
, 1);
2729 rLastTemplateBracket
= -1;
2731 if (rSelector
== 0xf)
2732 rLastTemplateBracket
= rRet
.lastIndexOf('}');
2734 rLastTemplateBracket
= -1;
2736 rSelector
= sal::static_int_cast
< sal_uInt8
>(-1);
2740 void MathType::HandleEmblishments()
2745 pS
->ReadUChar( nEmbel
);
2751 rRet
.append(" dot ");
2754 rRet
.append(" ddot ");
2757 rRet
.append(" dddot ");
2762 sPost
.append(" sup {}");
2763 nPostSup
= sPost
.getLength();
2765 sPost
.insert(nPostSup
-1," ' ");
2771 sPost
.append(" sup {}");
2772 nPostSup
= sPost
.getLength();
2774 sPost
.insert(nPostSup
-1," '' ");
2780 sPost
.append(" lsup {}");
2781 nPostlSup
= sPost
.getLength();
2783 sPost
.insert(nPostlSup
-1," ' ");
2787 rRet
.append(" tilde ");
2790 rRet
.append(" hat ");
2793 rRet
.append(" vec ");
2796 rRet
.append(" overstrike ");
2799 rRet
.append(" bar ");
2804 sPost
.append(" sup {}");
2805 nPostSup
= sPost
.getLength();
2807 sPost
.insert(nPostSup
-1," ''' ");
2811 rRet
.append(" breve ");
2814 OSL_ENSURE(nEmbel
< 21,"Embel out of range");
2822 void MathType::HandleSetSize()
2825 pS
->ReadUChar(nTemp
);
2829 pS
->ReadInt16( nLSize
);
2833 pS
->ReadUChar( nTemp
);
2835 pS
->ReadInt16( nDSize
);
2839 pS
->ReadUChar( nTemp
);
2845 bool MathType::HandleChar(sal_Int32
&rTextStart
, int &rSetSize
, int nLevel
,
2846 sal_uInt8 nTag
, sal_uInt8 nSelector
, sal_uInt8 nVariation
, bool bSilent
)
2848 sal_Unicode
nChar(0);
2853 //This is a candidate for function recognition, whatever
2857 sal_uInt8 nOldTypeFace
= nTypeFace
;
2858 pS
->ReadUChar( nTypeFace
);
2861 sal_uInt8
nChar8(0);
2862 pS
->ReadUChar( nChar8
);
2866 pS
->ReadUtf16( nChar
);
2869 bad character, old mathtype < 3 has these
2876 //A bit tricky, the character emblishments for
2877 //mathtype can all be listed after each other, in
2878 //starmath some must go before the character and some
2879 //must go after. In addition some of the emblishments
2880 //may repeated and in starmath some of these groups
2881 //must be gathered together. sPost is the portion that
2882 //follows the char and nPostSup and nPostlSup are the
2883 //indexes at which this class of emblishment is
2886 nPostSup
= nPostlSup
= 0;
2887 int nOriglen
=rRet
.getLength()-rTextStart
;
2888 rRet
.append(" {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2889 if ((!bSilent
) && (nOriglen
> 1))
2891 bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
);
2897 TypeFaceToString(aStr
,nOldTypeFace
);
2899 rRet
.insert(std::min(rTextStart
, rRet
.getLength()), aStr
);
2902 TypeFaceToString(aStr
,nTypeFace
);
2903 rRet
.append(aStr
+ "{");
2907 rTextStart
= rRet
.getLength();
2913 sal_Int32 nOldLen
= rRet
.getLength();
2915 HandleSize(nLSize
,nDSize
,rSetSize
) ||
2916 (nOldTypeFace
!= nTypeFace
)
2919 if ((nOldLen
- rTextStart
) > 1)
2921 rRet
.insert(nOldLen
, "\"");
2923 TypeFaceToString(aStr
,nOldTypeFace
);
2925 rRet
.insert(rTextStart
,aStr
);
2927 rTextStart
= rRet
.getLength();
2929 nOldLen
= rRet
.getLength();
2930 if (!LookupChar(nChar
,rRet
,nVersion
,nTypeFace
))
2932 if (nOldLen
- rTextStart
> 1)
2934 rRet
.insert(nOldLen
, "\"");
2936 TypeFaceToString(aStr
,nOldTypeFace
);
2938 rRet
.insert(rTextStart
, aStr
);
2940 rTextStart
= rRet
.getLength();
2942 lcl_PrependDummyTerm(rRet
, rTextStart
);
2945 if ((xfEMBELL(nTag
)) && (!bSilent
))
2947 rRet
.append("}}" + sPost
); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2948 rTextStart
= rRet
.getLength();
2953 bool MathType::HandleLim(SmNode
*pNode
,int nLevel
)
2956 //Special case for the "lim" option in StarMath
2957 if ((pNode
->GetToken().eType
== TLIM
)
2958 || (pNode
->GetToken().eType
== TLIMSUP
)
2959 || (pNode
->GetToken().eType
== TLIMINF
)
2962 if (pNode
->GetSubNode(1))
2964 sal_uInt8 nVariation2
=HandleCScript(pNode
->GetSubNode(0),nullptr,
2967 pS
->WriteUChar( 0x0A );
2968 pS
->WriteUChar( LINE
); //line
2969 pS
->WriteUChar( CHAR
|0x10 );
2970 pS
->WriteUChar( 0x82 );
2971 pS
->WriteUInt16( 'l' );
2972 pS
->WriteUChar( CHAR
|0x10 );
2973 pS
->WriteUChar( 0x82 );
2974 pS
->WriteUInt16( 'i' );
2975 pS
->WriteUChar( CHAR
|0x10 );
2976 pS
->WriteUChar( 0x82 );
2977 pS
->WriteUInt16( 'm' );
2979 if (pNode
->GetToken().eType
== TLIMSUP
)
2981 pS
->WriteUChar( CHAR
); //some space
2982 pS
->WriteUChar( 0x98 );
2983 pS
->WriteUInt16( 0xEB04 );
2985 pS
->WriteUChar( CHAR
|0x10 );
2986 pS
->WriteUChar( 0x82 );
2987 pS
->WriteUInt16( 's' );
2988 pS
->WriteUChar( CHAR
|0x10 );
2989 pS
->WriteUChar( 0x82 );
2990 pS
->WriteUInt16( 'u' );
2991 pS
->WriteUChar( CHAR
|0x10 );
2992 pS
->WriteUChar( 0x82 );
2993 pS
->WriteUInt16( 'p' );
2995 else if (pNode
->GetToken().eType
== TLIMINF
)
2997 pS
->WriteUChar( CHAR
); //some space
2998 pS
->WriteUChar( 0x98 );
2999 pS
->WriteUInt16( 0xEB04 );
3001 pS
->WriteUChar( CHAR
|0x10 );
3002 pS
->WriteUChar( 0x82 );
3003 pS
->WriteUInt16( 'i' );
3004 pS
->WriteUChar( CHAR
|0x10 );
3005 pS
->WriteUChar( 0x82 );
3006 pS
->WriteUInt16( 'n' );
3007 pS
->WriteUChar( CHAR
|0x10 );
3008 pS
->WriteUChar( 0x82 );
3009 pS
->WriteUInt16( 'f' );
3013 pS
->WriteUChar( CHAR
); //some space
3014 pS
->WriteUChar( 0x98 );
3015 pS
->WriteUInt16( 0xEB04 );
3017 if (nVariation2
!= 0xff)
3019 pS
->WriteUChar( END
);
3020 pS
->WriteUChar( END
);
3022 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
3029 void MathType::HandleMAlign(SmNode
*pNode
,int nLevel
)
3031 sal_uInt8 nPushedHAlign
=nHAlign
;
3032 switch(pNode
->GetToken().eType
)
3044 size_t nSize
= pNode
->GetNumSubNodes();
3045 for (size_t i
= 0; i
< nSize
; ++i
)
3047 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
3048 HandleNodes(pTemp
,nLevel
+1);
3050 nHAlign
=nPushedHAlign
;
3053 void MathType::HandleMath(SmNode
*pNode
)
3055 if (pNode
->GetToken().eType
== TMLINE
)
3057 pS
->WriteUChar( END
);
3058 pS
->WriteUChar( LINE
);
3059 bIsReInterpBrace
=true;
3062 SmMathSymbolNode
*pTemp
= static_cast<SmMathSymbolNode
*>(pNode
);
3063 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3065 sal_Unicode nArse
= SmTextNode::ConvertSymbolToUnicode(pTemp
->GetText()[i
]);
3066 if ((nArse
== 0x2224) || (nArse
== 0x2288) || (nArse
== 0x2285) ||
3069 pS
->WriteUChar( CHAR
|0x20 );
3071 else if (nPendingAttributes
&&
3072 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3074 pS
->WriteUChar( 0x22 );
3077 pS
->WriteUChar( CHAR
); //char without formula recognition
3078 //The typeface seems to be MTEXTRA for unicode characters,
3079 //though how to determine when mathtype chooses one over
3080 //the other is unknown. This should do the trick
3083 if ( (nArse
== 0x2213) || (nArse
== 0x2218) ||
3084 (nArse
== 0x210F) || (
3085 (nArse
>= 0x22EE) && (nArse
<= 0x22FF)
3088 nBias
= 0xB; //typeface
3090 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3091 nBias
= 0x2; //typeface
3092 else if ((nArse
> 0x2000) || (nArse
== 0x00D7))
3093 nBias
= 0x6; //typeface
3094 else if (nArse
== 0x3d1)
3096 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3097 nBias
= 0xB; //typeface
3099 nBias
= 0x3; //typeface
3101 pS
->WriteUChar( nSpec
+nBias
+128 ); //typeface
3103 if (nArse
== 0x2224)
3105 pS
->WriteUInt16( 0x7C );
3106 pS
->WriteUChar( EMBEL
);
3107 pS
->WriteUChar( 0x0A );
3108 pS
->WriteUChar( END
); //end embel
3109 pS
->WriteUChar( END
); //end embel
3111 else if (nArse
== 0x2225)
3112 pS
->WriteUInt16( 0xEC09 );
3113 else if (nArse
== 0xE421)
3114 pS
->WriteUInt16( 0x2265 );
3115 else if (nArse
== 0x230A)
3116 pS
->WriteUInt16( 0xF8F0 );
3117 else if (nArse
== 0x230B)
3118 pS
->WriteUInt16( 0xF8FB );
3119 else if (nArse
== 0xE425)
3120 pS
->WriteUInt16( 0x2264 );
3121 else if (nArse
== 0x226A)
3123 pS
->WriteUInt16( 0x3C );
3124 pS
->WriteUChar( CHAR
);
3125 pS
->WriteUChar( 0x98 );
3126 pS
->WriteUInt16( 0xEB01 );
3127 pS
->WriteUChar( CHAR
);
3128 pS
->WriteUChar( 0x86 );
3129 pS
->WriteUInt16( 0x3c );
3131 else if (nArse
== 0x2288)
3133 pS
->WriteUInt16( 0x2286 );
3134 pS
->WriteUChar( EMBEL
);
3135 pS
->WriteUChar( 0x0A );
3136 pS
->WriteUChar( END
); //end embel
3137 pS
->WriteUChar( END
); //end embel
3139 else if (nArse
== 0x2289)
3141 pS
->WriteUInt16( 0x2287 );
3142 pS
->WriteUChar( EMBEL
);
3143 pS
->WriteUChar( 0x0A );
3144 pS
->WriteUChar( END
); //end embel
3145 pS
->WriteUChar( END
); //end embel
3147 else if (nArse
== 0x2285)
3149 pS
->WriteUInt16( 0x2283 );
3150 pS
->WriteUChar( EMBEL
);
3151 pS
->WriteUChar( 0x0A );
3152 pS
->WriteUChar( END
); //end embel
3153 pS
->WriteUChar( END
); //end embel
3156 pS
->WriteUInt16( nArse
);
3158 nPendingAttributes
= 0;
3161 void MathType::HandleAttributes(SmNode
*pNode
,int nLevel
)
3163 int nOldPending
= 0;
3164 SmNode
*pTemp
= nullptr;
3165 SmTextNode
*pIsText
= nullptr;
3167 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
3169 pIsText
= static_cast<SmTextNode
*>(pNode
->GetSubNode(1));
3171 switch (pTemp
->GetToken().eType
)
3174 //there's just no way we can now handle any character
3175 //attributes (from mathtypes perspective) centered
3176 //over an expression but above template attributes
3177 //such as widevec and similar constructs
3178 //we have to drop them
3179 nOldPending
= StartTemplate(0x2f,0x01);
3181 case TCHECK
: //Not Exportable
3182 case TACUTE
: //Not Exportable
3183 case TGRAVE
: //Not Exportable
3184 case TCIRCLE
: //Not Exportable
3185 case TWIDEHARPOON
: //Not Exportable
3186 case TWIDETILDE
: //Not Exportable
3187 case TWIDEHAT
: //Not Exportable
3190 nOldPending
= StartTemplate(0x10);
3192 case TOVERLINE
: //If the next node is not text
3193 //or text with more than one char
3195 pIsText
->GetToken().eType
!= TTEXT
||
3196 pIsText
->GetText().getLength() > 1)
3197 nOldPending
= StartTemplate(0x11);
3200 nPendingAttributes
++;
3206 HandleNodes(pIsText
,nLevel
+1);
3210 switch (pTemp
->GetToken().eType
)
3214 EndTemplate(nOldPending
);
3218 pIsText
->GetToken().eType
!= TTEXT
||
3219 pIsText
->GetText().getLength() > 1)
3220 EndTemplate(nOldPending
);
3227 //if there was no suitable place to put the attribute,
3228 //then we have to just give up on it
3229 if (nPendingAttributes
)
3230 nPendingAttributes
--;
3233 if ((nInsertion
!= 0) && nullptr != (pTemp
= pNode
->GetSubNode(0)))
3235 auto nPos
= pS
->Tell();
3237 pS
->Seek(nInsertion
);
3238 switch(pTemp
->GetToken().eType
)
3240 case TACUTE
: //Not Exportable
3241 case TGRAVE
: //Not Exportable
3242 case TCIRCLE
: //Not Exportable
3245 pS
->WriteUChar( 2 );
3248 pS
->WriteUChar( 3 );
3251 pS
->WriteUChar( 4 );
3254 pS
->WriteUChar( 8 );
3257 pS
->WriteUChar( 9 );
3260 pS
->WriteUChar( 11 );
3263 pS
->WriteUChar( 16 );
3267 (pIsText
->GetToken().eType
== TTEXT
&&
3268 pIsText
->GetText().getLength() == 1))
3269 pS
->WriteUChar( 17 );
3272 pS
->WriteUChar( 20 );
3281 pS
->WriteUChar( 17 );
3284 pS
->WriteUChar( 2 );
3292 void MathType::HandleText(SmNode
*pNode
)
3294 SmTextNode
*pTemp
= static_cast<SmTextNode
*>(pNode
);
3295 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3297 if (nPendingAttributes
&&
3298 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3300 pS
->WriteUChar( 0x22 ); //char, with attributes right
3301 //after the character
3304 pS
->WriteUChar( CHAR
);
3306 sal_uInt8 nFace
= 0x1;
3307 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3309 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3311 pS
->WriteUChar( nFace
+128 ); //typeface
3312 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3313 pS
->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar
) );
3315 //Mathtype can only have these sort of character
3316 //attributes on a single character, starmath can put them
3317 //anywhere, when the entity involved is a text run this is
3318 //a large effort to place the character attribute on the
3319 //central mathtype character so that it does pretty much
3320 //what the user probably has in mind. The attributes
3321 //filled in here are dummy ones which are replaced in the
3322 //ATTRIBUTE handler if a suitable location for the
3323 //attributes was found here. Unfortunately it is
3324 //possible for starmath to place character attributes on
3325 //entities which cannot occur in mathtype e.g. a Summation
3326 //symbol so these attributes may be lost
3327 if (nPendingAttributes
&&
3328 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3330 pS
->WriteUChar( EMBEL
);
3331 while (nPendingAttributes
)
3333 pS
->WriteUChar( 2 );
3334 //wedge the attributes in here and clear
3336 nPendingAttributes
--;
3338 nInsertion
=pS
->Tell();
3339 pS
->WriteUChar( END
); //end embel
3340 pS
->WriteUChar( END
); //end embel
3345 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportMathType(SvStream
&rStream
)
3347 OUStringBuffer sText
;
3348 MathType
aEquation(sText
);
3352 bRet
= aEquation
.Parse(&rStream
);
3354 catch (const std::out_of_range
&)
3360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */