1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "mathtype.hxx"
22 #include <filter/msfilter/classids.hxx>
23 #include <osl/diagnose.h>
24 #include <sfx2/docfile.hxx>
25 #include <sot/storage.hxx>
26 #include <sal/log.hxx>
28 #include "eqnolefilehdr.hxx"
33 //These are the default MathType sizes
34 aSizeTable
.push_back(12);
35 aSizeTable
.push_back(8);
36 aSizeTable
.push_back(6);
37 aSizeTable
.push_back(24);
38 aSizeTable
.push_back(10);
39 aSizeTable
.push_back(12);
40 aSizeTable
.push_back(12);
43 These are the default MathType italic/bold settings If mathtype is changed
44 from its defaults, there is nothing we can do, as this information is not
45 stored in the document
48 for(sal_uInt8 i
=1;i
<=11;i
++)
64 aUserStyles
.insert(aFont
);
69 /*ToDo replace with table rather than switch, returns
70 sal_True in the case that the char is just a char, and
71 sal_False if the character is an operator which must not be
72 placed inside the quote sequence designed to protect
73 against being parsed as a keyword
75 General solution required to force starmath to handle
76 unicode math chars the way it handles its own math
77 chars rather than handle them as text as it will do
78 for the default case below, i.e. incorrect spacing
79 between math symbols and ordinary text e.g. 1=2 rather
82 bool MathType::LookupChar(sal_Unicode nChar
,OUStringBuffer
&rRet
,sal_uInt8 nVersion
,
86 const char *pC
= nullptr;
114 if ((nVersion
< 3) && (nTypeFace
== 0x86))
118 rRet
.append(OUStringChar(nChar
));
123 if ((nVersion
< 3) && (nTypeFace
== 0x81))
125 rRet
.append(OUStringChar(nChar
));
129 if ((nVersion
< 3) && (nTypeFace
== 0x84))
131 rRet
.append(OUStringChar(nChar
));
135 if ((nVersion
< 3) && (nTypeFace
== 0x84))
137 rRet
.append(OUStringChar(nChar
));
141 if ((nVersion
< 3) && (nTypeFace
== 0x84))
143 rRet
.append(OUStringChar(nChar
));
147 if ((nVersion
< 3) && (nTypeFace
== 0x84))
149 rRet
.append(OUStringChar(nChar
));
153 if ((nVersion
< 3) && (nTypeFace
== 0x84))
155 rRet
.append(OUStringChar(nChar
));
159 if ((nVersion
< 3) && (nTypeFace
== 0x84))
161 rRet
.append(OUStringChar(nChar
));
165 if ((nVersion
< 3) && (nTypeFace
== 0x82))
167 rRet
.append(OUStringChar(nChar
));
171 if ((nVersion
< 3) && (nTypeFace
== 0x86))
175 rRet
.append(OUStringChar(nChar
));
180 if ((nVersion
< 3) && (nTypeFace
== 0x86))
184 rRet
.append(OUStringChar(nChar
));
189 if ((nVersion
< 3) && (nTypeFace
== 0x86))
193 rRet
.append(OUStringChar(nChar
));
198 if ((nVersion
< 3) && (nTypeFace
== 0x85))
202 rRet
.append(OUStringChar(nChar
));
315 case 0x2209: // notin
316 rRet
.append(" func ").append(OUStringChar(nChar
)).append(" ");
319 rRet
.append(u
" func \u220b ");
355 pC
= " intersection ";
404 pC
= " preccurlyeq ";
407 pC
= " succcurlyeq ";
422 case 0x2282: // subset
423 case 0x2283: // supset
424 case 0x2284: // nsubset
425 case 0x2285: // nsupset
426 case 0x2286: // subseteq
427 case 0x2287: // supseteq
428 case 0x2288: // nsubseteq
429 case 0x2289: // nsupseteq
430 case 0x22b2: // NORMAL SUBGROUP OF
431 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
432 rRet
.append(" func ").append(OUStringChar(nChar
)).append(" ");
486 case 0xeb01: //no space
487 case 0xeb08: //normal space
490 case 0xef04: //tiny space
491 case 0xef05: //tiny space
492 case 0xeb02: //small space
493 case 0xeb04: //medium space
496 case 0xeb05: //large space
503 rRet
.append(OUStringChar(nChar
));
508 rRet
.appendAscii(pC
);
512 void MathTypeFont::AppendStyleToText(OUString
&rRet
)
514 const char *pC
= nullptr;
531 rRet
+= OUString::createFromAscii( pC
);
534 void MathType::TypeFaceToString(OUString
&rTxt
,sal_uInt8 nFace
)
536 MathTypeFont
aFont(nFace
);
537 MathTypeFontSet::iterator aItr
= aUserStyles
.find(aFont
);
538 if (aItr
!= aUserStyles
.end())
539 aFont
.nStyle
= aItr
->nStyle
;
540 aFont
.AppendStyleToText(rTxt
);
543 bool MathType::Parse(SotStorage
*pStor
)
545 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(
547 StreamMode::STD_READ
);
548 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
550 return Parse(xSrc
.get());
553 bool MathType::Parse(SvStream
* pStream
)
556 pS
->SetEndian( SvStreamEndian::LITTLE
);
560 sal_uInt8 nProdVersion
;
561 sal_uInt8 nProdSubVersion
;
564 pS
->ReadUChar( nVersion
);
565 pS
->ReadUChar( nPlatform
);
566 pS
->ReadUChar( nProduct
);
567 pS
->ReadUChar( nProdVersion
);
568 pS
->ReadUChar( nProdSubVersion
);
570 if (nVersion
> 3) // allow only supported versions of MathType to be parsed
573 bool bRet
= HandleRecords(0);
574 //little crude hack to close occasionally open expressions
575 //a sophisticated system to determine what expressions are
576 //opened is required, but this is as much work as rewriting
577 //starmaths internals.
583 static void lcl_PrependDummyTerm(OUStringBuffer
&rRet
, sal_Int32
&rTextStart
)
585 if ((rTextStart
< rRet
.getLength()) &&
586 (rRet
[rTextStart
] == '=') &&
587 ((rTextStart
== 0) || (rRet
[ rTextStart
-1 ] == '{'))
590 rRet
.insert(rTextStart
, " {}");
595 static void lcl_AppendDummyTerm(OUStringBuffer
&rRet
)
598 for(int nI
=rRet
.getLength()-1;nI
>= 0; nI
--)
600 sal_Int32 nIdx
= sal::static_int_cast
< sal_Int32
>(nI
);
601 sal_Unicode nChar
= rRet
[nIdx
];
604 if (rRet
[nIdx
] != '{')
608 if (!bOk
) //No term, use dummy
612 void MathType::HandleNudge()
615 pS
->ReadUChar( nXNudge
);
617 pS
->ReadUChar( nYNudge
);
618 if (nXNudge
== 128 && nYNudge
== 128)
620 sal_uInt16 nXLongNudge
;
621 sal_uInt16 nYLongNudge
;
622 pS
->ReadUInt16( nXLongNudge
);
623 pS
->ReadUInt16( nYLongNudge
);
627 /* Fabulously complicated as many tokens have to be reordered and generally
628 * moved around from mathtypes paradigm to starmaths. */
629 bool MathType::HandleRecords(int nLevel
, sal_uInt8 nSelector
,
630 sal_uInt8 nVariation
, int nMatrixRows
, int nMatrixCols
)
636 sal_uInt8 nTag
,nRecord
;
637 sal_uInt8 nTabType
,nTabStops
;
638 sal_uInt16 nTabOffset
;
642 OUString sPush
,sMainTerm
;
643 int nSetSize
=0,nSetAlign
=0;
644 int nCurRow
=0,nCurCol
=0;
645 bool bOpenString
=false;
646 sal_Int32 nTextStart
= 0;
647 sal_Int32 nSubSupStartPos
= 0;
648 sal_Int32 nLastTemplateBracket
=-1;
654 pS
->ReadUChar( nTag
);
657 /*MathType strings can of course include words which
658 *are StarMath keywords, the simplest solution is
659 to escape strings of greater than len 1 with double
660 quotes to avoid scanning the TokenTable for matches
662 Unfortunately it may turn out that the string gets
663 split during the handling of a character emblishment
664 so this special case must be handled in the
665 character handler case 2:
667 if ((nRecord
== CHAR
) && (!bOpenString
))
670 nTextStart
= rRet
.getLength();
672 else if ((nRecord
!= CHAR
) && bOpenString
)
675 if ((rRet
.getLength() - nTextStart
) > 1)
678 TypeFaceToString(aStr
,nTypeFace
);
680 rRet
.insert(nTextStart
,aStr
);
683 else if (nRecord
== END
&& !rRet
.isEmpty())
685 sal_Unicode cChar
= 0;
686 sal_Int32 nI
= rRet
.getLength()-1;
687 while (nI
&& ((cChar
= rRet
[nI
]) == ' '))
689 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
702 rRet
.append("\nnewline\n");
709 rRet
.append(" langle ");
710 else if (nVariation
==1)
711 rRet
.append(" \\langle ");
715 rRet
.append(" left (");
716 else if (nVariation
==1)
720 if ((nVariation
==0) || (nVariation
==1))
721 rRet
.append(" left lbrace ");
723 rRet
.append(" left none ");
727 rRet
.append(" left [");
728 else if (nVariation
==1)
737 rRet
.append(" lline ");
738 else if (nVariation
==1)
739 rRet
.append(" \\lline ");
743 rRet
.append(" ldline ");
744 else if (nVariation
==1)
745 rRet
.append(" \\ldline ");
748 if (nVariation
== 0 || nVariation
& 0x01) // tvFENCE_L
749 rRet
.append(" left lfloor ");
751 rRet
.append(" left none ");
755 rRet
.append(" lceil ");
756 else if (nVariation
==1)
757 rRet
.append(" \\lceil ");
770 rRet
.append(" sqrt");
773 rRet
.append(" nroot");
774 sPush
= rRet
.makeStringAndClear();
785 rRet
.append(" over ");
789 nSubSupStartPos
= rRet
.getLength();
790 if ((nVariation
== 0) ||
791 ((nVariation
== 2) && (nPart
==1)))
793 lcl_AppendDummyTerm(rRet
);
794 rRet
.append(" rSup");
796 else if ((nVariation
== 1) ||
797 ((nVariation
== 2) && (nPart
==0)))
799 lcl_AppendDummyTerm(rRet
);
800 rRet
.append(" rSub");
806 rRet
.append(" {underline ");
807 else if (nVariation
== 1)
808 rRet
.append(" {underline underline ");
813 rRet
.append(" {overline ");
814 else if (nVariation
== 1)
815 rRet
.append(" {overline overline ");
822 rRet
.append(" widevec ");//left arrow above
823 else if (nVariation
== 1)
824 rRet
.append(" widevec ");//left arrow below
832 rRet
.append(" widevec ");//right arrow above
833 else if (nVariation
== 1)
834 rRet
.append(" widevec ");//right arrow below
842 rRet
.append(" widevec ");//double arrow above
843 else if (nVariation
== 1)
844 rRet
.append(" widevec ");//double arrow below
851 if ((nVariation
== 3) || (nVariation
== 4))
852 rRet
.append(" lInt");
855 if ( (nVariation
!= 0) && (nVariation
!= 3))
857 sPush
= rRet
.makeStringAndClear();
860 if (((nVariation
== 1) ||
861 (nVariation
== 4)) && (nPart
==1))
862 rRet
.append(" rSub");
863 else if ((nVariation
== 2) && (nPart
==2))
864 rRet
.append(" rSup");
865 else if ((nVariation
== 2) && (nPart
==1))
866 rRet
.append(" rSub");
872 if ((nVariation
== 2) || (nVariation
== 3))
873 rRet
.append(" llInt");
875 rRet
.append(" iInt");
876 if ( (nVariation
!= 0) && (nVariation
!= 2))
878 sPush
= rRet
.makeStringAndClear();
881 if (((nVariation
== 1) ||
882 (nVariation
== 3)) && (nPart
==1))
883 rRet
.append(" rSub");
889 if ((nVariation
== 2) || (nVariation
== 3))
890 rRet
.append(" lllInt");
892 rRet
.append(" iiInt");
893 if ( (nVariation
!= 0) && (nVariation
!= 2))
895 sPush
= rRet
.makeStringAndClear();
898 if (((nVariation
== 1) ||
899 (nVariation
== 3)) && (nPart
==1))
900 rRet
.append(" rSub");
907 rRet
.append(" lInt");
910 sPush
= rRet
.makeStringAndClear();
912 if (((nVariation
== 1) ||
913 (nVariation
== 2)) && (nPart
==1))
914 rRet
.append(" cSub");
915 else if ((nVariation
== 0) && (nPart
==2))
916 rRet
.append(" cSup");
917 else if ((nVariation
== 0) && (nPart
==1))
918 rRet
.append(" cSub");
925 rRet
.append(" llInt");
927 rRet
.append(" iInt");
928 sPush
= rRet
.makeStringAndClear();
931 rRet
.append(" cSub");
938 rRet
.append(" lllInt");
940 rRet
.append(" iiInt");
941 sPush
= rRet
.makeStringAndClear();
944 rRet
.append(" cSub");
957 sPush
= rRet
.makeStringAndClear();
960 if ((nVariation
== 0) && (nPart
==1))
961 rRet
.append(" cSub");
962 else if ((nVariation
== 1) && (nPart
==2))
963 rRet
.append(" cSup");
964 else if ((nVariation
== 1) && (nPart
==1))
965 rRet
.append(" cSub");
972 sPush
= rRet
.makeStringAndClear();
974 if ((nVariation
== 0) && (nPart
==1))
975 rRet
.append(" rSub");
976 else if ((nVariation
== 1) && (nPart
==2))
977 rRet
.append(" rSup");
978 else if ((nVariation
== 1) && (nPart
==1))
979 rRet
.append(" rSub");
985 rRet
.append(" Prod");
988 sPush
= rRet
.makeStringAndClear();
991 if ((nVariation
== 0) && (nPart
==1))
992 rRet
.append(" cSub");
993 else if ((nVariation
== 1) && (nPart
==2))
994 rRet
.append(" cSup");
995 else if ((nVariation
== 1) && (nPart
==1))
996 rRet
.append(" cSub");
1002 rRet
.append(" Prod");
1003 sPush
= rRet
.makeStringAndClear();
1005 if ((nVariation
== 0) && (nPart
==1))
1006 rRet
.append(" rSub");
1007 else if ((nVariation
== 1) && (nPart
==2))
1008 rRet
.append(" rSup");
1009 else if ((nVariation
== 1) && (nPart
==1))
1010 rRet
.append(" rSub");
1016 rRet
.append(" coProd");
1017 if (nVariation
!= 2)
1019 sPush
= rRet
.makeStringAndClear();
1022 if ((nVariation
== 0) && (nPart
==1))
1023 rRet
.append(" cSub");
1024 else if ((nVariation
== 1) && (nPart
==2))
1025 rRet
.append(" cSup");
1026 else if ((nVariation
== 1) && (nPart
==1))
1027 rRet
.append(" cSub");
1033 rRet
.append(" coProd");
1034 sPush
= rRet
.makeStringAndClear();
1036 if ((nVariation
== 0) && (nPart
==1))
1037 rRet
.append(" rSub");
1038 else if ((nVariation
== 1) && (nPart
==2))
1039 rRet
.append(" rSup");
1040 else if ((nVariation
== 1) && (nPart
==1))
1041 rRet
.append(" rSub");
1047 rRet
.append(" union"); //union
1048 if (nVariation
!= 2)
1050 sPush
= rRet
.makeStringAndClear();
1053 if ((nVariation
== 0) && (nPart
==1))
1054 rRet
.append(" cSub");
1055 else if ((nVariation
== 1) && (nPart
==2))
1056 rRet
.append(" cSup");
1057 else if ((nVariation
== 1) && (nPart
==1))
1058 rRet
.append(" cSub");
1064 rRet
.append(" union"); //union
1065 sPush
= rRet
.makeStringAndClear();
1067 if ((nVariation
== 0) && (nPart
==1))
1068 rRet
.append(" rSub");
1069 else if ((nVariation
== 1) && (nPart
==2))
1070 rRet
.append(" rSup");
1071 else if ((nVariation
== 1) && (nPart
==1))
1072 rRet
.append(" rSub");
1078 rRet
.append(" intersect"); //intersect
1079 if (nVariation
!= 2)
1081 sPush
= rRet
.makeStringAndClear();
1084 if ((nVariation
== 0) && (nPart
==1))
1085 rRet
.append(" cSub");
1086 else if ((nVariation
== 1) && (nPart
==2))
1087 rRet
.append(" cSup");
1088 else if ((nVariation
== 1) && (nPart
==1))
1089 rRet
.append(" cSub");
1095 rRet
.append(" intersect"); //intersect
1096 sPush
= rRet
.makeStringAndClear();
1098 if ((nVariation
== 0) && (nPart
==1))
1099 rRet
.append(" rSub");
1100 else if ((nVariation
== 1) && (nPart
==2))
1101 rRet
.append(" rSup");
1102 else if ((nVariation
== 1) && (nPart
==1))
1103 rRet
.append(" rSub");
1107 if ((nVariation
== 0) && (nPart
==1))
1108 rRet
.append(" cSup");
1109 else if ((nVariation
== 1) && (nPart
==1))
1110 rRet
.append(" cSub");
1111 else if ((nVariation
== 2) && (nPart
==1))
1112 rRet
.append(" cSub");
1113 else if ((nVariation
== 2) && (nPart
==2))
1114 rRet
.append(" cSup");
1118 if (nVariation
== 0)
1122 sPush
= rRet
.makeStringAndClear();
1126 if (nVariation
== 0)
1129 rRet
.append("alignr ");
1132 rRet
.append("\\lline ");
1133 if (nVariation
== 1)
1134 rRet
.append("overline ");
1142 sPush
= rRet
.makeStringAndClear();
1144 if ((nVariation
== 0) && (nPart
==0))
1145 rRet
.append(" rSup");
1146 else if ((nVariation
== 2) && (nPart
==1))
1147 rRet
.append(" rSup");
1148 else if ((nVariation
== 1) && (nPart
==0))
1149 rRet
.append(" rSub");
1150 else if ((nVariation
== 2) && (nPart
==0))
1151 rRet
.append(" rSub");
1157 sPush
= rRet
.makeStringAndClear();
1159 if ((nVariation
== 0) && (nPart
==0))
1160 rRet
.append(" cSup");
1161 else if ((nVariation
== 2) && (nPart
==1))
1162 rRet
.append(" cSup");
1163 else if ((nVariation
== 1) && (nPart
==0))
1164 rRet
.append(" cSub");
1165 else if ((nVariation
== 2) && (nPart
==0))
1166 rRet
.append(" cSub");
1171 rRet
.append("\"\"");
1172 if ((nVariation
== 0)
1173 || ((nVariation
== 2) && (nPart
==1)))
1174 rRet
.append(" lSup");
1175 else if ((nVariation
== 1)
1176 || ((nVariation
== 2) && (nPart
==0)))
1177 rRet
.append(" lSub");
1184 rRet
.append(" langle ");
1186 else if (nVariation
==1)
1188 rRet
.append(" \\langle ");
1191 else if (nVariation
==2)
1193 rRet
.append(" \\lline ");
1198 if (nVariation
== 0)
1199 rRet
.append(" widevec ");//left below
1200 else if (nVariation
== 1)
1201 rRet
.append(" widevec ");//right below
1202 else if (nVariation
== 2)
1203 rRet
.append(" widevec ");//double headed below
1207 if (nVariation
== 0)
1208 rRet
.append(" widevec ");//left above
1209 else if (nVariation
== 1)
1210 rRet
.append(" widevec ");//right above
1211 else if (nVariation
== 2)
1212 rRet
.append(" widevec ");//double headed above
1218 sal_Int16 nOldCurSize
=nCurSize
;
1219 sal_Int32 nSizeStartPos
= rRet
.getLength();
1220 HandleSize( nLSize
, nDSize
, nSetSize
);
1221 bRet
= HandleRecords( nLevel
+1 );
1225 sal_Int32 nI
= rRet
.lastIndexOf('{');
1228 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1229 if (rRet
[nI
] != ' ')
1240 else if (rRet
.getLength() > nSizeStartPos
)
1241 rRet
= rRet
.truncate(nSizeStartPos
);
1243 nCurSize
=nOldCurSize
;
1247 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1254 rRet
.append(" rangle ");
1255 else if (nVariation
==2)
1256 rRet
.append(" \\rangle ");
1260 rRet
.append(" right )");
1261 else if (nVariation
==2)
1265 if ((nVariation
==0) || (nVariation
==2))
1266 rRet
.append(" right rbrace ");
1268 rRet
.append(" right none ");
1272 rRet
.append(" right ]");
1273 else if (nVariation
==2)
1278 rRet
.append(" rline ");
1279 else if (nVariation
==2)
1280 rRet
.append(" \\rline ");
1284 rRet
.append(" rdline ");
1285 else if (nVariation
==2)
1286 rRet
.append(" \\rdline ");
1289 if (nVariation
== 0 || nVariation
& 0x02) // tvFENCE_R
1290 rRet
.append(" right rfloor ");
1292 rRet
.append(" right none ");
1296 rRet
.append(" rceil ");
1297 else if (nVariation
==2)
1298 rRet
.append(" \\rceil ");
1310 if (nVariation
== 1)
1315 sMainTerm
= rRet
.makeStringAndClear();
1317 else if (nPart
== 1)
1319 rRet
.insert(0, sPush
);
1320 rRet
.append(sMainTerm
);
1346 ((nVariation
== 2) || (nVariation
== 1)))
1350 sal_Int32 nI
= rRet
.lastIndexOf('{');
1353 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1354 if (rRet
[nI
] != ' ')
1365 else if (rRet
.getLength() > nSubSupStartPos
)
1366 rRet
= rRet
.truncate(nSubSupStartPos
);
1372 ((nVariation
== 2) || (nVariation
== 1)))
1400 rRet
.append("overbrace");
1409 rRet
.append("underbrace");
1416 else if ((nPart
==1) &&
1417 ((nVariation
== 2) || (nVariation
== 1)))
1424 if (nVariation
== 0)
1428 sMainTerm
= rRet
.makeStringAndClear();
1430 else if (nPart
== 1)
1432 rRet
.insert(0, sPush
);
1433 rRet
.append(" over ").append(sMainTerm
);
1450 rRet
.append("slash");
1453 rRet
.append("wideslash");
1472 if (nVariation
!= 2)
1474 sMainTerm
= rRet
.makeStringAndClear();
1478 else if ((nPart
== 1) && (nVariation
== 0))
1480 rRet
.insert(0, sPush
);
1481 rRet
.append(sMainTerm
);
1486 else if ((nPart
== 1) && (nVariation
== 1))
1488 else if ((nPart
== 2) && (nVariation
== 1))
1490 rRet
.insert(0, sPush
);
1491 rRet
.append(sMainTerm
);
1502 if ((nVariation
!= 0) && (nVariation
!= 3))
1504 sMainTerm
= rRet
.makeStringAndClear();
1508 else if ((nPart
== 1) &&
1509 ((nVariation
== 1) || (nVariation
==4)))
1511 rRet
.insert(0, sPush
);
1512 rRet
.append(sMainTerm
);
1517 else if ((nPart
== 1) && (nVariation
== 2))
1519 else if ((nPart
== 2) && (nVariation
== 2))
1521 rRet
.insert(0, sPush
);
1522 rRet
.append(sMainTerm
);
1534 if ((nVariation
!= 0) && (nVariation
!= 2))
1536 sMainTerm
= rRet
.makeStringAndClear();
1540 else if ((nPart
== 1) &&
1541 ((nVariation
== 1) || (nVariation
==3)))
1543 rRet
.insert(0, sPush
);
1544 rRet
.append(sMainTerm
);
1555 sMainTerm
= rRet
.makeStringAndClear();
1558 else if ((nPart
== 1) &&
1559 ((nVariation
== 1) || (nVariation
==2)))
1561 rRet
.insert(0, sPush
);
1562 rRet
.append(sMainTerm
);
1567 else if ((nPart
== 1) && (nVariation
== 0))
1569 else if ((nPart
== 2) && (nVariation
== 0))
1571 rRet
.insert(0, sPush
);
1572 rRet
.append(sMainTerm
);
1584 sMainTerm
= rRet
.makeStringAndClear();
1587 else if (nPart
== 1)
1589 rRet
.insert(0, sPush
);
1590 rRet
.append(sMainTerm
);
1602 ((nVariation
== 0) || (nVariation
== 1)))
1604 sMainTerm
= rRet
.makeStringAndClear();
1607 else if ((nPart
== 0) && (nVariation
== 2))
1609 else if ((nPart
== 1) && (nVariation
== 2))
1611 sMainTerm
= rRet
.makeStringAndClear();
1614 else if ((nPart
== 2) || ((nPart
== 1) &&
1615 (nVariation
== 0 || nVariation
== 1)))
1617 rRet
.insert(0, sPush
);
1618 rRet
.append(sMainTerm
);
1629 newline
--; //there is another term to arrive
1630 rRet
.append(" mline ");
1633 rRet
.append(" rangle ");
1635 else if (nVariation
==1)
1636 rRet
.append(" \\lline ");
1637 else if (nVariation
==2)
1638 rRet
.append(" \\rangle ");
1644 bSilent
= true; //Skip the optional brackets and/or
1645 //symbols that follow some of these
1646 //records. Foo Data.
1648 /*In matrices and piles we cannot separate equation
1649 *lines with the newline keyword*/
1658 bRet
= HandleChar( nTextStart
, nSetSize
, nLevel
, nTag
, nSelector
, nVariation
, bSilent
);
1663 bRet
= HandleTemplate( nLevel
, nSelector
, nVariation
, nLastTemplateBracket
);
1668 bRet
= HandlePile( nSetAlign
, nLevel
, nSelector
, nVariation
);
1669 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1674 bRet
= HandleMatrix( nLevel
, nSelector
, nVariation
);
1675 HandleMatrixSeparator( nMatrixRows
, nMatrixCols
, nCurCol
, nCurRow
);
1680 HandleEmblishments();
1683 pS
->ReadUChar( nTabStops
);
1684 for (i
=0;i
<nTabStops
;i
++)
1686 pS
->ReadUChar( nTabType
);
1687 pS
->ReadUInt16( nTabOffset
);
1689 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1694 pS
->ReadUChar( aFont
.nTface
);
1696 The typeface number is the negative (which makes it
1697 positive) of the typeface value (unbiased) that appears in
1698 CHAR records that might follow a given FONT record
1700 aFont
.nTface
= 128-aFont
.nTface
;
1701 pS
->ReadUChar( aFont
.nStyle
);
1702 aUserStyles
.insert(aFont
);
1707 pS
->ReadChar( nChar8
);
1728 while (nRecord
!= END
&& !pS
->eof());
1737 /*Simply determine if we are at the end of a record or the end of a line,
1738 *with fiddly logic to see if we are in a matrix or a pile or neither
1740 Note we cannot tell until after the event that this is the last entry
1741 of a pile, so we must strip the last separator of a pile after this
1742 is detected in the PILE handler
1744 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1745 int &rCurCol
,int &rCurRow
)
1750 if (rCurCol
== nMatrixCols
-1)
1752 if (rCurRow
!= nMatrixRows
-1)
1753 rRet
.append(" {} ##\n");
1754 if (nMatrixRows
!=-1)
1762 rRet
.append(" {} # ");
1763 if (nMatrixRows
!=-1)
1770 /* set the alignment of the following term, but starmath currently
1771 * cannot handle vertical alignment */
1772 void MathType::HandleAlign(sal_uInt8 nHorAlign
, int &rSetAlign
)
1778 rRet
.append("alignl {");
1781 rRet
.append("alignc {");
1784 rRet
.append("alignr {");
1790 /* set size of text, complexity due to overuse of signedness as a flag
1791 * indicator by mathtype file format*/
1792 bool MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1794 const sal_Int16 nDefaultSize
= 12;
1798 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1806 if (-nLstSize
/32 != nLastSize
)
1808 nLastSize
= nCurSize
;
1809 rRet
.append(" size ");
1810 rRet
.append(OUString::number(-nLstSize
/32));
1815 nCurSize
= -nLstSize
/32;
1820 /*sizetable should theoretically be filled with the default sizes
1821 *of the various font groupings matching starmaths equivalents
1822 in aTypeFaces, and a test would be done to see if the new font
1823 size would be the same as what starmath would have chosen for
1824 itself anyway in which case the size setting could be ignored*/
1825 nLstSize
= aSizeTable
.at(nLstSize
);
1826 nLstSize
= nLstSize
+ nDefSize
;
1827 if (nLstSize
!= nCurSize
)
1835 if (nLstSize
!= nLastSize
)
1837 nLastSize
= nCurSize
;
1838 rRet
.append(" size ");
1839 rRet
.append(OUString::number(nLstSize
));
1844 nCurSize
= nLstSize
;
1850 bool MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1855 SvStream
*pStream
= rMedium
.GetOutStream();
1858 tools::SvRef
<SotStorage
> pStor
= new SotStorage( pStream
, false );
1860 SvGlobalName
aGName(MSO_EQUATION3_CLASSID
);
1861 pStor
->SetClass( aGName
, SotClipboardFormatId::NONE
, "Microsoft Equation 3.0");
1863 static sal_uInt8
const aCompObj
[] = {
1864 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1865 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1866 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1868 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1869 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1870 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1871 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1872 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1873 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1874 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1875 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1878 tools::SvRef
<SotStorageStream
> xStor( pStor
->OpenSotStream("\1CompObj"));
1879 xStor
->WriteBytes(aCompObj
, sizeof(aCompObj
));
1881 static sal_uInt8
const aOle
[] = {
1882 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00
1886 tools::SvRef
<SotStorageStream
> xStor2( pStor
->OpenSotStream("\1Ole"));
1887 xStor2
->WriteBytes(aOle
, sizeof(aOle
));
1891 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream("Equation Native");
1892 if ( (!xSrc
.is()) || (ERRCODE_NONE
!= xSrc
->GetError()))
1896 pS
->SetEndian( SvStreamEndian::LITTLE
);
1898 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1899 pS
->WriteUChar( 0x03 );
1900 pS
->WriteUChar( 0x01 );
1901 pS
->WriteUChar( 0x01 );
1902 pS
->WriteUChar( 0x03 );
1903 pS
->WriteUChar( 0x00 );
1904 sal_uInt32 nSize
= pS
->Tell();
1905 nPendingAttributes
=0;
1907 HandleNodes(pTree
, 0);
1908 pS
->WriteUChar( END
);
1910 nSize
= pS
->Tell()-nSize
;
1912 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1922 void MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1924 switch(pNode
->GetType())
1926 case SmNodeType::Attribut
:
1927 HandleAttributes(pNode
,nLevel
);
1929 case SmNodeType::Text
:
1932 case SmNodeType::VerticalBrace
:
1933 HandleVerticalBrace(pNode
,nLevel
);
1935 case SmNodeType::Brace
:
1936 HandleBrace(pNode
,nLevel
);
1938 case SmNodeType::Oper
:
1939 HandleOperator(pNode
,nLevel
);
1941 case SmNodeType::BinVer
:
1942 HandleFractions(pNode
,nLevel
);
1944 case SmNodeType::Root
:
1945 HandleRoot(pNode
,nLevel
);
1947 case SmNodeType::Special
:
1949 SmTextNode
*pText
= static_cast<SmTextNode
*>(pNode
);
1950 //if the token str and the result text are the same then this
1951 //is to be seen as text, else assume it's a mathchar
1952 if (pText
->GetText() == pText
->GetToken().aText
)
1958 case SmNodeType::Math
:
1959 case SmNodeType::MathIdent
:
1962 case SmNodeType::SubSup
:
1963 HandleSubSupScript(pNode
,nLevel
);
1965 case SmNodeType::Expression
:
1967 size_t nSize
= pNode
->GetNumSubNodes();
1968 for (size_t i
= 0; i
< nSize
; ++i
)
1970 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1971 HandleNodes(pTemp
,nLevel
+1);
1975 case SmNodeType::Table
:
1976 //Root Node, PILE equivalent, i.e. vertical stack
1977 HandleTable(pNode
,nLevel
);
1979 case SmNodeType::Matrix
:
1980 HandleSmMatrix(static_cast<SmMatrixNode
*>(pNode
),nLevel
);
1982 case SmNodeType::Line
:
1984 pS
->WriteUChar( 0x0a );
1985 pS
->WriteUChar( LINE
);
1986 size_t nSize
= pNode
->GetNumSubNodes();
1987 for (size_t i
= 0; i
< nSize
; ++i
)
1989 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
1990 HandleNodes(pTemp
,nLevel
+1);
1992 pS
->WriteUChar( END
);
1995 case SmNodeType::Align
:
1996 HandleMAlign(pNode
,nLevel
);
1998 case SmNodeType::Blank
:
1999 pS
->WriteUChar( CHAR
);
2000 pS
->WriteUChar( 0x98 );
2001 if (pNode
->GetToken().eType
== TSBLANK
)
2002 pS
->WriteUInt16( 0xEB04 );
2004 pS
->WriteUInt16( 0xEB05 );
2008 size_t nSize
= pNode
->GetNumSubNodes();
2009 for (size_t i
= 0; i
< nSize
; ++i
)
2011 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2012 HandleNodes(pTemp
,nLevel
+1);
2020 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2022 int nOldPending
=nPendingAttributes
;
2023 pS
->WriteUChar( TMPL
); //Template
2024 pS
->WriteUChar( nSelector
); //selector
2025 pS
->WriteUChar( nVariation
); //variation
2026 pS
->WriteUChar( 0x00 ); //options
2027 pS
->WriteUChar( LINE
);
2028 //there's just no way we can now handle any character
2029 //attributes (from mathtypes perspective) centered
2030 //over an expression but above template attribute
2031 //such as widevec and similar constructs
2032 //we have to drop them
2033 nPendingAttributes
=0;
2037 void MathType::EndTemplate(int nOldPendingAttributes
)
2039 pS
->WriteUChar( END
); //end line
2040 pS
->WriteUChar( END
); //end template
2041 nPendingAttributes
=nOldPendingAttributes
;
2045 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2047 pS
->WriteUChar( MATRIX
);
2048 pS
->WriteUChar( 0x00 ); //vAlign ?
2049 pS
->WriteUChar( 0x00 ); //h_just
2050 pS
->WriteUChar( 0x00 ); //v_just
2051 pS
->WriteUChar( pMatrix
->GetNumRows() ); //v_just
2052 pS
->WriteUChar( pMatrix
->GetNumCols() ); //v_just
2053 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2054 if (((pMatrix
->GetNumRows()+1)*2)%8)
2056 for (int j
= 0; j
< nBytes
; j
++)
2057 pS
->WriteUChar( 0x00 ); //row_parts
2058 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2059 if (((pMatrix
->GetNumCols()+1)*2)%8)
2061 for (int k
= 0; k
< nBytes
; k
++)
2062 pS
->WriteUChar( 0x00 ); //col_parts
2063 size_t nSize
= pMatrix
->GetNumSubNodes();
2064 for (size_t i
= 0; i
< nSize
; ++i
)
2066 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2068 pS
->WriteUChar( LINE
); //line
2069 HandleNodes(pTemp
,nLevel
+1);
2070 pS
->WriteUChar( END
); //end line
2073 pS
->WriteUChar( END
);
2077 //Root Node, PILE equivalent, i.e. vertical stack
2078 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2080 size_t nSize
= pNode
->GetNumSubNodes();
2081 //The root of the starmath is a table, if
2082 //we convert this them each iteration of
2083 //conversion from starmath to mathtype will
2084 //add an extra unnecessary level to the
2085 //mathtype output stack which would grow
2086 //without bound in a multi step conversion
2089 pS
->WriteUChar( 0x0A ); //initial size
2091 if ( nLevel
|| (nSize
>1))
2093 pS
->WriteUChar( PILE
);
2094 pS
->WriteUChar( nHAlign
); //vAlign ?
2095 pS
->WriteUChar( 0x01 ); //hAlign
2098 for (size_t i
= 0; i
< nSize
; ++i
)
2100 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2102 pS
->WriteUChar( LINE
);
2103 HandleNodes(pTemp
,nLevel
+1);
2104 pS
->WriteUChar( END
);
2107 if (nLevel
|| (nSize
>1))
2108 pS
->WriteUChar( END
);
2112 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2115 pS
->WriteUChar( TMPL
); //Template
2116 pS
->WriteUChar( 0x0D ); //selector
2117 if (pNode
->GetSubNode(0))
2118 pS
->WriteUChar( 0x01 ); //variation
2120 pS
->WriteUChar( 0x00 ); //variation
2121 pS
->WriteUChar( 0x00 ); //options
2123 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2125 pS
->WriteUChar( LINE
); //line
2126 HandleNodes(pTemp
,nLevel
+1);
2127 pS
->WriteUChar( END
);
2130 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2132 pS
->WriteUChar( LINE
); //line
2133 HandleNodes(pTemp
,nLevel
+1);
2134 pS
->WriteUChar( END
);
2137 pS
->WriteUChar( LINE
|0x10 ); //dummy line
2140 pS
->WriteUChar( END
);
2143 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2144 sal_uInt64
*pPos
,bool bTest
)
2146 sal_uInt8 nVariation2
=0xff;
2148 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2151 if (pNode
->GetSubNode(CSUB
+1))
2154 else if (pNode
->GetSubNode(CSUB
+1))
2157 if (nVariation2
!=0xff)
2161 pS
->WriteUChar( TMPL
); //Template
2162 pS
->WriteUChar( 0x2B ); //selector
2163 pS
->WriteUChar( nVariation2
);
2164 pS
->WriteUChar( 0x00 ); //options
2168 pS
->WriteUChar( LINE
); //line
2169 HandleNodes(pContent
,nLevel
+1);
2170 pS
->WriteUChar( END
); //line
2173 pS
->WriteUChar( LINE
|0x10 );
2175 pS
->WriteUChar( 0x0B );
2178 if (nullptr != (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2180 pS
->WriteUChar( LINE
); //line
2181 HandleNodes(pTemp
,nLevel
+1);
2182 pS
->WriteUChar( END
); //line
2185 pS
->WriteUChar( LINE
|0x10 );
2186 if (bTest
&& nullptr != (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2188 pS
->WriteUChar( LINE
); //line
2189 HandleNodes(pTemp
,nLevel
+1);
2190 pS
->WriteUChar( END
); //line
2193 pS
->WriteUChar( LINE
|0x10 );
2200 Sub and Sup scripts and another problem area, StarMath
2201 can have all possible options used at the same time, whereas
2202 Mathtype cannot. The ordering of the nodes for each system
2203 is quite different as well leading to some complexity
2205 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2207 sal_uInt8 nVariation
=0xff;
2208 if (pNode
->GetSubNode(LSUP
+1))
2211 if (pNode
->GetSubNode(LSUB
+1))
2214 else if ( nullptr != pNode
->GetSubNode(LSUB
+1) )
2218 if (nVariation
!=0xff)
2220 pS
->WriteUChar( TMPL
); //Template
2221 pS
->WriteUChar( 0x2c ); //selector
2222 pS
->WriteUChar( nVariation
);
2223 pS
->WriteUChar( 0x00 ); //options
2224 pS
->WriteUChar( 0x0B );
2226 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2228 pS
->WriteUChar( LINE
); //line
2229 HandleNodes(pTemp
,nLevel
+1);
2230 pS
->WriteUChar( END
); //line
2233 pS
->WriteUChar( LINE
|0x10 );
2234 if (nullptr != (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2236 pS
->WriteUChar( LINE
); //line
2237 HandleNodes(pTemp
,nLevel
+1);
2238 pS
->WriteUChar( END
); //line
2241 pS
->WriteUChar( LINE
|0x10 );
2242 pS
->WriteUChar( END
);
2247 sal_uInt8 nVariation2
=HandleCScript(pNode
,nullptr,nLevel
);
2249 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2251 HandleNodes(pTemp
,nLevel
+1);
2254 if (nVariation2
!= 0xff)
2255 pS
->WriteUChar( END
);
2257 if (nullptr != (pNode
->GetSubNode(RSUP
+1)))
2260 if (pNode
->GetSubNode(RSUB
+1))
2263 else if (nullptr != pNode
->GetSubNode(RSUB
+1))
2266 if (nVariation
!=0xff)
2268 pS
->WriteUChar( TMPL
); //Template
2269 pS
->WriteUChar( 0x0F ); //selector
2270 pS
->WriteUChar( nVariation
);
2271 pS
->WriteUChar( 0x00 ); //options
2272 pS
->WriteUChar( 0x0B );
2274 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2276 pS
->WriteUChar( LINE
); //line
2277 HandleNodes(pTemp
,nLevel
+1);
2278 pS
->WriteUChar( END
); //line
2281 pS
->WriteUChar( LINE
|0x10 );
2282 if (nullptr != (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2284 pS
->WriteUChar( LINE
); //line
2285 HandleNodes(pTemp
,nLevel
+1);
2286 pS
->WriteUChar( END
); //line
2289 pS
->WriteUChar( LINE
|0x10 );
2290 pS
->WriteUChar( END
); //line
2293 //After subscript mathtype will keep the size of
2294 //normal text at the subscript size, sigh.
2295 pS
->WriteUChar( 0x0A );
2299 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2302 pS
->WriteUChar( TMPL
); //Template
2303 pS
->WriteUChar( 0x0E ); //selector
2304 pS
->WriteUChar( 0x00 ); //variation
2305 pS
->WriteUChar( 0x00 ); //options
2307 pS
->WriteUChar( 0x0A );
2308 pS
->WriteUChar( LINE
); //line
2309 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2310 HandleNodes(pTemp
,nLevel
+1);
2311 pS
->WriteUChar( END
);
2313 pS
->WriteUChar( 0x0A );
2314 pS
->WriteUChar( LINE
); //line
2315 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2316 HandleNodes(pTemp
,nLevel
+1);
2317 pS
->WriteUChar( END
);
2319 pS
->WriteUChar( END
);
2323 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2326 SmNode
*pLeft
=pNode
->GetSubNode(0);
2327 SmNode
*pRight
=pNode
->GetSubNode(2);
2329 pS
->WriteUChar( TMPL
); //Template
2330 bIsReInterpBrace
=false;
2331 sal_uInt8 nBSpec
=0x10;
2332 auto nLoc
= pS
->Tell();
2335 switch (pLeft
->GetToken().eType
)
2338 pS
->WriteUChar( tmANGLE
); //selector
2339 pS
->WriteUChar( 0 ); //variation
2340 pS
->WriteUChar( 0 ); //options
2343 pS
->WriteUChar( tmBRACE
); //selector
2344 pS
->WriteUChar( 0 ); //variation
2345 pS
->WriteUChar( 0 ); //options
2349 pS
->WriteUChar( tmBRACK
); //selector
2350 pS
->WriteUChar( 0 ); //variation
2351 pS
->WriteUChar( 0 ); //options
2355 pS
->WriteUChar( tmFLOOR
); //selector
2356 pS
->WriteUChar( 0 ); //variation
2357 pS
->WriteUChar( 0 ); //options
2360 pS
->WriteUChar( tmBAR
); //selector
2361 pS
->WriteUChar( 0 ); //variation
2362 pS
->WriteUChar( 0 ); //options
2366 pS
->WriteUChar( tmDBAR
); //selector
2367 pS
->WriteUChar( 0 ); //variation
2368 pS
->WriteUChar( 0 ); //options
2371 pS
->WriteUChar( tmPAREN
); //selector
2372 pS
->WriteUChar( 0 ); //variation
2373 pS
->WriteUChar( 0 ); //options
2379 if (nullptr != (pTemp
= pNode
->GetSubNode(1)))
2381 pS
->WriteUChar( LINE
); //line
2382 HandleNodes(pTemp
,nLevel
+1);
2383 pS
->WriteUChar( END
); //options
2387 HandleNodes(pLeft
,nLevel
+1);
2388 if (bIsReInterpBrace
)
2390 auto nLoc2
= pS
->Tell();
2392 pS
->WriteUChar( 0x2D );
2394 pS
->WriteUChar( CHAR
);
2395 pS
->WriteUChar( 0x96 );
2396 pS
->WriteUInt16( 0xEC07 );
2397 bIsReInterpBrace
=false;
2400 HandleNodes(pRight
,nLevel
+1);
2402 pS
->WriteUChar( END
);
2406 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2409 pS
->WriteUChar( TMPL
); //Template
2410 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2411 pS
->WriteUChar( tmLHBRACE
); //selector
2413 pS
->WriteUChar( tmUHBRACE
); //selector
2414 pS
->WriteUChar( 0 ); //variation
2415 pS
->WriteUChar( 0 ); //options
2417 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
2419 pS
->WriteUChar( LINE
); //line
2420 HandleNodes(pTemp
,nLevel
+1);
2421 pS
->WriteUChar( END
); //options
2424 if (nullptr != (pTemp
= pNode
->GetSubNode(2)))
2426 pS
->WriteUChar( LINE
); //line
2427 HandleNodes(pTemp
,nLevel
+1);
2428 pS
->WriteUChar( END
); //options
2430 pS
->WriteUChar( END
);
2433 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2435 if (HandleLim(pNode
,nLevel
))
2439 sal_uInt8 nVariation
;
2441 switch (pNode
->GetToken().eType
)
2448 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2449 pNode
->GetSubNode(1),nLevel
,&nPos
,false);
2452 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2453 pNode
->GetSubNode(1),nLevel
,&nPos
);
2457 sal_uInt8 nOldVariation
=nVariation
;
2458 sal_uInt8 nIntVariation
=nVariation
;
2461 if (nVariation
!= 0xff)
2465 if (nVariation
== 2)
2470 else if (nVariation
== 0)
2472 else if (nVariation
== 1)
2480 pS
->WriteUChar( TMPL
);
2481 switch(pNode
->GetToken().eType
)
2485 if (nOldVariation
!= 0xff)
2486 pS
->WriteUChar( 0x18 ); //selector
2488 pS
->WriteUChar( 0x15 ); //selector
2489 pS
->WriteUChar( nIntVariation
); //variation
2492 if (nOldVariation
!= 0xff)
2494 pS
->WriteUChar( 0x19 );
2495 pS
->WriteUChar( 0x01 );
2499 pS
->WriteUChar( 0x16 );
2500 pS
->WriteUChar( 0x00 );
2504 if (nOldVariation
!= 0xff)
2506 pS
->WriteUChar( 0x1a );
2507 pS
->WriteUChar( 0x01 );
2511 pS
->WriteUChar( 0x17 );
2512 pS
->WriteUChar( 0x00 );
2516 if (nOldVariation
!= 0xff)
2518 pS
->WriteUChar( 0x18 );
2519 pS
->WriteUChar( 0x02 );
2523 pS
->WriteUChar( 0x15 );
2524 pS
->WriteUChar( 0x03 );
2528 if (nOldVariation
!= 0xff)
2530 pS
->WriteUChar( 0x19 );
2531 pS
->WriteUChar( 0x00 );
2535 pS
->WriteUChar( 0x16 );
2536 pS
->WriteUChar( 0x02 );
2540 if (nOldVariation
!= 0xff)
2542 pS
->WriteUChar( 0x1a );
2543 pS
->WriteUChar( 0x00 );
2547 pS
->WriteUChar( 0x17 );
2548 pS
->WriteUChar( 0x02 );
2553 pS
->WriteUChar( 0x1d );
2554 pS
->WriteUChar( nVariation
);
2557 pS
->WriteUChar( 0x1f );
2558 pS
->WriteUChar( nVariation
);
2561 pS
->WriteUChar( 0x21 );
2562 pS
->WriteUChar( nVariation
);
2565 pS
->WriteUChar( 0 ); //options
2571 pS
->WriteUChar( LINE
); //line
2572 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2573 pS
->WriteUChar( END
); //line
2574 pS
->WriteUChar( LINE
|0x10 );
2575 pS
->WriteUChar( LINE
|0x10 );
2578 pS
->WriteUChar( 0x0D );
2579 switch(pNode
->GetToken().eType
)
2583 pS
->WriteUChar( CHAR
);
2584 pS
->WriteUChar( 0x86 );
2585 pS
->WriteUInt16( 0x2211 );
2588 pS
->WriteUChar( CHAR
);
2589 pS
->WriteUChar( 0x86 );
2590 pS
->WriteUInt16( 0x220F );
2593 pS
->WriteUChar( CHAR
);
2594 pS
->WriteUChar( 0x8B );
2595 pS
->WriteUInt16( 0x2210 );
2599 pS
->WriteUChar( CHAR
);
2600 pS
->WriteUChar( 0x86 );
2601 pS
->WriteUInt16( 0x222B );
2605 pS
->WriteUChar( CHAR
);
2606 pS
->WriteUChar( 0x86 );
2607 pS
->WriteUInt16( 0x222B );
2612 pS
->WriteUChar( CHAR
);
2613 pS
->WriteUChar( 0x86 );
2614 pS
->WriteUInt16( 0x222B );
2617 pS
->WriteUChar( END
);
2618 pS
->WriteUChar( 0x0A );
2622 bool MathType::HandlePile(int &rSetAlign
, int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2625 pS
->ReadUChar( nHAlign
);
2626 pS
->ReadUChar( nVAlign
);
2628 HandleAlign(nHAlign
, rSetAlign
);
2630 rRet
.append(" stack {\n");
2631 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, -1, -1 );
2632 int nRemoveFrom
= rRet
.getLength() >= 3 ? rRet
.getLength() - 3 : 0;
2633 rRet
.remove(nRemoveFrom
, 2);
2644 bool MathType::HandleMatrix(int nLevel
, sal_uInt8 nSelector
, sal_uInt8 nVariation
)
2646 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
,nVAlign
;
2647 pS
->ReadUChar( nVAlign
);
2648 pS
->ReadUChar( nH_just
);
2649 pS
->ReadUChar( nV_just
);
2650 pS
->ReadUChar( nRows
);
2651 pS
->ReadUChar( nCols
);
2652 int nBytes
= ((nRows
+1)*2)/8;
2653 if (((nRows
+1)*2)%8)
2655 pS
->SeekRel(nBytes
);
2656 nBytes
= ((nCols
+1)*2)/8;
2657 if (((nCols
+1)*2)%8)
2659 pS
->SeekRel(nBytes
);
2660 rRet
.append(" matrix {\n");
2661 bool bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
, nRows
, nCols
);
2663 sal_Int32 nI
= rRet
.lastIndexOf('#');
2665 if (rRet
[nI
-1] != '#') //missing column
2668 rRet
.append("\n} ");
2672 bool MathType::HandleTemplate(int nLevel
, sal_uInt8
&rSelector
,
2673 sal_uInt8
&rVariation
, sal_Int32
&rLastTemplateBracket
)
2675 sal_uInt8 nOption
; //This appears utterly unused
2676 pS
->ReadUChar( rSelector
);
2677 pS
->ReadUChar( rVariation
);
2678 pS
->ReadUChar( nOption
);
2679 OSL_ENSURE(rSelector
< 48,"Selector out of range");
2680 if ((rSelector
>= 21) && (rSelector
<=26))
2682 OSL_ENSURE(nOption
< 2,"Option out of range");
2684 else if (rSelector
<= 12)
2686 OSL_ENSURE(nOption
< 3,"Option out of range");
2689 //For the (broken) case where one subscript template ends, and there is
2690 //another one after it, mathtype handles it as if the second one was
2691 //inside the first one and renders it as sub of sub
2693 if ( (rSelector
== 0xf) && (rLastTemplateBracket
!= -1) )
2696 for (sal_Int32 nI
= rLastTemplateBracket
+1; nI
< rRet
.getLength(); nI
++ )
2697 if (rRet
[nI
] != ' ')
2705 bool bRet
= HandleRecords( nLevel
+1, rSelector
, rVariation
);
2709 if (rLastTemplateBracket
< rRet
.getLength())
2710 rRet
.remove(rLastTemplateBracket
, 1);
2712 rLastTemplateBracket
= -1;
2714 if (rSelector
== 0xf)
2715 rLastTemplateBracket
= rRet
.lastIndexOf('}');
2717 rLastTemplateBracket
= -1;
2719 rSelector
= sal::static_int_cast
< sal_uInt8
>(-1);
2723 void MathType::HandleEmblishments()
2728 pS
->ReadUChar( nEmbel
);
2734 rRet
.append(" dot ");
2737 rRet
.append(" ddot ");
2740 rRet
.append(" dddot ");
2745 sPost
.append(" sup {}");
2746 nPostSup
= sPost
.getLength();
2748 sPost
.insert(nPostSup
-1," ' ");
2754 sPost
.append(" sup {}");
2755 nPostSup
= sPost
.getLength();
2757 sPost
.insert(nPostSup
-1," '' ");
2763 sPost
.append(" lsup {}");
2764 nPostlSup
= sPost
.getLength();
2766 sPost
.insert(nPostlSup
-1," ' ");
2770 rRet
.append(" tilde ");
2773 rRet
.append(" hat ");
2776 rRet
.append(" vec ");
2779 rRet
.append(" overstrike ");
2782 rRet
.append(" bar ");
2787 sPost
.append(" sup {}");
2788 nPostSup
= sPost
.getLength();
2790 sPost
.insert(nPostSup
-1," ''' ");
2794 rRet
.append(" breve ");
2797 OSL_ENSURE(nEmbel
< 21,"Embel out of range");
2805 void MathType::HandleSetSize()
2808 pS
->ReadUChar( nTemp
);
2812 pS
->ReadInt16( nLSize
);
2816 pS
->ReadUChar( nTemp
);
2818 pS
->ReadInt16( nDSize
);
2822 pS
->ReadUChar( nTemp
);
2828 bool MathType::HandleChar(sal_Int32
&rTextStart
, int &rSetSize
, int nLevel
,
2829 sal_uInt8 nTag
, sal_uInt8 nSelector
, sal_uInt8 nVariation
, bool bSilent
)
2831 sal_Unicode
nChar(0);
2836 //This is a candidate for function recognition, whatever
2840 sal_uInt8 nOldTypeFace
= nTypeFace
;
2841 pS
->ReadUChar( nTypeFace
);
2844 sal_uInt8
nChar8(0);
2845 pS
->ReadUChar( nChar8
);
2849 pS
->ReadUtf16( nChar
);
2852 bad character, old mathtype < 3 has these
2859 //A bit tricky, the character emblishments for
2860 //mathtype can all be listed after each other, in
2861 //starmath some must go before the character and some
2862 //must go after. In addition some of the emblishments
2863 //may repeated and in starmath some of these groups
2864 //must be gathered together. sPost is the portion that
2865 //follows the char and nPostSup and nPostlSup are the
2866 //indexes at which this class of emblishment is
2869 nPostSup
= nPostlSup
= 0;
2870 int nOriglen
=rRet
.getLength()-rTextStart
;
2871 rRet
.append(" {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2872 if ((!bSilent
) && (nOriglen
> 1))
2874 bRet
= HandleRecords( nLevel
+1, nSelector
, nVariation
);
2880 TypeFaceToString(aStr
,nOldTypeFace
);
2882 rRet
.insert(std::min(rTextStart
, rRet
.getLength()), aStr
);
2885 TypeFaceToString(aStr
,nTypeFace
);
2886 rRet
.append(aStr
).append("{");
2890 rTextStart
= rRet
.getLength();
2896 sal_Int32 nOldLen
= rRet
.getLength();
2898 HandleSize(nLSize
,nDSize
,rSetSize
) ||
2899 (nOldTypeFace
!= nTypeFace
)
2902 if ((nOldLen
- rTextStart
) > 1)
2904 rRet
.insert(nOldLen
, "\"");
2906 TypeFaceToString(aStr
,nOldTypeFace
);
2908 rRet
.insert(rTextStart
,aStr
);
2910 rTextStart
= rRet
.getLength();
2912 nOldLen
= rRet
.getLength();
2913 if (!LookupChar(nChar
,rRet
,nVersion
,nTypeFace
))
2915 if (nOldLen
- rTextStart
> 1)
2917 rRet
.insert(nOldLen
, "\"");
2919 TypeFaceToString(aStr
,nOldTypeFace
);
2921 rRet
.insert(rTextStart
, aStr
);
2923 rTextStart
= rRet
.getLength();
2925 lcl_PrependDummyTerm(rRet
, rTextStart
);
2928 if ((xfEMBELL(nTag
)) && (!bSilent
))
2930 rRet
.append("}}").append(sPost
); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2931 rTextStart
= rRet
.getLength();
2936 bool MathType::HandleLim(SmNode
*pNode
,int nLevel
)
2939 //Special case for the "lim" option in StarMath
2940 if ((pNode
->GetToken().eType
== TLIM
)
2941 || (pNode
->GetToken().eType
== TLIMSUP
)
2942 || (pNode
->GetToken().eType
== TLIMINF
)
2945 if (pNode
->GetSubNode(1))
2947 sal_uInt8 nVariation2
=HandleCScript(pNode
->GetSubNode(0),nullptr,
2950 pS
->WriteUChar( 0x0A );
2951 pS
->WriteUChar( LINE
); //line
2952 pS
->WriteUChar( CHAR
|0x10 );
2953 pS
->WriteUChar( 0x82 );
2954 pS
->WriteUInt16( 'l' );
2955 pS
->WriteUChar( CHAR
|0x10 );
2956 pS
->WriteUChar( 0x82 );
2957 pS
->WriteUInt16( 'i' );
2958 pS
->WriteUChar( CHAR
|0x10 );
2959 pS
->WriteUChar( 0x82 );
2960 pS
->WriteUInt16( 'm' );
2962 if (pNode
->GetToken().eType
== TLIMSUP
)
2964 pS
->WriteUChar( CHAR
); //some space
2965 pS
->WriteUChar( 0x98 );
2966 pS
->WriteUInt16( 0xEB04 );
2968 pS
->WriteUChar( CHAR
|0x10 );
2969 pS
->WriteUChar( 0x82 );
2970 pS
->WriteUInt16( 's' );
2971 pS
->WriteUChar( CHAR
|0x10 );
2972 pS
->WriteUChar( 0x82 );
2973 pS
->WriteUInt16( 'u' );
2974 pS
->WriteUChar( CHAR
|0x10 );
2975 pS
->WriteUChar( 0x82 );
2976 pS
->WriteUInt16( 'p' );
2978 else if (pNode
->GetToken().eType
== TLIMINF
)
2980 pS
->WriteUChar( CHAR
); //some space
2981 pS
->WriteUChar( 0x98 );
2982 pS
->WriteUInt16( 0xEB04 );
2984 pS
->WriteUChar( CHAR
|0x10 );
2985 pS
->WriteUChar( 0x82 );
2986 pS
->WriteUInt16( 'i' );
2987 pS
->WriteUChar( CHAR
|0x10 );
2988 pS
->WriteUChar( 0x82 );
2989 pS
->WriteUInt16( 'n' );
2990 pS
->WriteUChar( CHAR
|0x10 );
2991 pS
->WriteUChar( 0x82 );
2992 pS
->WriteUInt16( 'f' );
2996 pS
->WriteUChar( CHAR
); //some space
2997 pS
->WriteUChar( 0x98 );
2998 pS
->WriteUInt16( 0xEB04 );
3000 if (nVariation2
!= 0xff)
3002 pS
->WriteUChar( END
);
3003 pS
->WriteUChar( END
);
3005 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
3012 void MathType::HandleMAlign(SmNode
*pNode
,int nLevel
)
3014 sal_uInt8 nPushedHAlign
=nHAlign
;
3015 switch(pNode
->GetToken().eType
)
3027 size_t nSize
= pNode
->GetNumSubNodes();
3028 for (size_t i
= 0; i
< nSize
; ++i
)
3030 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
3031 HandleNodes(pTemp
,nLevel
+1);
3033 nHAlign
=nPushedHAlign
;
3036 void MathType::HandleMath(SmNode
*pNode
)
3038 if (pNode
->GetToken().eType
== TMLINE
)
3040 pS
->WriteUChar( END
);
3041 pS
->WriteUChar( LINE
);
3042 bIsReInterpBrace
=true;
3045 SmMathSymbolNode
*pTemp
= static_cast<SmMathSymbolNode
*>(pNode
);
3046 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3048 sal_Unicode nArse
= SmTextNode::ConvertSymbolToUnicode(pTemp
->GetText()[i
]);
3049 if ((nArse
== 0x2224) || (nArse
== 0x2288) || (nArse
== 0x2285) ||
3052 pS
->WriteUChar( CHAR
|0x20 );
3054 else if (nPendingAttributes
&&
3055 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3057 pS
->WriteUChar( 0x22 );
3060 pS
->WriteUChar( CHAR
); //char without formula recognition
3061 //The typeface seems to be MTEXTRA for unicode characters,
3062 //though how to determine when mathtype chooses one over
3063 //the other is unknown. This should do the trick
3066 if ( (nArse
== 0x2213) || (nArse
== 0x2218) ||
3067 (nArse
== 0x210F) || (
3068 (nArse
>= 0x22EE) && (nArse
<= 0x22FF)
3071 nBias
= 0xB; //typeface
3073 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3074 nBias
= 0x2; //typeface
3075 else if ((nArse
> 0x2000) || (nArse
== 0x00D7))
3076 nBias
= 0x6; //typeface
3077 else if (nArse
== 0x3d1)
3079 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3080 nBias
= 0xB; //typeface
3082 nBias
= 0x3; //typeface
3084 pS
->WriteUChar( nSpec
+nBias
+128 ); //typeface
3086 if (nArse
== 0x2224)
3088 pS
->WriteUInt16( 0x7C );
3089 pS
->WriteUChar( EMBEL
);
3090 pS
->WriteUChar( 0x0A );
3091 pS
->WriteUChar( END
); //end embel
3092 pS
->WriteUChar( END
); //end embel
3094 else if (nArse
== 0x2225)
3095 pS
->WriteUInt16( 0xEC09 );
3096 else if (nArse
== 0xE421)
3097 pS
->WriteUInt16( 0x2265 );
3098 else if (nArse
== 0x230A)
3099 pS
->WriteUInt16( 0xF8F0 );
3100 else if (nArse
== 0x230B)
3101 pS
->WriteUInt16( 0xF8FB );
3102 else if (nArse
== 0xE425)
3103 pS
->WriteUInt16( 0x2264 );
3104 else if (nArse
== 0x226A)
3106 pS
->WriteUInt16( 0x3C );
3107 pS
->WriteUChar( CHAR
);
3108 pS
->WriteUChar( 0x98 );
3109 pS
->WriteUInt16( 0xEB01 );
3110 pS
->WriteUChar( CHAR
);
3111 pS
->WriteUChar( 0x86 );
3112 pS
->WriteUInt16( 0x3c );
3114 else if (nArse
== 0x2288)
3116 pS
->WriteUInt16( 0x2286 );
3117 pS
->WriteUChar( EMBEL
);
3118 pS
->WriteUChar( 0x0A );
3119 pS
->WriteUChar( END
); //end embel
3120 pS
->WriteUChar( END
); //end embel
3122 else if (nArse
== 0x2289)
3124 pS
->WriteUInt16( 0x2287 );
3125 pS
->WriteUChar( EMBEL
);
3126 pS
->WriteUChar( 0x0A );
3127 pS
->WriteUChar( END
); //end embel
3128 pS
->WriteUChar( END
); //end embel
3130 else if (nArse
== 0x2285)
3132 pS
->WriteUInt16( 0x2283 );
3133 pS
->WriteUChar( EMBEL
);
3134 pS
->WriteUChar( 0x0A );
3135 pS
->WriteUChar( END
); //end embel
3136 pS
->WriteUChar( END
); //end embel
3139 pS
->WriteUInt16( nArse
);
3141 nPendingAttributes
= 0;
3144 void MathType::HandleAttributes(SmNode
*pNode
,int nLevel
)
3146 int nOldPending
= 0;
3147 SmNode
*pTemp
= nullptr;
3148 SmTextNode
*pIsText
= nullptr;
3150 if (nullptr != (pTemp
= pNode
->GetSubNode(0)))
3152 pIsText
= static_cast<SmTextNode
*>(pNode
->GetSubNode(1));
3154 switch (pTemp
->GetToken().eType
)
3157 //there's just no way we can now handle any character
3158 //attributes (from mathtypes perspective) centered
3159 //over an expression but above template attributes
3160 //such as widevec and similar constructs
3161 //we have to drop them
3162 nOldPending
= StartTemplate(0x2f,0x01);
3164 case TCHECK
: //Not Exportable
3165 case TACUTE
: //Not Exportable
3166 case TGRAVE
: //Not Exportable
3167 case TCIRCLE
: //Not Exportable
3168 case TWIDEHARPOON
: //Not Exportable
3169 case TWIDETILDE
: //Not Exportable
3170 case TWIDEHAT
: //Not Exportable
3173 nOldPending
= StartTemplate(0x10);
3175 case TOVERLINE
: //If the next node is not text
3176 //or text with more than one char
3177 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3178 (pIsText
->GetText().getLength() > 1))
3179 nOldPending
= StartTemplate(0x11);
3182 nPendingAttributes
++;
3188 HandleNodes(pIsText
,nLevel
+1);
3190 switch (pTemp
->GetToken().eType
)
3194 EndTemplate(nOldPending
);
3197 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3198 (pIsText
->GetText().getLength() > 1))
3199 EndTemplate(nOldPending
);
3205 //if there was no suitable place to put the attribute,
3206 //then we have to just give up on it
3207 if (nPendingAttributes
)
3208 nPendingAttributes
--;
3211 if ((nInsertion
!= 0) && nullptr != (pTemp
= pNode
->GetSubNode(0)))
3213 auto nPos
= pS
->Tell();
3215 pS
->Seek(nInsertion
);
3216 switch(pTemp
->GetToken().eType
)
3218 case TACUTE
: //Not Exportable
3219 case TGRAVE
: //Not Exportable
3220 case TCIRCLE
: //Not Exportable
3223 pS
->WriteUChar( 2 );
3226 pS
->WriteUChar( 3 );
3229 pS
->WriteUChar( 4 );
3232 pS
->WriteUChar( 8 );
3235 pS
->WriteUChar( 9 );
3238 pS
->WriteUChar( 11 );
3241 pS
->WriteUChar( 16 );
3244 if ((pIsText
->GetToken().eType
== TTEXT
) &&
3245 (pIsText
->GetText().getLength() == 1))
3246 pS
->WriteUChar( 17 );
3249 pS
->WriteUChar( 20 );
3258 pS
->WriteUChar( 17 );
3261 pS
->WriteUChar( 2 );
3269 void MathType::HandleText(SmNode
*pNode
)
3271 SmTextNode
*pTemp
= static_cast<SmTextNode
*>(pNode
);
3272 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3274 if (nPendingAttributes
&&
3275 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3277 pS
->WriteUChar( 0x22 ); //char, with attributes right
3278 //after the character
3281 pS
->WriteUChar( CHAR
);
3283 sal_uInt8 nFace
= 0x1;
3284 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3286 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3288 pS
->WriteUChar( nFace
+128 ); //typeface
3289 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3290 pS
->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar
) );
3292 //Mathtype can only have these sort of character
3293 //attributes on a single character, starmath can put them
3294 //anywhere, when the entity involved is a text run this is
3295 //a large effort to place the character attribute on the
3296 //central mathtype character so that it does pretty much
3297 //what the user probably has in mind. The attributes
3298 //filled in here are dummy ones which are replaced in the
3299 //ATTRIBUT handler if a suitable location for the
3300 //attributes was found here. Unfortunately it is
3301 //possible for starmath to place character attributes on
3302 //entities which cannot occur in mathtype e.g. a Summation
3303 //symbol so these attributes may be lost
3304 if (nPendingAttributes
&&
3305 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3307 pS
->WriteUChar( EMBEL
);
3308 while (nPendingAttributes
)
3310 pS
->WriteUChar( 2 );
3311 //wedge the attributes in here and clear
3313 nPendingAttributes
--;
3315 nInsertion
=pS
->Tell();
3316 pS
->WriteUChar( END
); //end embel
3317 pS
->WriteUChar( END
); //end embel
3322 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportMathType(SvStream
&rStream
)
3324 OUStringBuffer sText
;
3325 MathType
aEquation(sText
);
3329 bRet
= aEquation
.Parse(&rStream
);
3331 catch (const std::out_of_range
&)
3337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */