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>
27 #include "eqnolefilehdr.hxx"
32 //These are the default MathType sizes
33 aSizeTable
.push_back(12);
34 aSizeTable
.push_back(8);
35 aSizeTable
.push_back(6);
36 aSizeTable
.push_back(24);
37 aSizeTable
.push_back(10);
38 aSizeTable
.push_back(12);
39 aSizeTable
.push_back(12);
42 These are the default MathType italic/bold settings If mathtype is changed
43 from its defaults, there is nothing we can do, as this information is not
44 stored in the document
47 for(sal_uInt8 i
=1;i
<=11;i
++)
63 aUserStyles
.insert(aFont
);
68 /*ToDo replace with table rather than switch, returns
69 sal_True in the case that the char is just a char, and
70 sal_False if the character is an operator which must not be
71 placed inside the quote sequence designed to protect
72 against being parsed as a keyword
74 General solution required to force starmath to handle
75 unicode math chars the way it handles its own math
76 chars rather than handle them as text as it will do
77 for the default case below, i.e. incorrect spacing
78 between math symbols and ordinary text e.g. 1=2 rather
81 bool MathType::LookupChar(sal_Unicode nChar
,OUStringBuffer
&rRet
,sal_uInt8 nVersion
,
85 const char *pC
= nullptr;
113 if ((nVersion
< 3) && (nTypeFace
== 0x86))
117 rRet
.append(OUStringLiteral1(nChar
));
122 if ((nVersion
< 3) && (nTypeFace
== 0x81))
124 rRet
.append(OUStringLiteral1(nChar
));
128 if ((nVersion
< 3) && (nTypeFace
== 0x84))
130 rRet
.append(OUStringLiteral1(nChar
));
134 if ((nVersion
< 3) && (nTypeFace
== 0x84))
136 rRet
.append(OUStringLiteral1(nChar
));
140 if ((nVersion
< 3) && (nTypeFace
== 0x84))
142 rRet
.append(OUStringLiteral1(nChar
));
146 if ((nVersion
< 3) && (nTypeFace
== 0x84))
148 rRet
.append(OUStringLiteral1(nChar
));
152 if ((nVersion
< 3) && (nTypeFace
== 0x84))
154 rRet
.append(OUStringLiteral1(nChar
));
158 if ((nVersion
< 3) && (nTypeFace
== 0x84))
160 rRet
.append(OUStringLiteral1(nChar
));
164 if ((nVersion
< 3) && (nTypeFace
== 0x82))
166 rRet
.append(OUStringLiteral1(nChar
));
170 if ((nVersion
< 3) && (nTypeFace
== 0x86))
174 rRet
.append(OUStringLiteral1(nChar
));
179 if ((nVersion
< 3) && (nTypeFace
== 0x86))
183 rRet
.append(OUStringLiteral1(nChar
));
188 if ((nVersion
< 3) && (nTypeFace
== 0x86))
192 rRet
.append(OUStringLiteral1(nChar
));
197 if ((nVersion
< 3) && (nTypeFace
== 0x85))
201 rRet
.append(OUStringLiteral1(nChar
));
356 pC
= " intersection ";
405 pC
= " preccurlyeq ";
408 pC
= " succcurlyeq ";
449 rRet
.append(" ").append(OUStringLiteral1(nChar
)).append(" ");
503 case 0xeb01: //no space
504 case 0xeb08: //normal space
507 case 0xef04: //tiny space
508 case 0xef05: //tiny space
509 case 0xeb02: //small space
510 case 0xeb04: //medium space
513 case 0xeb05: //large space
520 rRet
.append(OUStringLiteral1(nChar
));
525 rRet
.appendAscii(pC
);
529 void MathTypeFont::AppendStyleToText(OUString
&rRet
)
531 const char *pC
= nullptr;
548 rRet
+= OUString::createFromAscii( pC
);
551 void MathType::TypeFaceToString(OUString
&rTxt
,sal_uInt8 nFace
)
553 MathTypeFont
aFont(nFace
);
554 MathTypeFontSet::iterator aItr
= aUserStyles
.find(aFont
);
555 if (aItr
!= aUserStyles
.end())
556 aFont
.nStyle
= aItr
->nStyle
;
557 aFont
.AppendStyleToText(rTxt
);
560 bool MathType::Parse(SotStorage
*pStor
)
562 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(
564 StreamMode::STD_READ
);
565 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
567 return Parse(xSrc
.get());
570 bool MathType::Parse(SvStream
* pStream
)
573 pS
->SetEndian( SvStreamEndian::LITTLE
);
577 sal_uInt8 nProdVersion
;
578 sal_uInt8 nProdSubVersion
;
581 pS
->ReadUChar( nVersion
);
582 pS
->ReadUChar( nPlatform
);
583 pS
->ReadUChar( nProduct
);
584 pS
->ReadUChar( nProdVersion
);
585 pS
->ReadUChar( nProdSubVersion
);
587 if (nVersion
> 3) // allow only supported versions of MathType to be parsed
590 bool bRet
= HandleRecords(0);
591 //little crude hack to close occasionally open expressions
592 //a sophisticated system to determine what expressions are
593 //opened is required, but this is as much work as rewriting
594 //starmaths internals.
600 static void lcl_PrependDummyTerm(OUStringBuffer
&rRet
, sal_Int32
&rTextStart
)
602 if ((rTextStart
< rRet
.getLength()) &&
603 (rRet
[rTextStart
] == '=') &&
604 ((rTextStart
== 0) || (rRet
[ rTextStart
-1 ] == '{'))
607 rRet
.insert(rTextStart
, " {}");
612 static void lcl_AppendDummyTerm(OUStringBuffer
&rRet
)
615 for(int nI
=rRet
.getLength()-1;nI
>= 0; nI
--)
617 sal_Int32 nIdx
= sal::static_int_cast
< sal_Int32
>(nI
);
618 sal_Unicode nChar
= rRet
[nIdx
];
621 if (rRet
[nIdx
] != '{')
625 if (!bOk
) //No term, use dummy
629 void MathType::HandleNudge()
632 pS
->ReadUChar( nXNudge
);
634 pS
->ReadUChar( nYNudge
);
635 if (nXNudge
== 128 && nYNudge
== 128)
637 sal_uInt16 nXLongNudge
;
638 sal_uInt16 nYLongNudge
;
639 pS
->ReadUInt16( nXLongNudge
);
640 pS
->ReadUInt16( nYLongNudge
);
644 /* Fabulously complicated as many tokens have to be reordered and generally
645 * moved around from mathtypes paradigm to starmaths. */
646 bool MathType::HandleRecords(int nLevel
, sal_uInt8 nSelector
,
647 sal_uInt8 nVariation
, int nMatrixRows
, int nMatrixCols
)
653 sal_uInt8 nTag
,nRecord
;
654 sal_uInt8 nTabType
,nTabStops
;
655 sal_uInt16 nTabOffset
;
659 OUString sPush
,sMainTerm
;
660 int nSetSize
=0,nSetAlign
=0;
661 int nCurRow
=0,nCurCol
=0;
662 bool bOpenString
=false;
663 sal_Int32 nTextStart
= 0;
664 sal_Int32 nSubSupStartPos
= 0;
665 sal_Int32 nLastTemplateBracket
=-1;
671 pS
->ReadUChar( nTag
);
674 /*MathType strings can of course include words which
675 *are StarMath keywords, the simplest solution is
676 to escape strings of greater than len 1 with double
677 quotes to avoid scanning the TokenTable for matches
679 Unfortunately it may turn out that the string gets
680 split during the handling of a character emblishment
681 so this special case must be handled in the
682 character handler case 2:
684 if ((nRecord
== CHAR
) && (!bOpenString
))
687 nTextStart
= rRet
.getLength();
689 else if ((nRecord
!= CHAR
) && bOpenString
)
692 if ((rRet
.getLength() - nTextStart
) > 1)
695 TypeFaceToString(aStr
,nTypeFace
);
697 rRet
.insert(nTextStart
,aStr
);
700 else if (nRecord
== END
&& !rRet
.isEmpty())
702 sal_Unicode cChar
= 0;
703 sal_Int32 nI
= rRet
.getLength()-1;
704 while (nI
&& ((cChar
= rRet
[nI
]) == ' '))
706 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
719 rRet
.append("\nnewline\n");
726 rRet
.append(" langle ");
727 else if (nVariation
==1)
728 rRet
.append(" \\langle ");
732 rRet
.append(" left (");
733 else if (nVariation
==1)
737 if ((nVariation
==0) || (nVariation
==1))
738 rRet
.append(" left lbrace ");
740 rRet
.append(" left none ");
744 rRet
.append(" left [");
745 else if (nVariation
==1)
754 rRet
.append(" lline ");
755 else if (nVariation
==1)
756 rRet
.append(" \\lline ");
760 rRet
.append(" ldline ");
761 else if (nVariation
==1)
762 rRet
.append(" \\ldline ");
765 if (nVariation
== 0 || nVariation
== 1)
766 rRet
.append(" left lfloor ");
767 else if (nVariation
==1)
768 rRet
.append(" left none ");
772 rRet
.append(" lceil ");
773 else if (nVariation
==1)
774 rRet
.append(" \\lceil ");
787 rRet
.append(" sqrt");
790 rRet
.append(" nroot");
791 sPush
= rRet
.makeStringAndClear();
802 rRet
.append(" over ");
806 nSubSupStartPos
= rRet
.getLength();
807 if ((nVariation
== 0) ||
808 ((nVariation
== 2) && (nPart
==1)))
810 lcl_AppendDummyTerm(rRet
);
811 rRet
.append(" rSup");
813 else if ((nVariation
== 1) ||
814 ((nVariation
== 2) && (nPart
==0)))
816 lcl_AppendDummyTerm(rRet
);
817 rRet
.append(" rSub");
823 rRet
.append(" {underline ");
824 else if (nVariation
== 1)
825 rRet
.append(" {underline underline ");
830 rRet
.append(" {overline ");
831 else if (nVariation
== 1)
832 rRet
.append(" {overline overline ");
839 rRet
.append(" widevec ");//left arrow above
840 else if (nVariation
== 1)
841 rRet
.append(" widevec ");//left arrow below
849 rRet
.append(" widevec ");//right arrow above
850 else if (nVariation
== 1)
851 rRet
.append(" widevec ");//right arrow below
859 rRet
.append(" widevec ");//double arrow above
860 else if (nVariation
== 1)
861 rRet
.append(" widevec ");//double arrow below
868 if ((nVariation
== 3) || (nVariation
== 4))
869 rRet
.append(" lInt");
872 if ( (nVariation
!= 0) && (nVariation
!= 3))
874 sPush
= rRet
.makeStringAndClear();
877 if (((nVariation
== 1) ||
878 (nVariation
== 4)) && (nPart
==1))
879 rRet
.append(" rSub");
880 else if ((nVariation
== 2) && (nPart
==2))
881 rRet
.append(" rSup");
882 else if ((nVariation
== 2) && (nPart
==1))
883 rRet
.append(" rSub");
889 if ((nVariation
== 2) || (nVariation
== 3))
890 rRet
.append(" llInt");
892 rRet
.append(" iInt");
893 if ( (nVariation
!= 0) && (nVariation
!= 2))
895 sPush
= rRet
.makeStringAndClear();
898 if (((nVariation
== 1) ||
899 (nVariation
== 3)) && (nPart
==1))
900 rRet
.append(" rSub");
906 if ((nVariation
== 2) || (nVariation
== 3))
907 rRet
.append(" lllInt");
909 rRet
.append(" iiInt");
910 if ( (nVariation
!= 0) && (nVariation
!= 2))
912 sPush
= rRet
.makeStringAndClear();
915 if (((nVariation
== 1) ||
916 (nVariation
== 3)) && (nPart
==1))
917 rRet
.append(" rSub");
924 rRet
.append(" lInt");
927 sPush
= rRet
.makeStringAndClear();
929 if (((nVariation
== 1) ||
930 (nVariation
== 2)) && (nPart
==1))
931 rRet
.append(" cSub");
932 else if ((nVariation
== 0) && (nPart
==2))
933 rRet
.append(" cSup");
934 else if ((nVariation
== 0) && (nPart
==1))
935 rRet
.append(" cSub");
942 rRet
.append(" llInt");
944 rRet
.append(" iInt");
945 sPush
= rRet
.makeStringAndClear();
948 rRet
.append(" cSub");
955 rRet
.append(" lllInt");
957 rRet
.append(" iiInt");
958 sPush
= rRet
.makeStringAndClear();
961 rRet
.append(" cSub");
974 sPush
= rRet
.makeStringAndClear();
977 if ((nVariation
== 0) && (nPart
==1))
978 rRet
.append(" cSub");
979 else if ((nVariation
== 1) && (nPart
==2))
980 rRet
.append(" cSup");
981 else if ((nVariation
== 1) && (nPart
==1))
982 rRet
.append(" cSub");
989 sPush
= rRet
.makeStringAndClear();
991 if ((nVariation
== 0) && (nPart
==1))
992 rRet
.append(" rSub");
993 else if ((nVariation
== 1) && (nPart
==2))
994 rRet
.append(" rSup");
995 else if ((nVariation
== 1) && (nPart
==1))
996 rRet
.append(" rSub");
1002 rRet
.append(" Prod");
1003 if (nVariation
!= 2)
1005 sPush
= rRet
.makeStringAndClear();
1008 if ((nVariation
== 0) && (nPart
==1))
1009 rRet
.append(" cSub");
1010 else if ((nVariation
== 1) && (nPart
==2))
1011 rRet
.append(" cSup");
1012 else if ((nVariation
== 1) && (nPart
==1))
1013 rRet
.append(" cSub");
1019 rRet
.append(" Prod");
1020 sPush
= rRet
.makeStringAndClear();
1022 if ((nVariation
== 0) && (nPart
==1))
1023 rRet
.append(" rSub");
1024 else if ((nVariation
== 1) && (nPart
==2))
1025 rRet
.append(" rSup");
1026 else if ((nVariation
== 1) && (nPart
==1))
1027 rRet
.append(" rSub");
1033 rRet
.append(" coProd");
1034 if (nVariation
!= 2)
1036 sPush
= rRet
.makeStringAndClear();
1039 if ((nVariation
== 0) && (nPart
==1))
1040 rRet
.append(" cSub");
1041 else if ((nVariation
== 1) && (nPart
==2))
1042 rRet
.append(" cSup");
1043 else if ((nVariation
== 1) && (nPart
==1))
1044 rRet
.append(" cSub");
1050 rRet
.append(" coProd");
1051 sPush
= rRet
.makeStringAndClear();
1053 if ((nVariation
== 0) && (nPart
==1))
1054 rRet
.append(" rSub");
1055 else if ((nVariation
== 1) && (nPart
==2))
1056 rRet
.append(" rSup");
1057 else if ((nVariation
== 1) && (nPart
==1))
1058 rRet
.append(" rSub");
1064 rRet
.append(" union"); //union
1065 if (nVariation
!= 2)
1067 sPush
= rRet
.makeStringAndClear();
1070 if ((nVariation
== 0) && (nPart
==1))
1071 rRet
.append(" cSub");
1072 else if ((nVariation
== 1) && (nPart
==2))
1073 rRet
.append(" cSup");
1074 else if ((nVariation
== 1) && (nPart
==1))
1075 rRet
.append(" cSub");
1081 rRet
.append(" union"); //union
1082 sPush
= rRet
.makeStringAndClear();
1084 if ((nVariation
== 0) && (nPart
==1))
1085 rRet
.append(" rSub");
1086 else if ((nVariation
== 1) && (nPart
==2))
1087 rRet
.append(" rSup");
1088 else if ((nVariation
== 1) && (nPart
==1))
1089 rRet
.append(" rSub");
1095 rRet
.append(" intersect"); //intersect
1096 if (nVariation
!= 2)
1098 sPush
= rRet
.makeStringAndClear();
1101 if ((nVariation
== 0) && (nPart
==1))
1102 rRet
.append(" cSub");
1103 else if ((nVariation
== 1) && (nPart
==2))
1104 rRet
.append(" cSup");
1105 else if ((nVariation
== 1) && (nPart
==1))
1106 rRet
.append(" cSub");
1112 rRet
.append(" intersect"); //intersect
1113 sPush
= rRet
.makeStringAndClear();
1115 if ((nVariation
== 0) && (nPart
==1))
1116 rRet
.append(" rSub");
1117 else if ((nVariation
== 1) && (nPart
==2))
1118 rRet
.append(" rSup");
1119 else if ((nVariation
== 1) && (nPart
==1))
1120 rRet
.append(" rSub");
1124 if ((nVariation
== 0) && (nPart
==1))
1125 rRet
.append(" cSup");
1126 else if ((nVariation
== 1) && (nPart
==1))
1127 rRet
.append(" cSub");
1128 else if ((nVariation
== 2) && (nPart
==1))
1129 rRet
.append(" cSub");
1130 else if ((nVariation
== 2) && (nPart
==2))
1131 rRet
.append(" cSup");
1135 if (nVariation
== 0)
1139 sPush
= rRet
.makeStringAndClear();
1143 if (nVariation
== 0)
1146 rRet
.append("alignr ");
1149 rRet
.append("\\lline ");
1150 if (nVariation
== 1)
1151 rRet
.append("overline ");
1159 sPush
= rRet
.makeStringAndClear();
1161 if ((nVariation
== 0) && (nPart
==0))
1162 rRet
.append(" rSup");
1163 else if ((nVariation
== 2) && (nPart
==1))
1164 rRet
.append(" rSup");
1165 else if ((nVariation
== 1) && (nPart
==0))
1166 rRet
.append(" rSub");
1167 else if ((nVariation
== 2) && (nPart
==0))
1168 rRet
.append(" rSub");
1174 sPush
= rRet
.makeStringAndClear();
1176 if ((nVariation
== 0) && (nPart
==0))
1177 rRet
.append(" cSup");
1178 else if ((nVariation
== 2) && (nPart
==1))
1179 rRet
.append(" cSup");
1180 else if ((nVariation
== 1) && (nPart
==0))
1181 rRet
.append(" cSub");
1182 else if ((nVariation
== 2) && (nPart
==0))
1183 rRet
.append(" cSub");
1188 rRet
.append("\"\"");
1189 if ((nVariation
== 0)
1190 || ((nVariation
== 2) && (nPart
==1)))
1191 rRet
.append(" lSup");
1192 else if ((nVariation
== 1)
1193 || ((nVariation
== 2) && (nPart
==0)))
1194 rRet
.append(" lSub");
1201 rRet
.append(" langle ");
1203 else if (nVariation
==1)
1205 rRet
.append(" \\langle ");
1208 else if (nVariation
==2)
1210 rRet
.append(" \\lline ");
1215 if (nVariation
== 0)
1216 rRet
.append(" widevec ");//left below
1217 else if (nVariation
== 1)
1218 rRet
.append(" widevec ");//right below
1219 else if (nVariation
== 2)
1220 rRet
.append(" widevec ");//double headed below
1224 if (nVariation
== 0)
1225 rRet
.append(" widevec ");//left above
1226 else if (nVariation
== 1)
1227 rRet
.append(" widevec ");//right above
1228 else if (nVariation
== 2)
1229 rRet
.append(" widevec ");//double headed above
1235 sal_Int16 nOldCurSize
=nCurSize
;
1236 sal_Int32 nSizeStartPos
= rRet
.getLength();
1237 HandleSize( nLSize
, nDSize
, nSetSize
);
1238 bRet
= HandleRecords( nLevel
+1 );
1242 sal_Int32 nI
= rRet
.lastIndexOf('{');
1245 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1246 if (rRet
[nI
] != ' ')
1257 else if (rRet
.getLength() > nSizeStartPos
)
1258 rRet
= rRet
.truncate(nSizeStartPos
);
1260 nCurSize
=nOldCurSize
;
1264 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1271 rRet
.append(" rangle ");
1272 else if (nVariation
==2)
1273 rRet
.append(" \\rangle ");
1277 rRet
.append(" right )");
1278 else if (nVariation
==2)
1282 if ((nVariation
==0) || (nVariation
==2))
1283 rRet
.append(" right rbrace ");
1285 rRet
.append(" right none ");
1289 rRet
.append(" right ]");
1290 else if (nVariation
==2)
1295 rRet
.append(" rline ");
1296 else if (nVariation
==2)
1297 rRet
.append(" \\rline ");
1301 rRet
.append(" rdline ");
1302 else if (nVariation
==2)
1303 rRet
.append(" \\rdline ");
1306 if (nVariation
== 0 || nVariation
== 2)
1307 rRet
.append(" right rfloor ");
1308 else if (nVariation
==2)
1309 rRet
.append(" right none ");
1313 rRet
.append(" rceil ");
1314 else if (nVariation
==2)
1315 rRet
.append(" \\rceil ");
1327 if (nVariation
== 1)
1332 sMainTerm
= rRet
.makeStringAndClear();
1334 else if (nPart
== 1)
1336 rRet
.insert(0, sPush
);
1337 rRet
.append(sMainTerm
);
1363 ((nVariation
== 2) || (nVariation
== 1)))
1367 sal_Int32 nI
= rRet
.lastIndexOf('{');
1370 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1371 if (rRet
[nI
] != ' ')
1382 else if (rRet
.getLength() > nSubSupStartPos
)
1383 rRet
= rRet
.truncate(nSubSupStartPos
);
1389 ((nVariation
== 2) || (nVariation
== 1)))
1417 rRet
.append("overbrace");
1426 rRet
.append("underbrace");
1433 else if ((nPart
==1) &&
1434 ((nVariation
== 2) || (nVariation
== 1)))
1441 if (nVariation
== 0)
1445 sMainTerm
= rRet
.makeStringAndClear();
1447 else if (nPart
== 1)
1449 rRet
.insert(0, sPush
);
1450 rRet
.append(" over ").append(sMainTerm
);
1467 rRet
.append("slash");
1470 rRet
.append("wideslash");
1489 if (nVariation
!= 2)
1491 sMainTerm
= rRet
.makeStringAndClear();
1495 else if ((nPart
== 1) && (nVariation
== 0))
1497 rRet
.insert(0, sPush
);
1498 rRet
.append(sMainTerm
);
1503 else if ((nPart
== 1) && (nVariation
== 1))
1505 else if ((nPart
== 2) && (nVariation
== 1))
1507 rRet
.insert(0, sPush
);
1508 rRet
.append(sMainTerm
);
1519 if ((nVariation
!= 0) && (nVariation
!= 3))
1521 sMainTerm
= rRet
.makeStringAndClear();
1525 else if ((nPart
== 1) &&
1526 ((nVariation
== 1) || (nVariation
==4)))
1528 rRet
.insert(0, sPush
);
1529 rRet
.append(sMainTerm
);
1534 else if ((nPart
== 1) && (nVariation
== 2))
1536 else if ((nPart
== 2) && (nVariation
== 2))
1538 rRet
.insert(0, sPush
);
1539 rRet
.append(sMainTerm
);
1551 if ((nVariation
!= 0) && (nVariation
!= 2))
1553 sMainTerm
= rRet
.makeStringAndClear();
1557 else if ((nPart
== 1) &&
1558 ((nVariation
== 1) || (nVariation
==3)))
1560 rRet
.insert(0, sPush
);
1561 rRet
.append(sMainTerm
);
1572 sMainTerm
= rRet
.makeStringAndClear();
1575 else if ((nPart
== 1) &&
1576 ((nVariation
== 1) || (nVariation
==2)))
1578 rRet
.insert(0, sPush
);
1579 rRet
.append(sMainTerm
);
1584 else if ((nPart
== 1) && (nVariation
== 0))
1586 else if ((nPart
== 2) && (nVariation
== 0))
1588 rRet
.insert(0, sPush
);
1589 rRet
.append(sMainTerm
);
1601 sMainTerm
= rRet
.makeStringAndClear();
1604 else if (nPart
== 1)
1606 rRet
.insert(0, sPush
);
1607 rRet
.append(sMainTerm
);
1619 ((nVariation
== 0) || (nVariation
== 1)))
1621 sMainTerm
= rRet
.makeStringAndClear();
1624 else if ((nPart
== 0) && (nVariation
== 2))
1626 else if ((nPart
== 1) && (nVariation
== 2))
1628 sMainTerm
= rRet
.makeStringAndClear();
1631 else if ((nPart
== 2) || ((nPart
== 1) &&
1632 (nVariation
== 0 || nVariation
== 1)))
1634 rRet
.insert(0, sPush
);
1635 rRet
.append(sMainTerm
);
1646 newline
--; //there is another term to arrive
1647 rRet
.append(" mline ");
1650 rRet
.append(" rangle ");
1652 else if (nVariation
==1)
1653 rRet
.append(" \\lline ");
1654 else if (nVariation
==2)
1655 rRet
.append(" \\rangle ");
1661 bSilent
= true; //Skip the optional brackets and/or
1662 //symbols that follow some of these
1663 //records. Foo Data.
1665 /*In matrices and piles we cannot separate equation
1666 *lines with the newline keyword*/
1675 bRet
= HandleChar( nTextStart
, nSetSize
, nLevel
, nTag
, nSelector
, nVariation
, bSilent
);
1680 bRet
= HandleTemplate( nLevel
, nSelector
, nVariation
, nLastTemplateBracket
);
1685 bRet
= HandlePile( nSetAlign
, nLevel
, nSelector
, nVariation
);
1686 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1691 bRet
= HandleMatrix( nLevel
, nSelector
, nVariation
);
1692 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1697 HandleEmblishments();
1700 pS
->ReadUChar( nTabStops
);
1701 for (i
=0;i
<nTabStops
;i
++)
1703 pS
->ReadUChar( nTabType
);
1704 pS
->ReadUInt16( nTabOffset
);
1706 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1711 pS
->ReadUChar( aFont
.nTface
);
1713 The typeface number is the negative (which makes it
1714 positive) of the typeface value (unbiased) that appears in
1715 CHAR records that might follow a given FONT record
1717 aFont
.nTface
= 128-aFont
.nTface
;
1718 pS
->ReadUChar( aFont
.nStyle
);
1719 aUserStyles
.insert(aFont
);
1724 pS
->ReadChar( nChar8
);
1745 while (nRecord
!= END
&& !pS
->eof());
1754 /*Simply determine if we are at the end of a record or the end of a line,
1755 *with fiddly logic to see if we are in a matrix or a pile or neither
1757 Note we cannot tell until after the event that this is the last entry
1758 of a pile, so we must strip the last separator of a pile after this
1759 is detected in the PILE handler
1761 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1762 int &rCurCol
,int &rCurRow
)
1766 if (rCurCol
== nMatrixCols
-1)
1768 if (rCurRow
!= nMatrixRows
-1)
1769 rRet
.append(" {} ##\n");
1770 if (nMatrixRows
!=-1)
1778 rRet
.append(" {} # ");
1779 if (nMatrixRows
!=-1)
1787 /* set the alignment of the following term, but starmath currently
1788 * cannot handle vertical alignment */
1789 void MathType::HandleAlign(sal_uInt8 nHorAlign
, int &rSetAlign
)
1795 rRet
.append("alignl {");
1798 rRet
.append("alignc {");
1801 rRet
.append("alignr {");
1807 /* set size of text, complexity due to overuse of signedness as a flag
1808 * indicator by mathtype file format*/
1809 bool MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1811 const sal_Int16 nDefaultSize
= 12;
1815 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1823 if (-nLstSize
/32 != nLastSize
)
1825 nLastSize
= nCurSize
;
1826 rRet
.append(" size ");
1827 rRet
.append(OUString::number(-nLstSize
/32));
1832 nCurSize
= -nLstSize
/32;
1837 /*sizetable should theoreticaly be filled with the default sizes
1838 *of the various font groupings matching starmaths equivalents
1839 in aTypeFaces, and a test would be done to see if the new font
1840 size would be the same as what starmath would have chosen for
1841 itself anyway in which case the size setting could be ignored*/
1842 nLstSize
= aSizeTable
.at(nLstSize
);
1843 nLstSize
= nLstSize
+ nDefSize
;
1844 if (nLstSize
!= nCurSize
)
1852 if (nLstSize
!= nLastSize
)
1854 nLastSize
= nCurSize
;
1855 rRet
.append(" size ");
1856 rRet
.append(OUString::number(nLstSize
));
1861 nCurSize
= nLstSize
;
1867 bool MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1872 SvStream
*pStream
= rMedium
.GetOutStream();
1875 tools::SvRef
<SotStorage
> pStor
= new SotStorage( pStream
, false );
1877 SvGlobalName
aGName(MSO_EQUATION3_CLASSID
);
1878 pStor
->SetClass( aGName
, SotClipboardFormatId::NONE
, "Microsoft Equation 3.0");
1880 static sal_uInt8
const aCompObj
[] = {
1881 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1882 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1885 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1886 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1887 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1888 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1889 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1890 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1891 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1892 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1895 tools::SvRef
<SotStorageStream
> xStor( pStor
->OpenSotStream("\1CompObj"));
1896 xStor
->WriteBytes(aCompObj
, sizeof(aCompObj
));
1898 static sal_uInt8
const aOle
[] = {
1899 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1901 0x00, 0x00, 0x00, 0x00
1903 tools::SvRef
<SotStorageStream
> xStor2( pStor
->OpenSotStream("\1Ole"));
1904 xStor2
->WriteBytes(aOle
, sizeof(aOle
));
1908 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream("Equation Native");
1909 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
1913 pS
->SetEndian( SvStreamEndian::LITTLE
);
1915 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1916 pS
->WriteUChar( 0x03 );
1917 pS
->WriteUChar( 0x01 );
1918 pS
->WriteUChar( 0x01 );
1919 pS
->WriteUChar( 0x03 );
1920 pS
->WriteUChar( 0x00 );
1921 sal_uInt32 nSize
= pS
->Tell();
1922 nPendingAttributes
=0;
1924 HandleNodes(pTree
, 0);
1925 pS
->WriteUChar( END
);
1927 nSize
= pS
->Tell()-nSize
;
1929 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1939 void MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1941 switch(pNode
->GetType())
1943 case SmNodeType::Attribut
:
1944 HandleAttributes(pNode
,nLevel
);
1946 case SmNodeType::Text
:
1949 case SmNodeType::VerticalBrace
:
1950 HandleVerticalBrace(pNode
,nLevel
);
1952 case SmNodeType::Brace
:
1953 HandleBrace(pNode
,nLevel
);
1955 case SmNodeType::Oper
:
1956 HandleOperator(pNode
,nLevel
);
1958 case SmNodeType::BinVer
:
1959 HandleFractions(pNode
,nLevel
);
1961 case SmNodeType::Root
:
1962 HandleRoot(pNode
,nLevel
);
1964 case SmNodeType::Special
:
1966 SmTextNode
*pText
= static_cast<SmTextNode
*>(pNode
);
1967 //if the token str and the result text are the same then this
1968 //is to be seen as text, else assume it's a mathchar
1969 if (pText
->GetText() == pText
->GetToken().aText
)
1975 case SmNodeType::Math
:
1976 case SmNodeType::MathIdent
:
1979 case SmNodeType::SubSup
:
1980 HandleSubSupScript(pNode
,nLevel
);
1982 case SmNodeType::Expression
:
1984 size_t nSize
= pNode
->GetNumSubNodes();
1985 for (size_t i
= 0; i
< nSize
; ++i
)
1987 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1988 HandleNodes(pTemp
,nLevel
+1);
1992 case SmNodeType::Table
:
1993 //Root Node, PILE equivalent, i.e. vertical stack
1994 HandleTable(pNode
,nLevel
);
1996 case SmNodeType::Matrix
:
1997 HandleSmMatrix(static_cast<SmMatrixNode
*>(pNode
),nLevel
);
1999 case SmNodeType::Line
:
2001 pS
->WriteUChar( 0x0a );
2002 pS
->WriteUChar( LINE
);
2003 size_t nSize
= pNode
->GetNumSubNodes();
2004 for (size_t i
= 0; i
< nSize
; ++i
)
2006 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2007 HandleNodes(pTemp
,nLevel
+1);
2009 pS
->WriteUChar( END
);
2012 case SmNodeType::Align
:
2013 HandleMAlign(pNode
,nLevel
);
2015 case SmNodeType::Blank
:
2016 pS
->WriteUChar( CHAR
);
2017 pS
->WriteUChar( 0x98 );
2018 if (pNode
->GetToken().eType
== TSBLANK
)
2019 pS
->WriteUInt16( 0xEB04 );
2021 pS
->WriteUInt16( 0xEB05 );
2025 size_t nSize
= pNode
->GetNumSubNodes();
2026 for (size_t i
= 0; i
< nSize
; ++i
)
2028 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2029 HandleNodes(pTemp
,nLevel
+1);
2037 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2039 int nOldPending
=nPendingAttributes
;
2040 pS
->WriteUChar( TMPL
); //Template
2041 pS
->WriteUChar( nSelector
); //selector
2042 pS
->WriteUChar( nVariation
); //variation
2043 pS
->WriteUChar( 0x00 ); //options
2044 pS
->WriteUChar( LINE
);
2045 //there's just no way we can now handle any character
2046 //attributes (from mathtypes perspective) centered
2047 //over an expression but above template attribute
2048 //such as widevec and similar constructs
2049 //we have to drop them
2050 nPendingAttributes
=0;
2054 void MathType::EndTemplate(int nOldPendingAttributes
)
2056 pS
->WriteUChar( END
); //end line
2057 pS
->WriteUChar( END
); //end template
2058 nPendingAttributes
=nOldPendingAttributes
;
2062 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2064 pS
->WriteUChar( MATRIX
);
2065 pS
->WriteUChar( 0x00 ); //vAlign ?
2066 pS
->WriteUChar( 0x00 ); //h_just
2067 pS
->WriteUChar( 0x00 ); //v_just
2068 pS
->WriteUChar( pMatrix
->GetNumRows() ); //v_just
2069 pS
->WriteUChar( pMatrix
->GetNumCols() ); //v_just
2070 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2071 if (((pMatrix
->GetNumRows()+1)*2)%8)
2073 for (int j
= 0; j
< nBytes
; j
++)
2074 pS
->WriteUChar( 0x00 ); //row_parts
2075 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2076 if (((pMatrix
->GetNumCols()+1)*2)%8)
2078 for (int k
= 0; k
< nBytes
; k
++)
2079 pS
->WriteUChar( 0x00 ); //col_parts
2080 size_t nSize
= pMatrix
->GetNumSubNodes();
2081 for (size_t i
= 0; i
< nSize
; ++i
)
2083 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2085 pS
->WriteUChar( LINE
); //line
2086 HandleNodes(pTemp
,nLevel
+1);
2087 pS
->WriteUChar( END
); //end line
2090 pS
->WriteUChar( END
);
2094 //Root Node, PILE equivalent, i.e. vertical stack
2095 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2097 size_t nSize
= pNode
->GetNumSubNodes();
2098 //The root of the starmath is a table, if
2099 //we convert this them each iteration of
2100 //conversion from starmath to mathtype will
2101 //add an extra unnecessary level to the
2102 //mathtype output stack which would grow
2103 //without bound in a multi step conversion
2106 pS
->WriteUChar( 0x0A ); //initial size
2108 if ( nLevel
|| (nSize
>1))
2110 pS
->WriteUChar( PILE
);
2111 pS
->WriteUChar( nHAlign
); //vAlign ?
2112 pS
->WriteUChar( 0x01 ); //hAlign
2115 for (size_t i
= 0; i
< nSize
; ++i
)
2117 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2119 pS
->WriteUChar( LINE
);
2120 HandleNodes(pTemp
,nLevel
+1);
2121 pS
->WriteUChar( END
);
2124 if (nLevel
|| (nSize
>1))
2125 pS
->WriteUChar( END
);
2129 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2132 pS
->WriteUChar( TMPL
); //Template
2133 pS
->WriteUChar( 0x0D ); //selector
2134 if (pNode
->GetSubNode(0))
2135 pS
->WriteUChar( 0x01 ); //variation
2137 pS
->WriteUChar( 0x00 ); //variation
2138 pS
->WriteUChar( 0x00 ); //options
2140 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2142 pS
->WriteUChar( LINE
); //line
2143 HandleNodes(pTemp
,nLevel
+1);
2144 pS
->WriteUChar( END
);
2147 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2149 pS
->WriteUChar( LINE
); //line
2150 HandleNodes(pTemp
,nLevel
+1);
2151 pS
->WriteUChar( END
);
2154 pS
->WriteUChar( LINE
|0x10 ); //dummy line
2157 pS
->WriteUChar( END
);
2160 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2161 sal_uInt64
*pPos
,bool bTest
)
2163 sal_uInt8 nVariation2
=0xff;
2165 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2168 if (pNode
->GetSubNode(CSUB
+1))
2171 else if (pNode
->GetSubNode(CSUB
+1))
2174 if (nVariation2
!=0xff)
2178 pS
->WriteUChar( TMPL
); //Template
2179 pS
->WriteUChar( 0x2B ); //selector
2180 pS
->WriteUChar( nVariation2
);
2181 pS
->WriteUChar( 0x00 ); //options
2185 pS
->WriteUChar( LINE
); //line
2186 HandleNodes(pContent
,nLevel
+1);
2187 pS
->WriteUChar( END
); //line
2190 pS
->WriteUChar( LINE
|0x10 );
2192 pS
->WriteUChar( 0x0B );
2195 if (nullptr != (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2197 pS
->WriteUChar( LINE
); //line
2198 HandleNodes(pTemp
,nLevel
+1);
2199 pS
->WriteUChar( END
); //line
2202 pS
->WriteUChar( LINE
|0x10 );
2203 if (bTest
&& nullptr != (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2205 pS
->WriteUChar( LINE
); //line
2206 HandleNodes(pTemp
,nLevel
+1);
2207 pS
->WriteUChar( END
); //line
2210 pS
->WriteUChar( LINE
|0x10 );
2217 Sub and Sup scripts and another problem area, StarMath
2218 can have all possible options used at the same time, whereas
2219 Mathtype cannot. The ordering of the nodes for each system
2220 is quite different as well leading to some complexity
2222 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2224 sal_uInt8 nVariation
=0xff;
2225 if (pNode
->GetSubNode(LSUP
+1))
2228 if (pNode
->GetSubNode(LSUB
+1))
2231 else if ( nullptr != pNode
->GetSubNode(LSUB
+1) )
2235 if (nVariation
!=0xff)
2237 pS
->WriteUChar( TMPL
); //Template
2238 pS
->WriteUChar( 0x2c ); //selector
2239 pS
->WriteUChar( nVariation
);
2240 pS
->WriteUChar( 0x00 ); //options
2241 pS
->WriteUChar( 0x0B );
2243 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2245 pS
->WriteUChar( LINE
); //line
2246 HandleNodes(pTemp
,nLevel
+1);
2247 pS
->WriteUChar( END
); //line
2250 pS
->WriteUChar( LINE
|0x10 );
2251 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2253 pS
->WriteUChar( LINE
); //line
2254 HandleNodes(pTemp
,nLevel
+1);
2255 pS
->WriteUChar( END
); //line
2258 pS
->WriteUChar( LINE
|0x10 );
2259 pS
->WriteUChar( END
);
2264 sal_uInt8 nVariation2
=HandleCScript(pNode
,nullptr,nLevel
);
2266 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2268 HandleNodes(pTemp
,nLevel
+1);
2271 if (nVariation2
!= 0xff)
2272 pS
->WriteUChar( END
);
2274 if (nullptr != (pNode
->GetSubNode(RSUP
+1)))
2277 if (pNode
->GetSubNode(RSUB
+1))
2280 else if (nullptr != pNode
->GetSubNode(RSUB
+1))
2283 if (nVariation
!=0xff)
2285 pS
->WriteUChar( TMPL
); //Template
2286 pS
->WriteUChar( 0x0F ); //selector
2287 pS
->WriteUChar( nVariation
);
2288 pS
->WriteUChar( 0x00 ); //options
2289 pS
->WriteUChar( 0x0B );
2291 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2293 pS
->WriteUChar( LINE
); //line
2294 HandleNodes(pTemp
,nLevel
+1);
2295 pS
->WriteUChar( END
); //line
2298 pS
->WriteUChar( LINE
|0x10 );
2299 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2301 pS
->WriteUChar( LINE
); //line
2302 HandleNodes(pTemp
,nLevel
+1);
2303 pS
->WriteUChar( END
); //line
2306 pS
->WriteUChar( LINE
|0x10 );
2307 pS
->WriteUChar( END
); //line
2310 //After subscript mathtype will keep the size of
2311 //normal text at the subscript size, sigh.
2312 pS
->WriteUChar( 0x0A );
2316 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2319 pS
->WriteUChar( TMPL
); //Template
2320 pS
->WriteUChar( 0x0E ); //selector
2321 pS
->WriteUChar( 0x00 ); //variation
2322 pS
->WriteUChar( 0x00 ); //options
2324 pS
->WriteUChar( 0x0A );
2325 pS
->WriteUChar( LINE
); //line
2326 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2327 HandleNodes(pTemp
,nLevel
+1);
2328 pS
->WriteUChar( END
);
2330 pS
->WriteUChar( 0x0A );
2331 pS
->WriteUChar( LINE
); //line
2332 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2333 HandleNodes(pTemp
,nLevel
+1);
2334 pS
->WriteUChar( END
);
2336 pS
->WriteUChar( END
);
2340 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2343 SmNode
*pLeft
=pNode
->GetSubNode(0);
2344 SmNode
*pRight
=pNode
->GetSubNode(2);
2346 pS
->WriteUChar( TMPL
); //Template
2347 bIsReInterpBrace
=false;
2348 sal_uInt8 nBSpec
=0x10;
2349 auto nLoc
= pS
->Tell();
2352 switch (pLeft
->GetToken().eType
)
2355 pS
->WriteUChar( tmANGLE
); //selector
2356 pS
->WriteUChar( 0 ); //variation
2357 pS
->WriteUChar( 0 ); //options
2360 pS
->WriteUChar( tmBRACE
); //selector
2361 pS
->WriteUChar( 0 ); //variation
2362 pS
->WriteUChar( 0 ); //options
2366 pS
->WriteUChar( tmBRACK
); //selector
2367 pS
->WriteUChar( 0 ); //variation
2368 pS
->WriteUChar( 0 ); //options
2372 pS
->WriteUChar( tmFLOOR
); //selector
2373 pS
->WriteUChar( 0 ); //variation
2374 pS
->WriteUChar( 0 ); //options
2377 pS
->WriteUChar( tmBAR
); //selector
2378 pS
->WriteUChar( 0 ); //variation
2379 pS
->WriteUChar( 0 ); //options
2383 pS
->WriteUChar( tmDBAR
); //selector
2384 pS
->WriteUChar( 0 ); //variation
2385 pS
->WriteUChar( 0 ); //options
2388 pS
->WriteUChar( tmPAREN
); //selector
2389 pS
->WriteUChar( 0 ); //variation
2390 pS
->WriteUChar( 0 ); //options
2396 if (nullptr != (pTemp
= pNode
->GetSubNode(1)))
2398 pS
->WriteUChar( LINE
); //line
2399 HandleNodes(pTemp
,nLevel
+1);
2400 pS
->WriteUChar( END
); //options
2404 HandleNodes(pLeft
,nLevel
+1);
2405 if (bIsReInterpBrace
)
2407 auto nLoc2
= pS
->Tell();
2409 pS
->WriteUChar( 0x2D );
2411 pS
->WriteUChar( CHAR
);
2412 pS
->WriteUChar( 0x96 );
2413 pS
->WriteUInt16( 0xEC07 );
2414 bIsReInterpBrace
=false;
2417 HandleNodes(pRight
,nLevel
+1);
2419 pS
->WriteUChar( END
);
2423 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2426 pS
->WriteUChar( TMPL
); //Template
2427 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2428 pS
->WriteUChar( tmLHBRACE
); //selector
2430 pS
->WriteUChar( tmUHBRACE
); //selector
2431 pS
->WriteUChar( 0 ); //variation
2432 pS
->WriteUChar( 0 ); //options
2434 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2436 pS
->WriteUChar( LINE
); //line
2437 HandleNodes(pTemp
,nLevel
+1);
2438 pS
->WriteUChar( END
); //options
2441 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2443 pS
->WriteUChar( LINE
); //line
2444 HandleNodes(pTemp
,nLevel
+1);
2445 pS
->WriteUChar( END
); //options
2447 pS
->WriteUChar( END
);
2450 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2452 if (HandleLim(pNode
,nLevel
))
2456 sal_uInt8 nVariation
;
2458 switch (pNode
->GetToken().eType
)
2465 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2466 pNode
->GetSubNode(1),nLevel
,&nPos
,false);
2469 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2470 pNode
->GetSubNode(1),nLevel
,&nPos
);
2474 sal_uInt8 nOldVariation
=nVariation
;
2475 sal_uInt8 nIntVariation
=nVariation
;
2478 if (nVariation
!= 0xff)
2482 if (nVariation
== 2)
2487 else if (nVariation
== 0)
2489 else if (nVariation
== 1)
2497 pS
->WriteUChar( TMPL
);
2498 switch(pNode
->GetToken().eType
)
2502 if (nOldVariation
!= 0xff)
2503 pS
->WriteUChar( 0x18 ); //selector
2505 pS
->WriteUChar( 0x15 ); //selector
2506 pS
->WriteUChar( nIntVariation
); //variation
2509 if (nOldVariation
!= 0xff)
2511 pS
->WriteUChar( 0x19 );
2512 pS
->WriteUChar( 0x01 );
2516 pS
->WriteUChar( 0x16 );
2517 pS
->WriteUChar( 0x00 );
2521 if (nOldVariation
!= 0xff)
2523 pS
->WriteUChar( 0x1a );
2524 pS
->WriteUChar( 0x01 );
2528 pS
->WriteUChar( 0x17 );
2529 pS
->WriteUChar( 0x00 );
2533 if (nOldVariation
!= 0xff)
2535 pS
->WriteUChar( 0x18 );
2536 pS
->WriteUChar( 0x02 );
2540 pS
->WriteUChar( 0x15 );
2541 pS
->WriteUChar( 0x03 );
2545 if (nOldVariation
!= 0xff)
2547 pS
->WriteUChar( 0x19 );
2548 pS
->WriteUChar( 0x00 );
2552 pS
->WriteUChar( 0x16 );
2553 pS
->WriteUChar( 0x02 );
2557 if (nOldVariation
!= 0xff)
2559 pS
->WriteUChar( 0x1a );
2560 pS
->WriteUChar( 0x00 );
2564 pS
->WriteUChar( 0x17 );
2565 pS
->WriteUChar( 0x02 );
2570 pS
->WriteUChar( 0x1d );
2571 pS
->WriteUChar( nVariation
);
2574 pS
->WriteUChar( 0x1f );
2575 pS
->WriteUChar( nVariation
);
2578 pS
->WriteUChar( 0x21 );
2579 pS
->WriteUChar( nVariation
);
2582 pS
->WriteUChar( 0 ); //options
2588 pS
->WriteUChar( LINE
); //line
2589 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2590 pS
->WriteUChar( END
); //line
2591 pS
->WriteUChar( LINE
|0x10 );
2592 pS
->WriteUChar( LINE
|0x10 );
2595 pS
->WriteUChar( 0x0D );
2596 switch(pNode
->GetToken().eType
)
2600 pS
->WriteUChar( CHAR
);
2601 pS
->WriteUChar( 0x86 );
2602 pS
->WriteUInt16( 0x2211 );
2605 pS
->WriteUChar( CHAR
);
2606 pS
->WriteUChar( 0x86 );
2607 pS
->WriteUInt16( 0x220F );
2610 pS
->WriteUChar( CHAR
);
2611 pS
->WriteUChar( 0x8B );
2612 pS
->WriteUInt16( 0x2210 );
2616 pS
->WriteUChar( CHAR
);
2617 pS
->WriteUChar( 0x86 );
2618 pS
->WriteUInt16( 0x222B );
2622 pS
->WriteUChar( CHAR
);
2623 pS
->WriteUChar( 0x86 );
2624 pS
->WriteUInt16( 0x222B );
2629 pS
->WriteUChar( CHAR
);
2630 pS
->WriteUChar( 0x86 );
2631 pS
->WriteUInt16( 0x222B );
2634 pS
->WriteUChar( END
);
2635 pS
->WriteUChar( 0x0A );
2639 bool MathType::HandlePile(int &rSetAlign
, int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2642 pS
->ReadUChar( nHAlign
);
2643 pS
->ReadUChar( nVAlign
);
2645 HandleAlign(nHAlign
, rSetAlign
);
2647 rRet
.append(" stack {\n");
2648 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, -1, -1 );
2649 int nRemoveFrom
= rRet
.getLength() >= 3 ? rRet
.getLength() - 3 : 0;
2650 rRet
.remove(nRemoveFrom
, 2);
2661 bool MathType::HandleMatrix(int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2663 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
,nVAlign
;
2664 pS
->ReadUChar( nVAlign
);
2665 pS
->ReadUChar( nH_just
);
2666 pS
->ReadUChar( nV_just
);
2667 pS
->ReadUChar( nRows
);
2668 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 ");
2763 nPostSup
= sPost
.getLength();
2765 sPost
= sPost
.replaceAt(nPostSup
-1,0," ' ");
2772 nPostSup
= sPost
.getLength();
2774 sPost
= sPost
.replaceAt(nPostSup
-1,0," '' ");
2780 sPost
+= " lsup {}";
2781 nPostlSup
= sPost
.getLength();
2783 sPost
= sPost
.replaceAt(nPostlSup
-1,0," ' ");
2787 rRet
.append(" tilde ");
2790 rRet
.append(" hat ");
2793 rRet
.append(" vec ");
2796 rRet
.append(" overstrike ");
2799 rRet
.append(" bar ");
2805 nPostSup
= sPost
.getLength();
2807 sPost
= sPost
.replaceAt(nPostSup
-1,0," ''' ");
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
).append("{");
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("}}").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
> 0x2000) || (nArse
== 0x00D7))
3091 nBias
= 0x6; //typeface
3092 else if (nArse
== 0x3d1)
3094 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3095 nBias
= 0xB; //typeface
3096 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3097 nBias
= 0x2; //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 TWIDETILDE
: //Not Exportable
3186 case TWIDEHAT
: //Not Exportable
3189 nOldPending
= StartTemplate(0x10);
3191 case TOVERLINE
: //If the next node is not text
3192 //or text with more than one char
3193 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3194 (pIsText
->GetText().getLength() > 1))
3195 nOldPending
= StartTemplate(0x11);
3198 nPendingAttributes
++;
3204 HandleNodes(pIsText
,nLevel
+1);
3206 switch (pTemp
->GetToken().eType
)
3210 EndTemplate(nOldPending
);
3213 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3214 (pIsText
->GetText().getLength() > 1))
3215 EndTemplate(nOldPending
);
3221 //if there was no suitable place to put the attribute,
3222 //then we have to just give up on it
3223 if (nPendingAttributes
)
3224 nPendingAttributes
--;
3227 if ((nInsertion
!= 0) && nullptr != (pTemp
= pNode
->GetSubNode(0)))
3229 auto nPos
= pS
->Tell();
3231 pS
->Seek(nInsertion
);
3232 switch(pTemp
->GetToken().eType
)
3234 case TACUTE
: //Not Exportable
3235 case TGRAVE
: //Not Exportable
3236 case TCIRCLE
: //Not Exportable
3239 pS
->WriteUChar( 2 );
3242 pS
->WriteUChar( 3 );
3245 pS
->WriteUChar( 4 );
3248 pS
->WriteUChar( 8 );
3251 pS
->WriteUChar( 9 );
3254 pS
->WriteUChar( 11 );
3257 pS
->WriteUChar( 16 );
3260 if ((pIsText
->GetToken().eType
== TTEXT
) &&
3261 (pIsText
->GetText().getLength() == 1))
3262 pS
->WriteUChar( 17 );
3265 pS
->WriteUChar( 20 );
3273 pS
->WriteUChar( 17 );
3276 pS
->WriteUChar( 2 );
3284 void MathType::HandleText(SmNode
*pNode
)
3286 SmTextNode
*pTemp
= static_cast<SmTextNode
*>(pNode
);
3287 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3289 if ((nPendingAttributes
) &&
3290 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3292 pS
->WriteUChar( 0x22 ); //char, with attributes right
3293 //after the character
3296 pS
->WriteUChar( CHAR
);
3298 sal_uInt8 nFace
= 0x1;
3299 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3301 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3303 pS
->WriteUChar( nFace
+128 ); //typeface
3304 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3305 pS
->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar
) );
3307 //Mathtype can only have these sort of character
3308 //attributes on a single character, starmath can put them
3309 //anywhere, when the entity involved is a text run this is
3310 //a large effort to place the character attribute on the
3311 //central mathtype character so that it does pretty much
3312 //what the user probably has in mind. The attributes
3313 //filled in here are dummy ones which are replaced in the
3314 //ATTRIBUT handler if a suitable location for the
3315 //attributes was found here. Unfortunately it is
3316 //possible for starmath to place character attributes on
3317 //entities which cannot occur in mathtype e.g. a Summation
3318 //symbol so these attributes may be lost
3319 if ((nPendingAttributes
) &&
3320 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3322 pS
->WriteUChar( EMBEL
);
3323 while (nPendingAttributes
)
3325 pS
->WriteUChar( 2 );
3326 //wedge the attributes in here and clear
3328 nPendingAttributes
--;
3330 nInsertion
=pS
->Tell();
3331 pS
->WriteUChar( END
); //end embel
3332 pS
->WriteUChar( END
); //end embel
3337 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportMathType(SvStream
&rStream
)
3339 OUStringBuffer sText
;
3340 MathType
aEquation(sText
);
3344 bRet
= aEquation
.Parse(&rStream
);
3346 catch (const std::out_of_range
&)
3352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */