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 .
21 #include <mathtype.hxx>
22 #include <osl/diagnose.h>
23 #include <sfx2/docfile.hxx>
27 //These are the default MathType sizes
28 aSizeTable
.push_back(12);
29 aSizeTable
.push_back(8);
30 aSizeTable
.push_back(6);
31 aSizeTable
.push_back(24);
32 aSizeTable
.push_back(10);
33 aSizeTable
.push_back(12);
34 aSizeTable
.push_back(12);
37 These are the default MathType italic/bold settings If mathtype is changed
38 from its defaults, there is nothing we can do, as this information is not
39 stored in the document
42 for(sal_uInt8 i
=1;i
<=11;i
++)
58 aUserStyles
.insert(aFont
);
63 /*ToDo replace with table rather than switch, returns
64 sal_True in the case that the char is just a char, and
65 sal_False if the character is an operator which must not be
66 placed inside the quote sequence designed to protect
67 against being parsed as a keyword
69 General solution required to force starmath to handle
70 unicode math chars the way it handles its own math
71 chars rathar than handle them as text as it will do
72 for the default case below, i.e. incorrect spacing
73 between math symbols and ordinary text e.g. 1=2 rather
76 bool MathType::LookupChar(sal_Unicode nChar
,OUString
&rRet
,sal_uInt8 nVersion
,
80 const char *pC
= NULL
;
108 if ((nVersion
< 3) && (nTypeFace
== 0x86))
112 rRet
+= OUString( nChar
);
117 if ((nVersion
< 3) && (nTypeFace
== 0x81))
119 rRet
+= OUString( nChar
);
123 if ((nVersion
< 3) && (nTypeFace
== 0x84))
125 rRet
+= OUString( nChar
);
129 if ((nVersion
< 3) && (nTypeFace
== 0x84))
131 rRet
+= OUString( nChar
);
135 if ((nVersion
< 3) && (nTypeFace
== 0x84))
137 rRet
+= OUString( nChar
);
141 if ((nVersion
< 3) && (nTypeFace
== 0x84))
143 rRet
+= OUString( nChar
);
147 if ((nVersion
< 3) && (nTypeFace
== 0x84))
149 rRet
+= OUString( nChar
);
153 if ((nVersion
< 3) && (nTypeFace
== 0x84))
155 rRet
+= OUString( nChar
);
159 if ((nVersion
< 3) && (nTypeFace
== 0x82))
161 rRet
+= OUString( nChar
);
165 if ((nVersion
< 3) && (nTypeFace
== 0x86))
169 rRet
+= OUString( nChar
);
174 if ((nVersion
< 3) && (nTypeFace
== 0x86))
178 rRet
+= OUString( nChar
);
183 if ((nVersion
< 3) && (nTypeFace
== 0x86))
187 rRet
+= OUString( nChar
);
192 if ((nVersion
< 3) && (nTypeFace
== 0x85))
196 rRet
+= OUString( nChar
);
351 pC
= " intersection ";
400 pC
= " preccurlyeq ";
403 pC
= " succcurlyeq ";
444 rRet
+= " " + OUString( nChar
) + " ";
498 case 0xeb01: //no space
499 case 0xeb08: //normal space
502 case 0xef04: //tiny space
503 case 0xef05: //tiny space
504 case 0xeb02: //small space
505 case 0xeb04: //medium space
508 case 0xeb05: //large space
515 rRet
+= OUString( nChar
);
520 rRet
+= OUString::createFromAscii( pC
);
524 void MathTypeFont::AppendStyleToText(OUString
&rRet
)
526 const char *pC
= NULL
;
543 rRet
+= OUString::createFromAscii( pC
);
546 void MathType::TypeFaceToString(OUString
&rTxt
,sal_uInt8 nFace
)
548 MathTypeFont
aFont(nFace
);
549 MathTypeFontSet::iterator aItr
= aUserStyles
.find(aFont
);
550 if (aItr
!= aUserStyles
.end())
551 aFont
.nStyle
= aItr
->nStyle
;
552 aFont
.AppendStyleToText(rTxt
);
555 int MathType::Parse(SotStorage
*pStor
)
557 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(
558 OUString("Equation Native"),
559 STREAM_STD_READ
| StreamMode::NOCREATE
);
560 if ( (!xSrc
.Is()) || (SVSTREAM_OK
!= xSrc
->GetError()))
563 pS
->SetEndian( SvStreamEndian::LITTLE
);
567 pS
->ReadUChar( nVersion
);
568 pS
->ReadUChar( nPlatform
);
569 pS
->ReadUChar( nProduct
);
570 pS
->ReadUChar( nProdVersion
);
571 pS
->ReadUChar( nProdSubVersion
);
573 if (nVersion
> 3) // allow only supported versions of MathType to be parsed
576 int nRet
= HandleRecords();
577 //little crude hack to close occasionally open expressions
578 //a sophisticated system to determine what expressions are
579 //opened is required, but this is as much work as rewriting
580 //starmaths internals.
583 #if OSL_DEBUG_LEVEL > 1
587 //sigh, theres no point! MathType (in some bizarre subvarient) pads
588 //the end of the formula with ENDs (0)'s
589 sal_uLong nEnd
= pS
->Tell();
590 OSL_ENSURE(nEnd
== pS
->Seek(STREAM_SEEK_TO_END
),
591 "Possibly unfully parsed formula");
597 static void lcl_PrependDummyTerm(OUString
&rRet
, sal_Int32
&rTextStart
)
599 if ((rTextStart
< rRet
.getLength()) &&
600 (rRet
[rTextStart
] == '=') &&
601 ((rTextStart
== 0) || (rRet
[ rTextStart
-1 ] == '{'))
604 rRet
= rRet
.replaceAt(rTextStart
,0," {}");
609 static void lcl_AppendDummyTerm(OUString
&rRet
)
612 for(int nI
=rRet
.getLength()-1;nI
>= 0; nI
--)
614 sal_Int32 nIdx
= sal::static_int_cast
< sal_Int32
>(nI
);
615 sal_Unicode nChar
= rRet
[nIdx
];
618 if (rRet
[nIdx
] != '{')
622 if (!bOk
) //No term, use dummy
626 void MathType::HandleNudge()
629 pS
->ReadUChar( nXNudge
);
631 pS
->ReadUChar( nYNudge
);
632 if (nXNudge
== 128 && nYNudge
== 128)
634 sal_uInt16 nXLongNudge
;
635 sal_uInt16 nYLongNudge
;
636 pS
->ReadUInt16( nXLongNudge
);
637 pS
->ReadUInt16( nYLongNudge
);
640 /*Fabously complicated as many tokens have to be reordered and generally
641 *moved around from mathtypes paradigm to starmaths.*/
642 int MathType::HandleRecords(int nLevel
,sal_uInt8 nSelector
,
643 sal_uInt8 nVariation
, int nMatrixRows
,int nMatrixCols
)
645 sal_uInt8 nTag
,nRecord
;
646 sal_uInt8 nTabType
,nTabStops
;
647 sal_uInt16 nTabOffset
;
648 int i
,nRet
=1,newline
=0;
651 OUString sPush
,sMainTerm
;
652 int nSetSize
=0,nSetAlign
=0;
653 int nCurRow
=0,nCurCol
=0;
654 bool bOpenString
=false;
655 sal_Int32 nTextStart
= 0;
656 sal_Int32 nSubSupStartPos
= 0;
657 sal_Int32 nLastTemplateBracket
=-1;
662 pS
->ReadUChar( nTag
);
665 /*MathType strings can of course include words which
666 *are StarMath keywords, the simplest solution is
667 to escape strings of greater than len 1 with double
668 quotes to avoid scanning the TokenTable for matches
670 Unfortunately it may turn out that the string gets
671 split during the handling of a character emblishment
672 so this special case must be handled in the
673 character handler case 2:
675 if ((nRecord
== CHAR
) && (!bIsSilent
) && (!bOpenString
))
678 nTextStart
= rRet
.getLength();
680 else if ((nRecord
!= CHAR
) && (bOpenString
))
683 if ((rRet
.getLength() - nTextStart
) > 1)
686 TypeFaceToString(aStr
,nTypeFace
);
688 rRet
= rRet
.replaceAt(nTextStart
,0,aStr
);
691 else if (nRecord
== END
&& !rRet
.isEmpty())
693 sal_Unicode cChar
= 0;
694 sal_Int32 nI
= rRet
.getLength()-1;
695 while (nI
&& ((cChar
= rRet
[nI
]) == ' '))
697 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
710 rRet
+= "\nnewline\n";
718 else if (nVariation
==1)
719 rRet
+= " \\langle ";
724 else if (nVariation
==1)
728 if ((nVariation
==0) || (nVariation
==1))
729 rRet
+= " left lbrace ";
731 rRet
+= " left none ";
736 else if (nVariation
==1)
746 else if (nVariation
==1)
752 else if (nVariation
==1)
753 rRet
+= " \\ldline ";
756 if (nVariation
== 0 || nVariation
== 1)
757 rRet
+= " left lfloor ";
758 else if (nVariation
==1)
759 rRet
+= " left none ";
764 else if (nVariation
==1)
798 nSubSupStartPos
= rRet
.getLength();
799 if ((nVariation
== 0) ||
800 ((nVariation
== 2) && (nPart
==1)))
802 lcl_AppendDummyTerm(rRet
);
805 else if ((nVariation
== 1) ||
806 ((nVariation
== 2) && (nPart
==0)))
808 lcl_AppendDummyTerm(rRet
);
815 rRet
+= " {underline ";
816 else if (nVariation
== 1)
817 rRet
+= " {underline underline ";
822 rRet
+= " {overline ";
823 else if (nVariation
== 1)
824 rRet
+= " {overline overline ";
831 rRet
+= " widevec ";//left arrow above
832 else if (nVariation
== 1)
833 rRet
+= " widevec ";//left arrow below
841 rRet
+= " widevec ";//right arrow above
842 else if (nVariation
== 1)
843 rRet
+= " widevec ";//right arrow below
851 rRet
+= " widevec ";//double arrow above
852 else if (nVariation
== 1)
853 rRet
+= " widevec ";//double arrow below
860 if ((nVariation
== 3) || (nVariation
== 4))
864 if ( (nVariation
!= 0) && (nVariation
!= 3))
870 if (((nVariation
== 1) ||
871 (nVariation
== 4)) && (nPart
==1))
873 else if ((nVariation
== 2) && (nPart
==2))
875 else if ((nVariation
== 2) && (nPart
==1))
882 if ((nVariation
== 2) || (nVariation
== 3))
886 if ( (nVariation
!= 0) && (nVariation
!= 2))
892 if (((nVariation
== 1) ||
893 (nVariation
== 3)) && (nPart
==1))
900 if ((nVariation
== 2) || (nVariation
== 3))
904 if ( (nVariation
!= 0) && (nVariation
!= 2))
910 if (((nVariation
== 1) ||
911 (nVariation
== 3)) && (nPart
==1))
925 if (((nVariation
== 1) ||
926 (nVariation
== 2)) && (nPart
==1))
928 else if ((nVariation
== 0) && (nPart
==2))
930 else if ((nVariation
== 0) && (nPart
==1))
976 if ((nVariation
== 0) && (nPart
==1))
978 else if ((nVariation
== 1) && (nPart
==2))
980 else if ((nVariation
== 1) && (nPart
==1))
991 if ((nVariation
== 0) && (nPart
==1))
993 else if ((nVariation
== 1) && (nPart
==2))
995 else if ((nVariation
== 1) && (nPart
==1))
1003 if (nVariation
!= 2)
1009 if ((nVariation
== 0) && (nPart
==1))
1011 else if ((nVariation
== 1) && (nPart
==2))
1013 else if ((nVariation
== 1) && (nPart
==1))
1024 if ((nVariation
== 0) && (nPart
==1))
1026 else if ((nVariation
== 1) && (nPart
==2))
1028 else if ((nVariation
== 1) && (nPart
==1))
1036 if (nVariation
!= 2)
1042 if ((nVariation
== 0) && (nPart
==1))
1044 else if ((nVariation
== 1) && (nPart
==2))
1046 else if ((nVariation
== 1) && (nPart
==1))
1057 if ((nVariation
== 0) && (nPart
==1))
1059 else if ((nVariation
== 1) && (nPart
==2))
1061 else if ((nVariation
== 1) && (nPart
==1))
1068 rRet
+= " union"; //union
1069 if (nVariation
!= 2)
1075 if ((nVariation
== 0) && (nPart
==1))
1077 else if ((nVariation
== 1) && (nPart
==2))
1079 else if ((nVariation
== 1) && (nPart
==1))
1086 rRet
+= " union"; //union
1090 if ((nVariation
== 0) && (nPart
==1))
1092 else if ((nVariation
== 1) && (nPart
==2))
1094 else if ((nVariation
== 1) && (nPart
==1))
1101 rRet
+= " intersect"; //intersect
1102 if (nVariation
!= 2)
1108 if ((nVariation
== 0) && (nPart
==1))
1110 else if ((nVariation
== 1) && (nPart
==2))
1112 else if ((nVariation
== 1) && (nPart
==1))
1119 rRet
+= " intersect"; //intersect
1123 if ((nVariation
== 0) && (nPart
==1))
1125 else if ((nVariation
== 1) && (nPart
==2))
1127 else if ((nVariation
== 1) && (nPart
==1))
1132 if ((nVariation
== 0) && (nPart
==1))
1134 else if ((nVariation
== 1) && (nPart
==1))
1136 else if ((nVariation
== 2) && (nPart
==1))
1138 else if ((nVariation
== 2) && (nPart
==2))
1143 if (nVariation
== 0)
1152 if (nVariation
== 0)
1159 if (nVariation
== 1)
1160 rRet
+= "overline ";
1171 if ((nVariation
== 0) && (nPart
==0))
1173 else if ((nVariation
== 2) && (nPart
==1))
1175 else if ((nVariation
== 1) && (nPart
==0))
1177 else if ((nVariation
== 2) && (nPart
==0))
1187 if ((nVariation
== 0) && (nPart
==0))
1189 else if ((nVariation
== 2) && (nPart
==1))
1191 else if ((nVariation
== 1) && (nPart
==0))
1193 else if ((nVariation
== 2) && (nPart
==0))
1200 if ((nVariation
== 0)
1201 || ((nVariation
== 2) && (nPart
==1)))
1203 else if ((nVariation
== 1)
1204 || ((nVariation
== 2) && (nPart
==0)))
1214 else if (nVariation
==1)
1216 rRet
+= " \\langle ";
1219 else if (nVariation
==2)
1221 rRet
+= " \\lline ";
1226 if (nVariation
== 0)
1227 rRet
+= " widevec ";//left below
1228 else if (nVariation
== 1)
1229 rRet
+= " widevec ";//right below
1230 else if (nVariation
== 2)
1231 rRet
+= " widevec ";//double headed below
1235 if (nVariation
== 0)
1236 rRet
+= " widevec ";//left above
1237 else if (nVariation
== 1)
1238 rRet
+= " widevec ";//right above
1239 else if (nVariation
== 2)
1240 rRet
+= " widevec ";//double headed above
1246 sal_Int16 nOldCurSize
=nCurSize
;
1247 sal_Int32 nSizeStartPos
= rRet
.getLength();
1248 HandleSize(nLSize
,nDSize
,nSetSize
);
1249 nRet
= HandleRecords(nLevel
+1);
1253 sal_Int32 nI
= rRet
.lastIndexOf('{');
1256 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1257 if (rRet
[nI
] != ' ')
1269 rRet
= rRet
.replaceAt( nSizeStartPos
, rRet
.getLength(), "" );
1271 nCurSize
=nOldCurSize
;
1275 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1283 else if (nVariation
==2)
1284 rRet
+= " \\rangle ";
1289 else if (nVariation
==2)
1293 if ((nVariation
==0) || (nVariation
==2))
1294 rRet
+= " right rbrace ";
1296 rRet
+= " right none ";
1301 else if (nVariation
==2)
1307 else if (nVariation
==2)
1308 rRet
+= " \\rline ";
1313 else if (nVariation
==2)
1314 rRet
+= " \\rdline ";
1317 if (nVariation
== 0 || nVariation
== 2)
1318 rRet
+= " right rfloor ";
1319 else if (nVariation
==2)
1320 rRet
+= " right none ";
1325 else if (nVariation
==2)
1326 rRet
+= " \\rceil ";
1338 if (nVariation
== 1)
1374 ((nVariation
== 2) || (nVariation
== 1)))
1378 sal_Int32 nI
= rRet
.lastIndexOf('{');
1381 for(nI
=nI
+1;nI
<rRet
.getLength();nI
++)
1382 if (rRet
[nI
] != ' ')
1394 rRet
= rRet
.replaceAt(nSubSupStartPos
, rRet
.getLength(), "");
1400 ((nVariation
== 2) || (nVariation
== 1)))
1428 rRet
+= "overbrace";
1437 rRet
+= "underbrace";
1444 else if ((nPart
==1) &&
1445 ((nVariation
== 2) || (nVariation
== 1)))
1452 if (nVariation
== 0)
1482 rRet
+= "wideslash";
1501 if (nVariation
!= 2)
1508 else if ((nPart
== 1) && (nVariation
== 0))
1515 else if ((nPart
== 1) && (nVariation
== 1))
1517 else if ((nPart
== 2) && (nVariation
== 1))
1530 if ((nVariation
!= 0) && (nVariation
!= 3))
1537 else if ((nPart
== 1) &&
1538 ((nVariation
== 1) || (nVariation
==4)))
1545 else if ((nPart
== 1) && (nVariation
== 2))
1547 else if ((nPart
== 2) && (nVariation
== 2))
1561 if ((nVariation
!= 0) && (nVariation
!= 2))
1568 else if ((nPart
== 1) &&
1569 ((nVariation
== 1) || (nVariation
==3)))
1586 else if ((nPart
== 1) &&
1587 ((nVariation
== 1) || (nVariation
==2)))
1594 else if ((nPart
== 1) && (nVariation
== 0))
1596 else if ((nPart
== 2) && (nVariation
== 0))
1614 else if (nPart
== 1)
1628 ((nVariation
== 0) || (nVariation
== 1)))
1634 else if ((nPart
== 0) && (nVariation
== 2))
1636 else if ((nPart
== 1) && (nVariation
== 2))
1642 else if ((nPart
== 2) || ((((nPart
== 1) &&
1643 (nVariation
== 0)) || (nVariation
== 1))))
1656 newline
--; //there is another term to arrive
1662 else if (nVariation
==1)
1663 rRet
+= " \\lline ";
1664 else if (nVariation
==2)
1665 rRet
+= " \\rangle ";
1671 bSilent
= true; //Skip the optional brackets and/or
1672 //symbols that follow some of these
1673 //records. Foo Data.
1675 /*In matrices and piles we cannot separate equation
1676 *lines with the newline keyword*/
1685 nRet
= HandleChar(nTextStart
,nSetSize
,nLevel
,nTag
,nSelector
,
1686 nVariation
,bSilent
);
1691 nRet
= HandleTemplate(nLevel
,nSelector
,nVariation
,
1692 nLastTemplateBracket
);
1697 nRet
= HandlePile(nSetAlign
,nLevel
,nSelector
,nVariation
);
1698 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,nCurCol
,nCurRow
);
1703 nRet
= HandleMatrix(nLevel
,nSelector
,nVariation
);
1704 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,nCurCol
,nCurRow
);
1709 HandleEmblishments();
1712 pS
->ReadUChar( nTabStops
);
1713 for (i
=0;i
<nTabStops
;i
++)
1715 pS
->ReadUChar( nTabType
);
1716 pS
->ReadUInt16( nTabOffset
);
1718 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1723 pS
->ReadUChar( aFont
.nTface
);
1725 The typeface number is the negative (which makes it
1726 positive) of the typeface value (unbiased) that appears in
1727 CHAR records that might follow a given FONT record
1729 aFont
.nTface
= 128-aFont
.nTface
;
1730 pS
->ReadUChar( aFont
.nStyle
);
1731 aUserStyles
.insert(aFont
);
1732 std::vector
<sal_Char
> aSeq
;
1736 pS
->ReadChar( nChar8
);
1739 aSeq
.push_back(nChar8
);
1741 // Do nothing to the font name now in aSeq!?
1759 while (nRecord
!= END
&& !pS
->IsEof());
1768 /*Simply determine if we are at the end of a record or the end of a line,
1769 *with fiddley logic to see if we are in a matrix or a pile or neither
1771 Note we cannot tell until after the event that this is the last entry
1772 of a pile, so we must strip the last separator of a pile after this
1773 is detected in the PILE handler
1775 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1776 int &rCurCol
,int &rCurRow
)
1780 if (rCurCol
== nMatrixCols
-1)
1782 if (rCurRow
!= nMatrixRows
-1)
1784 if (nMatrixRows
!=-1)
1793 if (nMatrixRows
!=-1)
1801 /* set the alignment of the following term, but starmath currently
1802 * cannot handle vertical alignment */
1803 void MathType::HandleAlign(sal_uInt8 nHorAlign
, sal_uInt8
/*nVAlign*/, int &rSetAlign
)
1821 /* set size of text, complexity due to overuse of signedness as a flag
1822 * indicator by mathtype file format*/
1823 bool MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1828 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1836 if (-nLstSize
/32 != nLastSize
)
1838 nLastSize
= nCurSize
;
1840 rRet
+= OUString::number(-nLstSize
/32);
1845 nCurSize
= -nLstSize
/32;
1850 /*sizetable should theoreticaly be filled with the default sizes
1851 *of the various font groupings matching starmaths equivalents
1852 in aTypeFaces, and a test would be done to see if the new font
1853 size would be the same as what starmath would have chosen for
1854 itself anyway in which case the size setting could be ignored*/
1855 nLstSize
= aSizeTable
.at(nLstSize
);
1856 nLstSize
= nLstSize
+ nDefSize
;
1857 if (nLstSize
!= nCurSize
)
1865 if (nLstSize
!= nLastSize
)
1867 nLastSize
= nCurSize
;
1869 rRet
+= OUString::number(nLstSize
);
1874 nCurSize
= nLstSize
;
1880 int MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1885 SvStream
*pStream
= rMedium
.GetOutStream();
1888 tools::SvRef
<SotStorage
> pStor
= new SotStorage( pStream
, false );
1890 SvGlobalName
aGName(0x0002ce02L
, 0x0000, 0x0000,0xc0,0x00,
1891 0x00,0x00,0x00,0x00,0x00,0x46 );
1892 pStor
->SetClass( aGName
, SotClipboardFormatId::NONE
, OUString("Microsoft Equation 3.0"));
1894 static sal_uInt8
const aCompObj
[] = {
1895 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1896 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1897 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1898 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1899 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1900 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1901 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1902 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1903 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1904 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1905 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1906 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1909 tools::SvRef
<SotStorageStream
> xStor( pStor
->OpenSotStream(OUString("\1CompObj")));
1910 xStor
->Write(aCompObj
,sizeof(aCompObj
));
1912 static sal_uInt8
const aOle
[] = {
1913 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1914 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1915 0x00, 0x00, 0x00, 0x00
1917 tools::SvRef
<SotStorageStream
> xStor2( pStor
->OpenSotStream(OUString("\1Ole")));
1918 xStor2
->Write(aOle
,sizeof(aOle
));
1922 tools::SvRef
<SotStorageStream
> xSrc
= pStor
->OpenSotStream(OUString("Equation Native"));
1923 if ( (!xSrc
.Is()) || (SVSTREAM_OK
!= xSrc
->GetError()))
1927 pS
->SetEndian( SvStreamEndian::LITTLE
);
1929 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1930 pS
->WriteUChar( 0x03 );
1931 pS
->WriteUChar( 0x01 );
1932 pS
->WriteUChar( 0x01 );
1933 pS
->WriteUChar( 0x03 );
1934 pS
->WriteUChar( 0x00 );
1935 sal_uInt32 nSize
= pS
->Tell();
1936 nPendingAttributes
=0;
1939 pS
->WriteUChar( END
);
1941 nSize
= pS
->Tell()-nSize
;
1943 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1953 void MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1955 switch(pNode
->GetType())
1958 HandleAttributes(pNode
,nLevel
);
1961 HandleText(pNode
,nLevel
);
1963 case NVERTICAL_BRACE
:
1964 HandleVerticalBrace(pNode
,nLevel
);
1967 HandleBrace(pNode
,nLevel
);
1970 HandleOperator(pNode
,nLevel
);
1973 HandleFractions(pNode
,nLevel
);
1976 HandleRoot(pNode
,nLevel
);
1980 SmTextNode
*pText
= static_cast<SmTextNode
*>(pNode
);
1981 //if the token str and the result text are the same then this
1982 //is to be seen as text, else assume it's a mathchar
1983 if (pText
->GetText() == pText
->GetToken().aText
)
1984 HandleText(pText
,nLevel
);
1986 HandleMath(pText
,nLevel
);
1991 HandleMath(pNode
,nLevel
);
1994 HandleSubSupScript(pNode
,nLevel
);
1998 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
1999 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2000 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2001 HandleNodes(pTemp
,nLevel
+1);
2005 //Root Node, PILE equivalent, i.e. vertical stack
2006 HandleTable(pNode
,nLevel
);
2009 HandleSmMatrix(static_cast<SmMatrixNode
*>(pNode
),nLevel
);
2013 pS
->WriteUChar( 0x0a );
2014 pS
->WriteUChar( LINE
);
2015 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2016 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2017 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2018 HandleNodes(pTemp
,nLevel
+1);
2019 pS
->WriteUChar( END
);
2023 HandleMAlign(pNode
,nLevel
);
2026 pS
->WriteUChar( CHAR
);
2027 pS
->WriteUChar( 0x98 );
2028 if (pNode
->GetToken().eType
== TSBLANK
)
2029 pS
->WriteUInt16( 0xEB04 );
2031 pS
->WriteUInt16( 0xEB05 );
2035 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2036 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2037 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2038 HandleNodes(pTemp
,nLevel
+1);
2045 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2047 int nOldPending
=nPendingAttributes
;
2048 pS
->WriteUChar( TMPL
); //Template
2049 pS
->WriteUChar( nSelector
); //selector
2050 pS
->WriteUChar( nVariation
); //variation
2051 pS
->WriteUChar( 0x00 ); //options
2052 pS
->WriteUChar( LINE
);
2053 //theres just no way we can now handle any character
2054 //attributes (from mathtypes perspective) centered
2055 //over an expression but above template attribute
2056 //such as widevec and similar constructs
2057 //we have to drop them
2058 nPendingAttributes
=0;
2062 void MathType::EndTemplate(int nOldPendingAttributes
)
2064 pS
->WriteUChar( END
); //end line
2065 pS
->WriteUChar( END
); //end template
2066 nPendingAttributes
=nOldPendingAttributes
;
2070 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2072 pS
->WriteUChar( MATRIX
);
2073 pS
->WriteUChar( 0x00 ); //vAlign ?
2074 pS
->WriteUChar( 0x00 ); //h_just
2075 pS
->WriteUChar( 0x00 ); //v_just
2076 pS
->WriteUChar( pMatrix
->GetNumRows() ); //v_just
2077 pS
->WriteUChar( pMatrix
->GetNumCols() ); //v_just
2078 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2079 if (((pMatrix
->GetNumRows()+1)*2)%8)
2081 for (sal_uInt16 j
= 0; j
< nBytes
; j
++)
2082 pS
->WriteUChar( 0x00 ); //row_parts
2083 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2084 if (((pMatrix
->GetNumCols()+1)*2)%8)
2086 for (sal_uInt16 k
= 0; k
< nBytes
; k
++)
2087 pS
->WriteUChar( 0x00 ); //col_parts
2088 sal_uInt16 nSize
= pMatrix
->GetNumSubNodes();
2089 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2090 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2092 pS
->WriteUChar( LINE
); //line
2093 HandleNodes(pTemp
,nLevel
+1);
2094 pS
->WriteUChar( END
); //end line
2096 pS
->WriteUChar( END
);
2100 //Root Node, PILE equivalent, i.e. vertical stack
2101 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2103 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2104 //The root of the starmath is a table, if
2105 //we convert this them each iteration of
2106 //conversion from starmath to mathtype will
2107 //add an extra unnecessary level to the
2108 //mathtype output stack which would grow
2109 //without bound in a multi step conversion
2112 pS
->WriteUChar( 0x0A ); //initial size
2114 if ( nLevel
|| (nSize
>1))
2116 pS
->WriteUChar( PILE
);
2117 pS
->WriteUChar( nHAlign
); //vAlign ?
2118 pS
->WriteUChar( 0x01 ); //hAlign
2121 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2122 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2124 pS
->WriteUChar( LINE
);
2125 HandleNodes(pTemp
,nLevel
+1);
2126 pS
->WriteUChar( END
);
2128 if (nLevel
|| (nSize
>1))
2129 pS
->WriteUChar( END
);
2133 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2136 pS
->WriteUChar( TMPL
); //Template
2137 pS
->WriteUChar( 0x0D ); //selector
2138 if (pNode
->GetSubNode(0))
2139 pS
->WriteUChar( 0x01 ); //variation
2141 pS
->WriteUChar( 0x00 ); //variation
2142 pS
->WriteUChar( 0x00 ); //options
2144 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2146 pS
->WriteUChar( LINE
); //line
2147 HandleNodes(pTemp
,nLevel
+1);
2148 pS
->WriteUChar( END
);
2151 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2153 pS
->WriteUChar( LINE
); //line
2154 HandleNodes(pTemp
,nLevel
+1);
2155 pS
->WriteUChar( END
);
2158 pS
->WriteUChar( LINE
|0x10 ); //dummy line
2162 pS
->WriteUChar( END
);
2165 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2166 sal_uLong
*pPos
,bool bTest
)
2168 sal_uInt8 nVariation2
=0xff;
2170 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2173 if (pNode
->GetSubNode(CSUB
+1))
2176 else if (pNode
->GetSubNode(CSUB
+1))
2179 if (nVariation2
!=0xff)
2183 pS
->WriteUChar( TMPL
); //Template
2184 pS
->WriteUChar( 0x2B ); //selector
2185 pS
->WriteUChar( nVariation2
);
2186 pS
->WriteUChar( 0x00 ); //options
2190 pS
->WriteUChar( LINE
); //line
2191 HandleNodes(pContent
,nLevel
+1);
2192 pS
->WriteUChar( END
); //line
2195 pS
->WriteUChar( LINE
|0x10 );
2197 pS
->WriteUChar( 0x0B );
2200 if (NULL
!= (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2202 pS
->WriteUChar( LINE
); //line
2203 HandleNodes(pTemp
,nLevel
+1);
2204 pS
->WriteUChar( END
); //line
2207 pS
->WriteUChar( LINE
|0x10 );
2208 if (bTest
&& NULL
!= (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2210 pS
->WriteUChar( LINE
); //line
2211 HandleNodes(pTemp
,nLevel
+1);
2212 pS
->WriteUChar( END
); //line
2215 pS
->WriteUChar( LINE
|0x10 );
2223 Sub and Sup scripts and another problem area, StarMath
2224 can have all possible options used at the same time, whereas
2225 Mathtype cannot. The ordering of the nodes for each system
2226 is quite different as well leading to some complexity
2228 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2230 sal_uInt8 nVariation
=0xff;
2231 if (pNode
->GetSubNode(LSUP
+1))
2234 if (pNode
->GetSubNode(LSUB
+1))
2237 else if ( NULL
!= pNode
->GetSubNode(LSUB
+1) )
2241 if (nVariation
!=0xff)
2243 pS
->WriteUChar( TMPL
); //Template
2244 pS
->WriteUChar( 0x2c ); //selector
2245 pS
->WriteUChar( nVariation
);
2246 pS
->WriteUChar( 0x00 ); //options
2247 pS
->WriteUChar( 0x0B );
2249 if (NULL
!= (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2251 pS
->WriteUChar( LINE
); //line
2252 HandleNodes(pTemp
,nLevel
+1);
2253 pS
->WriteUChar( END
); //line
2256 pS
->WriteUChar( LINE
|0x10 );
2257 if (NULL
!= (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2259 pS
->WriteUChar( LINE
); //line
2260 HandleNodes(pTemp
,nLevel
+1);
2261 pS
->WriteUChar( END
); //line
2264 pS
->WriteUChar( LINE
|0x10 );
2265 pS
->WriteUChar( END
);
2270 sal_uInt8 nVariation2
=HandleCScript(pNode
,NULL
,nLevel
);
2272 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2274 HandleNodes(pTemp
,nLevel
+1);
2277 if (nVariation2
!= 0xff)
2278 pS
->WriteUChar( END
);
2280 if (NULL
!= (pNode
->GetSubNode(RSUP
+1)))
2283 if (pNode
->GetSubNode(RSUB
+1))
2286 else if (NULL
!= pNode
->GetSubNode(RSUB
+1))
2289 if (nVariation
!=0xff)
2291 pS
->WriteUChar( TMPL
); //Template
2292 pS
->WriteUChar( 0x0F ); //selector
2293 pS
->WriteUChar( nVariation
);
2294 pS
->WriteUChar( 0x00 ); //options
2295 pS
->WriteUChar( 0x0B );
2297 if (NULL
!= (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2299 pS
->WriteUChar( LINE
); //line
2300 HandleNodes(pTemp
,nLevel
+1);
2301 pS
->WriteUChar( END
); //line
2304 pS
->WriteUChar( LINE
|0x10 );
2305 if (NULL
!= (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2307 pS
->WriteUChar( LINE
); //line
2308 HandleNodes(pTemp
,nLevel
+1);
2309 pS
->WriteUChar( END
); //line
2312 pS
->WriteUChar( LINE
|0x10 );
2313 pS
->WriteUChar( END
); //line
2316 //After subscript mathtype will keep the size of
2317 //normal text at the subscript size, sigh.
2318 pS
->WriteUChar( 0x0A );
2322 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2325 pS
->WriteUChar( TMPL
); //Template
2326 pS
->WriteUChar( 0x0E ); //selector
2327 pS
->WriteUChar( 0x00 ); //variation
2328 pS
->WriteUChar( 0x00 ); //options
2330 pS
->WriteUChar( 0x0A );
2331 pS
->WriteUChar( LINE
); //line
2332 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2333 HandleNodes(pTemp
,nLevel
+1);
2334 pS
->WriteUChar( END
);
2336 pS
->WriteUChar( 0x0A );
2337 pS
->WriteUChar( LINE
); //line
2338 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2339 HandleNodes(pTemp
,nLevel
+1);
2340 pS
->WriteUChar( END
);
2342 pS
->WriteUChar( END
);
2346 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2349 SmNode
*pLeft
=pNode
->GetSubNode(0);
2350 SmNode
*pRight
=pNode
->GetSubNode(2);
2352 pS
->WriteUChar( TMPL
); //Template
2353 bIsReInterpBrace
=false;
2354 sal_uInt8 nBSpec
=0x10;
2355 sal_uLong nLoc
= pS
->Tell();
2358 switch (pLeft
->GetToken().eType
)
2361 pS
->WriteUChar( tmANGLE
); //selector
2362 pS
->WriteUChar( 0 ); //variation
2363 pS
->WriteUChar( 0 ); //options
2366 pS
->WriteUChar( tmBRACE
); //selector
2367 pS
->WriteUChar( 0 ); //variation
2368 pS
->WriteUChar( 0 ); //options
2372 pS
->WriteUChar( tmBRACK
); //selector
2373 pS
->WriteUChar( 0 ); //variation
2374 pS
->WriteUChar( 0 ); //options
2378 pS
->WriteUChar( tmFLOOR
); //selector
2379 pS
->WriteUChar( 0 ); //variation
2380 pS
->WriteUChar( 0 ); //options
2383 pS
->WriteUChar( tmBAR
); //selector
2384 pS
->WriteUChar( 0 ); //variation
2385 pS
->WriteUChar( 0 ); //options
2389 pS
->WriteUChar( tmDBAR
); //selector
2390 pS
->WriteUChar( 0 ); //variation
2391 pS
->WriteUChar( 0 ); //options
2394 pS
->WriteUChar( tmPAREN
); //selector
2395 pS
->WriteUChar( 0 ); //variation
2396 pS
->WriteUChar( 0 ); //options
2402 if (NULL
!= (pTemp
= pNode
->GetSubNode(1)))
2404 pS
->WriteUChar( LINE
); //line
2405 HandleNodes(pTemp
,nLevel
+1);
2406 pS
->WriteUChar( END
); //options
2410 HandleNodes(pLeft
,nLevel
+1);
2411 if (bIsReInterpBrace
)
2413 sal_uLong nLoc2
= pS
->Tell();
2415 pS
->WriteUChar( 0x2D );
2417 pS
->WriteUChar( CHAR
);
2418 pS
->WriteUChar( 0x96 );
2419 pS
->WriteUInt16( 0xEC07 );
2420 bIsReInterpBrace
=false;
2423 HandleNodes(pRight
,nLevel
+1);
2425 pS
->WriteUChar( END
);
2429 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2432 pS
->WriteUChar( TMPL
); //Template
2433 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2434 pS
->WriteUChar( tmLHBRACE
); //selector
2436 pS
->WriteUChar( tmUHBRACE
); //selector
2437 pS
->WriteUChar( 0 ); //variation
2438 pS
->WriteUChar( 0 ); //options
2440 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2442 pS
->WriteUChar( LINE
); //line
2443 HandleNodes(pTemp
,nLevel
+1);
2444 pS
->WriteUChar( END
); //options
2447 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2449 pS
->WriteUChar( LINE
); //line
2450 HandleNodes(pTemp
,nLevel
+1);
2451 pS
->WriteUChar( END
); //options
2453 pS
->WriteUChar( END
);
2456 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2458 if (HandleLim(pNode
,nLevel
))
2462 sal_uInt8 nVariation
;
2464 switch (pNode
->GetToken().eType
)
2471 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2472 pNode
->GetSubNode(1),nLevel
,&nPos
,false);
2475 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2476 pNode
->GetSubNode(1),nLevel
,&nPos
);
2480 sal_uInt8 nOldVariation
=nVariation
;
2481 sal_uInt8 nIntVariation
=nVariation
;
2484 if (nVariation
!= 0xff)
2488 if (nVariation
== 2)
2493 else if (nVariation
== 0)
2495 else if (nVariation
== 1)
2503 pS
->WriteUChar( TMPL
);
2504 switch(pNode
->GetToken().eType
)
2508 if (nOldVariation
!= 0xff)
2509 pS
->WriteUChar( 0x18 ); //selector
2511 pS
->WriteUChar( 0x15 ); //selector
2512 pS
->WriteUChar( nIntVariation
); //variation
2515 if (nOldVariation
!= 0xff)
2517 pS
->WriteUChar( 0x19 );
2518 pS
->WriteUChar( 0x01 );
2522 pS
->WriteUChar( 0x16 );
2523 pS
->WriteUChar( 0x00 );
2527 if (nOldVariation
!= 0xff)
2529 pS
->WriteUChar( 0x1a );
2530 pS
->WriteUChar( 0x01 );
2534 pS
->WriteUChar( 0x17 );
2535 pS
->WriteUChar( 0x00 );
2539 if (nOldVariation
!= 0xff)
2541 pS
->WriteUChar( 0x18 );
2542 pS
->WriteUChar( 0x02 );
2546 pS
->WriteUChar( 0x15 );
2547 pS
->WriteUChar( 0x03 );
2551 if (nOldVariation
!= 0xff)
2553 pS
->WriteUChar( 0x19 );
2554 pS
->WriteUChar( 0x00 );
2558 pS
->WriteUChar( 0x16 );
2559 pS
->WriteUChar( 0x02 );
2563 if (nOldVariation
!= 0xff)
2565 pS
->WriteUChar( 0x1a );
2566 pS
->WriteUChar( 0x00 );
2570 pS
->WriteUChar( 0x17 );
2571 pS
->WriteUChar( 0x02 );
2576 pS
->WriteUChar( 0x1d );
2577 pS
->WriteUChar( nVariation
);
2580 pS
->WriteUChar( 0x1f );
2581 pS
->WriteUChar( nVariation
);
2584 pS
->WriteUChar( 0x21 );
2585 pS
->WriteUChar( nVariation
);
2588 pS
->WriteUChar( 0 ); //options
2594 pS
->WriteUChar( LINE
); //line
2595 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2596 pS
->WriteUChar( END
); //line
2597 pS
->WriteUChar( LINE
|0x10 );
2598 pS
->WriteUChar( LINE
|0x10 );
2602 pS
->WriteUChar( 0x0D );
2603 switch(pNode
->GetToken().eType
)
2607 pS
->WriteUChar( CHAR
);
2608 pS
->WriteUChar( 0x86 );
2609 pS
->WriteUInt16( 0x2211 );
2612 pS
->WriteUChar( CHAR
);
2613 pS
->WriteUChar( 0x86 );
2614 pS
->WriteUInt16( 0x220F );
2617 pS
->WriteUChar( CHAR
);
2618 pS
->WriteUChar( 0x8B );
2619 pS
->WriteUInt16( 0x2210 );
2623 pS
->WriteUChar( CHAR
);
2624 pS
->WriteUChar( 0x86 );
2625 pS
->WriteUInt16( 0x222B );
2629 pS
->WriteUChar( CHAR
);
2630 pS
->WriteUChar( 0x86 );
2631 pS
->WriteUInt16( 0x222B );
2636 pS
->WriteUChar( CHAR
);
2637 pS
->WriteUChar( 0x86 );
2638 pS
->WriteUInt16( 0x222B );
2641 pS
->WriteUChar( END
);
2642 pS
->WriteUChar( 0x0A );
2646 int MathType::HandlePile(int &rSetAlign
,int nLevel
,sal_uInt8 nSelector
,
2647 sal_uInt8 nVariation
)
2649 pS
->ReadUChar( nHAlign
);
2650 pS
->ReadUChar( nVAlign
);
2652 HandleAlign(nHAlign
,nVAlign
,rSetAlign
);
2654 rRet
+= " stack {\n";
2655 int nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
,-1,-1);
2656 rRet
= rRet
.replaceAt(rRet
.getLength()-3,2,"");
2667 int MathType::HandleMatrix(int nLevel
,sal_uInt8 nSelector
,
2668 sal_uInt8 nVariation
)
2670 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
;
2671 pS
->ReadUChar( nVAlign
);
2672 pS
->ReadUChar( nH_just
);
2673 pS
->ReadUChar( nV_just
);
2674 pS
->ReadUChar( nRows
);
2675 pS
->ReadUChar( nCols
);
2676 int nBytes
= ((nRows
+1)*2)/8;
2677 if (((nRows
+1)*2)%8)
2679 pS
->SeekRel(nBytes
);
2680 nBytes
= ((nCols
+1)*2)/8;
2681 if (((nCols
+1)*2)%8)
2683 pS
->SeekRel(nBytes
);
2684 rRet
+= " matrix {\n";
2685 int nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
,nRows
,nCols
);
2687 sal_Int32 nI
= rRet
.lastIndexOf('#');
2689 if (rRet
[nI
-1] != '#') //missing column
2696 int MathType::HandleTemplate(int nLevel
,sal_uInt8
&rSelector
,
2697 sal_uInt8
&rVariation
, sal_Int32
&rLastTemplateBracket
)
2699 sal_uInt8 nOption
; //This appears utterly unused
2700 pS
->ReadUChar( rSelector
);
2701 pS
->ReadUChar( rVariation
);
2702 pS
->ReadUChar( nOption
);
2703 OSL_ENSURE(rSelector
< 48,"Selector out of range");
2704 if ((rSelector
>= 21) && (rSelector
<=26))
2706 OSL_ENSURE(nOption
< 2,"Option out of range");
2708 else if (/*(rSelector >= 0) &&*/ (rSelector
<=12))
2710 OSL_ENSURE(nOption
< 3,"Option out of range");
2713 //For the (broken) case where one subscript template ends, and there is
2714 //another one after it, mathtype handles it as if the second one was
2715 //inside the first one and renders it as sub of sub
2717 if ( (rSelector
== 0xf) && (rLastTemplateBracket
!= -1) )
2720 for (sal_Int32 nI
= rLastTemplateBracket
+1; nI
< rRet
.getLength(); nI
++ )
2721 if (rRet
[nI
] != ' ')
2729 int nRet
= HandleRecords(nLevel
+1,rSelector
,rVariation
);
2733 rRet
= rRet
.replaceAt(rLastTemplateBracket
,1,"");
2735 rLastTemplateBracket
= -1;
2737 if (rSelector
== 0xf)
2738 rLastTemplateBracket
= rRet
.lastIndexOf('}');
2740 rLastTemplateBracket
= -1;
2742 rSelector
= sal::static_int_cast
< sal_uInt8
>(-1);
2746 void MathType::HandleEmblishments()
2751 pS
->ReadUChar( nEmbel
);
2767 nPostSup
= sPost
.getLength();
2769 sPost
= sPost
.replaceAt(nPostSup
-1,0," ' ");
2776 nPostSup
= sPost
.getLength();
2778 sPost
= sPost
.replaceAt(nPostSup
-1,0," '' ");
2784 sPost
+= " lsup {}";
2785 nPostlSup
= sPost
.getLength();
2787 sPost
= sPost
.replaceAt(nPostlSup
-1,0," ' ");
2800 rRet
+= " overstrike ";
2809 nPostSup
= sPost
.getLength();
2811 sPost
= sPost
.replaceAt(nPostSup
-1,0," ''' ");
2818 OSL_ENSURE(nEmbel
< 21,"Embel out of range");
2826 void MathType::HandleSetSize()
2829 pS
->ReadUChar( nTemp
);
2833 pS
->ReadInt16( nLSize
);
2837 pS
->ReadUChar( nTemp
);
2839 pS
->ReadInt16( nDSize
);
2843 pS
->ReadUChar( nTemp
);
2849 int MathType::HandleChar(sal_Int32
&rTextStart
,int &rSetSize
,int nLevel
,
2850 sal_uInt8 nTag
,sal_uInt8 nSelector
,sal_uInt8 nVariation
, bool bSilent
)
2857 //This is a candidate for function recognition, whatever
2861 sal_uInt8 nOldTypeFace
= nTypeFace
;
2862 pS
->ReadUChar( nTypeFace
);
2866 pS
->ReadUChar( nChar8
);
2870 pS
->ReadUInt16( nChar
);
2873 bad character, old mathtype < 3 has these
2880 //A bit tricky, the character emblishments for
2881 //mathtype can all be listed after eachother, in
2882 //starmath some must go before the character and some
2883 //must go after. In addition some of the emblishments
2884 //may repeated and in starmath some of these groups
2885 //must be gathered together. sPost is the portion that
2886 //follows the char and nPostSup and nPostlSup are the
2887 //indexes at which this class of emblishment is
2890 nPostSup
= nPostlSup
= 0;
2891 int nOriglen
=rRet
.getLength()-rTextStart
;
2892 rRet
+= " {"; // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2893 if ((!bSilent
) && ((nOriglen
) > 1))
2895 nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
);
2901 TypeFaceToString(aStr
,nOldTypeFace
);
2903 rRet
= rRet
.replaceAt(rTextStart
,0,aStr
);
2906 TypeFaceToString(aStr
,nTypeFace
);
2911 rTextStart
= rRet
.getLength();
2917 sal_Int32 nOldLen
= rRet
.getLength();
2919 HandleSize(nLSize
,nDSize
,rSetSize
) ||
2920 (nOldTypeFace
!= nTypeFace
)
2923 if ((nOldLen
- rTextStart
) > 1)
2925 rRet
= rRet
.replaceAt(nOldLen
, 0, "\"");
2927 TypeFaceToString(aStr
,nOldTypeFace
);
2929 rRet
= rRet
.replaceAt(rTextStart
,0,aStr
);
2931 rTextStart
= rRet
.getLength();
2933 nOldLen
= rRet
.getLength();
2934 if (!LookupChar(nChar
,rRet
,nVersion
,nTypeFace
))
2936 if (nOldLen
- rTextStart
> 1)
2938 rRet
= rRet
.replaceAt(nOldLen
,0,"\"");
2940 TypeFaceToString(aStr
,nOldTypeFace
);
2942 rRet
= rRet
.replaceAt(rTextStart
, 0, aStr
);
2944 rTextStart
= rRet
.getLength();
2946 lcl_PrependDummyTerm(rRet
, rTextStart
);
2949 if ((xfEMBELL(nTag
)) && (!bSilent
))
2951 rRet
+= "}}" + sPost
; // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2952 rTextStart
= rRet
.getLength();
2957 bool MathType::HandleLim(SmNode
*pNode
,int nLevel
)
2960 //Special case for the "lim" option in StarMath
2961 if ((pNode
->GetToken().eType
== TLIM
)
2962 || (pNode
->GetToken().eType
== TLIMSUP
)
2963 || (pNode
->GetToken().eType
== TLIMINF
)
2966 if (pNode
->GetSubNode(1))
2968 sal_uInt8 nVariation2
=HandleCScript(pNode
->GetSubNode(0),NULL
,
2971 pS
->WriteUChar( 0x0A );
2972 pS
->WriteUChar( LINE
); //line
2973 pS
->WriteUChar( CHAR
|0x10 );
2974 pS
->WriteUChar( 0x82 );
2975 pS
->WriteUInt16( 'l' );
2976 pS
->WriteUChar( CHAR
|0x10 );
2977 pS
->WriteUChar( 0x82 );
2978 pS
->WriteUInt16( 'i' );
2979 pS
->WriteUChar( CHAR
|0x10 );
2980 pS
->WriteUChar( 0x82 );
2981 pS
->WriteUInt16( 'm' );
2983 if (pNode
->GetToken().eType
== TLIMSUP
)
2985 pS
->WriteUChar( CHAR
); //some space
2986 pS
->WriteUChar( 0x98 );
2987 pS
->WriteUInt16( 0xEB04 );
2989 pS
->WriteUChar( CHAR
|0x10 );
2990 pS
->WriteUChar( 0x82 );
2991 pS
->WriteUInt16( 's' );
2992 pS
->WriteUChar( CHAR
|0x10 );
2993 pS
->WriteUChar( 0x82 );
2994 pS
->WriteUInt16( 'u' );
2995 pS
->WriteUChar( CHAR
|0x10 );
2996 pS
->WriteUChar( 0x82 );
2997 pS
->WriteUInt16( 'p' );
2999 else if (pNode
->GetToken().eType
== TLIMINF
)
3001 pS
->WriteUChar( CHAR
); //some space
3002 pS
->WriteUChar( 0x98 );
3003 pS
->WriteUInt16( 0xEB04 );
3005 pS
->WriteUChar( CHAR
|0x10 );
3006 pS
->WriteUChar( 0x82 );
3007 pS
->WriteUInt16( 'i' );
3008 pS
->WriteUChar( CHAR
|0x10 );
3009 pS
->WriteUChar( 0x82 );
3010 pS
->WriteUInt16( 'n' );
3011 pS
->WriteUChar( CHAR
|0x10 );
3012 pS
->WriteUChar( 0x82 );
3013 pS
->WriteUInt16( 'f' );
3017 pS
->WriteUChar( CHAR
); //some space
3018 pS
->WriteUChar( 0x98 );
3019 pS
->WriteUInt16( 0xEB04 );
3021 if (nVariation2
!= 0xff)
3023 pS
->WriteUChar( END
);
3024 pS
->WriteUChar( END
);
3026 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
3033 void MathType::HandleMAlign(SmNode
*pNode
,int nLevel
)
3035 sal_uInt8 nPushedHAlign
=nHAlign
;
3036 switch(pNode
->GetToken().eType
)
3048 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
3049 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
3050 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
3051 HandleNodes(pTemp
,nLevel
+1);
3052 nHAlign
=nPushedHAlign
;
3055 void MathType::HandleMath(SmNode
*pNode
, int /*nLevel*/)
3057 if (pNode
->GetToken().eType
== TMLINE
)
3059 pS
->WriteUChar( END
);
3060 pS
->WriteUChar( LINE
);
3061 bIsReInterpBrace
=true;
3064 SmMathSymbolNode
*pTemp
= static_cast<SmMathSymbolNode
*>(pNode
);
3065 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3067 sal_Unicode nArse
= SmTextNode::ConvertSymbolToUnicode(pTemp
->GetText()[i
]);
3068 if ((nArse
== 0x2224) || (nArse
== 0x2288) || (nArse
== 0x2285) ||
3071 pS
->WriteUChar( CHAR
|0x20 );
3073 else if ((nPendingAttributes
) &&
3074 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3076 pS
->WriteUChar( 0x22 );
3079 pS
->WriteUChar( CHAR
); //char without formula recognition
3080 //The typeface seems to be MTEXTRA for unicode characters,
3081 //though how to determine when mathtype chooses one over
3082 //the other is unknown. This should do the trick
3085 if ( (nArse
== 0x2213) || (nArse
== 0x2218) ||
3086 (nArse
== 0x210F) || (
3087 (nArse
>= 0x22EE) && (nArse
<= 0x22FF)
3090 nBias
= 0xB; //typeface
3092 else if ((nArse
> 0x2000) || (nArse
== 0x00D7))
3093 nBias
= 0x6; //typeface
3094 else if (nArse
== 0x3d1)
3096 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3097 nBias
= 0xB; //typeface
3098 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3099 nBias
= 0x2; //typeface
3101 nBias
= 0x3; //typeface
3103 pS
->WriteUChar( nSpec
+nBias
+128 ); //typeface
3105 if (nArse
== 0x2224)
3107 pS
->WriteUInt16( 0x7C );
3108 pS
->WriteUChar( EMBEL
);
3109 pS
->WriteUChar( 0x0A );
3110 pS
->WriteUChar( END
); //end embel
3111 pS
->WriteUChar( END
); //end embel
3113 else if (nArse
== 0x2225)
3114 pS
->WriteUInt16( 0xEC09 );
3115 else if (nArse
== 0xE421)
3116 pS
->WriteUInt16( 0x2265 );
3117 else if (nArse
== 0x230A)
3118 pS
->WriteUInt16( 0xF8F0 );
3119 else if (nArse
== 0x230B)
3120 pS
->WriteUInt16( 0xF8FB );
3121 else if (nArse
== 0xE425)
3122 pS
->WriteUInt16( 0x2264 );
3123 else if (nArse
== 0x226A)
3125 pS
->WriteUInt16( 0x3C );
3126 pS
->WriteUChar( CHAR
);
3127 pS
->WriteUChar( 0x98 );
3128 pS
->WriteUInt16( 0xEB01 );
3129 pS
->WriteUChar( CHAR
);
3130 pS
->WriteUChar( 0x86 );
3131 pS
->WriteUInt16( 0x3c );
3133 else if (nArse
== 0x2288)
3135 pS
->WriteUInt16( 0x2286 );
3136 pS
->WriteUChar( EMBEL
);
3137 pS
->WriteUChar( 0x0A );
3138 pS
->WriteUChar( END
); //end embel
3139 pS
->WriteUChar( END
); //end embel
3141 else if (nArse
== 0x2289)
3143 pS
->WriteUInt16( 0x2287 );
3144 pS
->WriteUChar( EMBEL
);
3145 pS
->WriteUChar( 0x0A );
3146 pS
->WriteUChar( END
); //end embel
3147 pS
->WriteUChar( END
); //end embel
3149 else if (nArse
== 0x2285)
3151 pS
->WriteUInt16( 0x2283 );
3152 pS
->WriteUChar( EMBEL
);
3153 pS
->WriteUChar( 0x0A );
3154 pS
->WriteUChar( END
); //end embel
3155 pS
->WriteUChar( END
); //end embel
3158 pS
->WriteUInt16( nArse
);
3160 nPendingAttributes
= 0;
3163 void MathType::HandleAttributes(SmNode
*pNode
,int nLevel
)
3165 int nOldPending
= 0;
3167 SmTextNode
*pIsText
= 0;
3169 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
3171 pIsText
= static_cast<SmTextNode
*>(pNode
->GetSubNode(1));
3173 switch (pTemp
->GetToken().eType
)
3176 //theres just no way we can now handle any character
3177 //attributes (from mathtypes perspective) centered
3178 //over an expression but above template attributes
3179 //such as widevec and similar constructs
3180 //we have to drop them
3181 nOldPending
= StartTemplate(0x2f,0x01);
3183 case TCHECK
: //Not Exportable
3184 case TACUTE
: //Not Exportable
3185 case TGRAVE
: //Not Exportable
3186 case TCIRCLE
: //Not Exportable
3187 case TWIDETILDE
: //Not Exportable
3188 case TWIDEHAT
: //Not Exportable
3191 nOldPending
= StartTemplate(0x10);
3193 case TOVERLINE
: //If the next node is not text
3194 //or text with more than one char
3195 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3196 (pIsText
->GetText().getLength() > 1))
3197 nOldPending
= StartTemplate(0x11);
3200 nPendingAttributes
++;
3206 HandleNodes(pIsText
,nLevel
+1);
3208 switch (pTemp
->GetToken().eType
)
3212 EndTemplate(nOldPending
);
3215 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3216 (pIsText
->GetText().getLength() > 1))
3217 EndTemplate(nOldPending
);
3223 //if there was no suitable place to put the attribute,
3224 //then we have to just give up on it
3225 if (nPendingAttributes
)
3226 nPendingAttributes
--;
3229 if ((nInsertion
!= 0) && NULL
!= (pTemp
= pNode
->GetSubNode(0)))
3231 sal_uLong nPos
= pS
->Tell();
3233 pS
->Seek(nInsertion
);
3234 switch(pTemp
->GetToken().eType
)
3236 case TACUTE
: //Not Exportable
3237 case TGRAVE
: //Not Exportable
3238 case TCIRCLE
: //Not Exportable
3241 pS
->WriteUChar( 2 );
3244 pS
->WriteUChar( 3 );
3247 pS
->WriteUChar( 4 );
3250 pS
->WriteUChar( 8 );
3253 pS
->WriteUChar( 9 );
3256 pS
->WriteUChar( 11 );
3259 pS
->WriteUChar( 16 );
3262 if ((pIsText
->GetToken().eType
== TTEXT
) &&
3263 (pIsText
->GetText().getLength() == 1))
3264 pS
->WriteUChar( 17 );
3267 pS
->WriteUChar( 20 );
3275 pS
->WriteUChar( 17 );
3278 pS
->WriteUChar( 2 );
3286 void MathType::HandleText(SmNode
*pNode
, int /*nLevel*/)
3288 SmTextNode
*pTemp
= static_cast<SmTextNode
*>(pNode
);
3289 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3291 if ((nPendingAttributes
) &&
3292 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3294 pS
->WriteUChar( 0x22 ); //char, with attributes right
3295 //after the character
3298 pS
->WriteUChar( CHAR
);
3300 sal_uInt8 nFace
= 0x1;
3301 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3303 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3305 pS
->WriteUChar( nFace
+128 ); //typeface
3306 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3307 pS
->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar
) );
3309 //Mathtype can only have these sort of character
3310 //attributes on a single character, starmath can put them
3311 //anywhere, when the entity involved is a text run this is
3312 //a large effort to place the character attribute on the
3313 //central mathtype character so that it does pretty much
3314 //what the user probably has in mind. The attributes
3315 //filled in here are dummy ones which are replaced in the
3316 //ATTRIBUT handler if a suitable location for the
3317 //attributes was found here. Unfortunately it is
3318 //possible for starmath to place character attributes on
3319 //entities which cannot occur in mathtype e.g. a Summation
3320 //symbol so these attributes may be lost
3321 if ((nPendingAttributes
) &&
3322 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3324 pS
->WriteUChar( EMBEL
);
3325 while (nPendingAttributes
)
3327 pS
->WriteUChar( 2 );
3328 //wedge the attributes in here and clear
3330 nPendingAttributes
--;
3332 nInsertion
=pS
->Tell();
3333 pS
->WriteUChar( END
); //end embel
3334 pS
->WriteUChar( END
); //end embel
3339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */