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
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 sal_Bool
MathType::LookupChar(sal_Unicode nChar
,String
&rRet
,sal_uInt8 nVersion
,
80 const char *pC
= NULL
;
108 if ((nVersion
< 3) && (nTypeFace
== 0x86))
117 if ((nVersion
< 3) && (nTypeFace
== 0x81))
123 if ((nVersion
< 3) && (nTypeFace
== 0x84))
129 if ((nVersion
< 3) && (nTypeFace
== 0x84))
135 if ((nVersion
< 3) && (nTypeFace
== 0x84))
141 if ((nVersion
< 3) && (nTypeFace
== 0x84))
147 if ((nVersion
< 3) && (nTypeFace
== 0x84))
153 if ((nVersion
< 3) && (nTypeFace
== 0x84))
159 if ((nVersion
< 3) && (nTypeFace
== 0x82))
165 if ((nVersion
< 3) && (nTypeFace
== 0x86))
174 if ((nVersion
< 3) && (nTypeFace
== 0x86))
183 if ((nVersion
< 3) && (nTypeFace
== 0x86))
192 if ((nVersion
< 3) && (nTypeFace
== 0x85))
351 pC
= " intersection ";
400 pC
= " preccurlyeq ";
403 pC
= " succcurlyeq ";
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
520 rRet
.AppendAscii(pC
);
524 void MathTypeFont::AppendStyleToText(String
&rRet
)
526 const char *pC
= NULL
;
543 rRet
.AppendAscii(pC
);
546 void MathType::TypeFaceToString(String
&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 SvStorageStreamRef xSrc
= pStor
->OpenSotStream(
558 OUString("Equation Native"),
559 STREAM_STD_READ
| STREAM_NOCREATE
);
560 if ( (!xSrc
.Is()) || (SVSTREAM_OK
!= xSrc
->GetError()))
563 pS
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
571 *pS
>> nProdSubVersion
;
573 if (nVersion
> 3) // allow only supported versions of MathType to be parsed
577 *pOut
<< "Format Version is " << int(nVersion
) << endl
;
578 *pOut
<< "Generating Platform is " << (nPlatform
? "Windows"
580 *pOut
<< "Generating Product is " << (nPlatform
? "Equation Editor"
581 : "Equation Editor") << endl
;
582 *pOut
<< "Prod Version is " << int(nProdVersion
) << "." <<
583 int(nProdSubVersion
) << endl
<< endl
;
586 int nRet
= HandleRecords();
587 //little crude hack to close ocassionally open expressions
588 //a sophisticated system to determine what expressions are
589 //opened is required, but this is as much work as rewriting
590 //starmaths internals.
593 #if OSL_DEBUG_LEVEL > 1
597 //sigh, theres no point! MathType (in some bizarre subvarient) pads
598 //the end of the formula with ENDs (0)'s
599 sal_uLong nEnd
= pS
->Tell();
600 OSL_ENSURE(nEnd
== pS
->Seek(STREAM_SEEK_TO_END
),
601 "Possibly unfully parsed formula");
607 static void lcl_PrependDummyTerm(String
&rRet
, xub_StrLen
&rTextStart
)
609 if ((rRet
.GetChar(rTextStart
) == '=') &&
610 ((rTextStart
== 0) ||
611 (rRet
.GetChar(rTextStart
-1) == '{'))
614 rRet
.InsertAscii(" {}",rTextStart
);
619 static void lcl_AppendDummyTerm(String
&rRet
)
622 for(int nI
=rRet
.Len()-1;nI
>= 0; nI
--)
624 xub_StrLen nIdx
= sal::static_int_cast
< xub_StrLen
>(nI
);
625 sal_Unicode nChar
= rRet
.GetChar(nIdx
);
628 if (rRet
.GetChar(nIdx
) != '{')
632 if (!bOk
) //No term, use dummy
636 void MathType::HandleNudge()
642 if (nXNudge
== 128 && nYNudge
== 128)
644 sal_uInt16 nXLongNudge
;
645 sal_uInt16 nYLongNudge
;
650 /*Fabously complicated as many tokens have to be reordered and generally
651 *moved around from mathtypes paradigm to starmaths.*/
652 int MathType::HandleRecords(int nLevel
,sal_uInt8 nSelector
,
653 sal_uInt8 nVariation
, int nMatrixRows
,int nMatrixCols
)
655 sal_uInt8 nTag
,nRecord
;
656 sal_uInt8 nTabType
,nTabStops
;
657 sal_uInt16 nTabOffset
;
658 int i
,nRet
=1,newline
=0;
661 OUString sPush
,sMainTerm
;
662 int nSetSize
=0,nSetAlign
=0;
663 int nCurRow
=0,nCurCol
=0;
664 bool bOpenString
=false;
665 xub_StrLen nTextStart
= 0;
666 xub_StrLen nSubSupStartPos
= 0;
667 xub_StrLen nLastTemplateBracket
=STRING_NOTFOUND
;
674 /*MathType strings can of course include words which
675 *are StarMath keywords, the simplest solution is
676 to escape strings of greater than len 1 with double
677 quotes to avoid scanning the TokenTable for matches
679 Unfortunately it may turn out that the string gets
680 split during the handling of a character emblishment
681 so this special case must be handled in the
682 character handler case 2:
684 if ((nRecord
== CHAR
) && (!bIsSilent
) && (!bOpenString
))
687 nTextStart
= rRet
.Len();
689 else if ((nRecord
!= CHAR
) && (bOpenString
))
692 if ((rRet
.Len() - nTextStart
) > 1)
695 TypeFaceToString(aStr
,nTypeFace
);
697 rRet
.Insert(aStr
,nTextStart
);
700 else if (nRecord
== END
&& rRet
.Len() > 0)
702 sal_Unicode cChar
= 0;
703 xub_StrLen nI
= rRet
.Len()-1;
704 while (nI
&& ((cChar
= rRet
.GetChar(nI
)) == ' '))
706 if ((cChar
== '=') || (cChar
== '+') || (cChar
== '-'))
719 rRet
+= "\nnewline\n";
727 else if (nVariation
==1)
728 rRet
+= " \\langle ";
733 else if (nVariation
==1)
737 if ((nVariation
==0) || (nVariation
==1))
738 rRet
+= " left lbrace ";
740 rRet
+= " left none ";
745 else if (nVariation
==1)
755 else if (nVariation
==1)
761 else if (nVariation
==1)
762 rRet
+= " \\ldline ";
765 if (nVariation
== 0 || nVariation
== 1)
766 rRet
+= " left lfloor ";
767 else if (nVariation
==1)
768 rRet
+= " left none ";
773 else if (nVariation
==1)
807 nSubSupStartPos
= rRet
.Len();
808 if ((nVariation
== 0) ||
809 ((nVariation
== 2) && (nPart
==1)))
811 lcl_AppendDummyTerm(rRet
);
814 else if ((nVariation
== 1) ||
815 ((nVariation
== 2) && (nPart
==0)))
817 lcl_AppendDummyTerm(rRet
);
824 rRet
+= " {underline ";
825 else if (nVariation
== 1)
826 rRet
+= " {underline underline ";
831 rRet
+= " {overline ";
832 else if (nVariation
== 1)
833 rRet
+= " {overline overline ";
840 rRet
+= " widevec ";//left arrow above
841 else if (nVariation
== 1)
842 rRet
+= " widevec ";//left arrow below
850 rRet
+= " widevec ";//right arrow above
851 else if (nVariation
== 1)
852 rRet
+= " widevec ";//right arrow below
860 rRet
+= " widevec ";//double arrow above
861 else if (nVariation
== 1)
862 rRet
+= " widevec ";//double arrow below
869 if ((nVariation
== 3) || (nVariation
== 4))
873 if ( (nVariation
!= 0) && (nVariation
!= 3))
879 if (((nVariation
== 1) ||
880 (nVariation
== 4)) && (nPart
==1))
882 else if ((nVariation
== 2) && (nPart
==2))
884 else if ((nVariation
== 2) && (nPart
==1))
891 if ((nVariation
== 2) || (nVariation
== 3))
895 if ( (nVariation
!= 0) && (nVariation
!= 2))
901 if (((nVariation
== 1) ||
902 (nVariation
== 3)) && (nPart
==1))
909 if ((nVariation
== 2) || (nVariation
== 3))
913 if ( (nVariation
!= 0) && (nVariation
!= 2))
919 if (((nVariation
== 1) ||
920 (nVariation
== 3)) && (nPart
==1))
934 if (((nVariation
== 1) ||
935 (nVariation
== 2)) && (nPart
==1))
937 else if ((nVariation
== 0) && (nPart
==2))
939 else if ((nVariation
== 0) && (nPart
==1))
985 if ((nVariation
== 0) && (nPart
==1))
987 else if ((nVariation
== 1) && (nPart
==2))
989 else if ((nVariation
== 1) && (nPart
==1))
1000 if ((nVariation
== 0) && (nPart
==1))
1002 else if ((nVariation
== 1) && (nPart
==2))
1004 else if ((nVariation
== 1) && (nPart
==1))
1012 if (nVariation
!= 2)
1018 if ((nVariation
== 0) && (nPart
==1))
1020 else if ((nVariation
== 1) && (nPart
==2))
1022 else if ((nVariation
== 1) && (nPart
==1))
1033 if ((nVariation
== 0) && (nPart
==1))
1035 else if ((nVariation
== 1) && (nPart
==2))
1037 else if ((nVariation
== 1) && (nPart
==1))
1045 if (nVariation
!= 2)
1051 if ((nVariation
== 0) && (nPart
==1))
1053 else if ((nVariation
== 1) && (nPart
==2))
1055 else if ((nVariation
== 1) && (nPart
==1))
1066 if ((nVariation
== 0) && (nPart
==1))
1068 else if ((nVariation
== 1) && (nPart
==2))
1070 else if ((nVariation
== 1) && (nPart
==1))
1077 rRet
+= " union"; //union
1078 if (nVariation
!= 2)
1084 if ((nVariation
== 0) && (nPart
==1))
1086 else if ((nVariation
== 1) && (nPart
==2))
1088 else if ((nVariation
== 1) && (nPart
==1))
1095 rRet
+= " union"; //union
1099 if ((nVariation
== 0) && (nPart
==1))
1101 else if ((nVariation
== 1) && (nPart
==2))
1103 else if ((nVariation
== 1) && (nPart
==1))
1110 rRet
+= " intersect"; //intersect
1111 if (nVariation
!= 2)
1117 if ((nVariation
== 0) && (nPart
==1))
1119 else if ((nVariation
== 1) && (nPart
==2))
1121 else if ((nVariation
== 1) && (nPart
==1))
1128 rRet
+= " intersect"; //intersect
1132 if ((nVariation
== 0) && (nPart
==1))
1134 else if ((nVariation
== 1) && (nPart
==2))
1136 else if ((nVariation
== 1) && (nPart
==1))
1141 if ((nVariation
== 0) && (nPart
==1))
1143 else if ((nVariation
== 1) && (nPart
==1))
1145 else if ((nVariation
== 2) && (nPart
==1))
1147 else if ((nVariation
== 2) && (nPart
==2))
1152 if (nVariation
== 0)
1161 if (nVariation
== 0)
1168 if (nVariation
== 1)
1169 rRet
+= "overline ";
1180 if ((nVariation
== 0) && (nPart
==0))
1182 else if ((nVariation
== 2) && (nPart
==1))
1184 else if ((nVariation
== 1) && (nPart
==0))
1186 else if ((nVariation
== 2) && (nPart
==0))
1196 if ((nVariation
== 0) && (nPart
==0))
1198 else if ((nVariation
== 2) && (nPart
==1))
1200 else if ((nVariation
== 1) && (nPart
==0))
1202 else if ((nVariation
== 2) && (nPart
==0))
1209 if ((nVariation
== 0)
1210 || ((nVariation
== 2) && (nPart
==1)))
1212 else if ((nVariation
== 1)
1213 || ((nVariation
== 2) && (nPart
==0)))
1223 else if (nVariation
==1)
1225 rRet
+= " \\langle ";
1228 else if (nVariation
==2)
1230 rRet
+= " \\lline ";
1235 if (nVariation
== 0)
1236 rRet
+= " widevec ";//left below
1237 else if (nVariation
== 1)
1238 rRet
+= " widevec ";//right below
1239 else if (nVariation
== 2)
1240 rRet
+= " widevec ";//double headed below
1244 if (nVariation
== 0)
1245 rRet
+= " widevec ";//left above
1246 else if (nVariation
== 1)
1247 rRet
+= " widevec ";//right above
1248 else if (nVariation
== 2)
1249 rRet
+= " widevec ";//double headed above
1255 sal_Int16 nOldCurSize
=nCurSize
;
1256 xub_StrLen nSizeStartPos
= rRet
.Len();
1257 HandleSize(nLSize
,nDSize
,nSetSize
);
1258 nRet
= HandleRecords(nLevel
+1);
1262 xub_StrLen nI
= rRet
.SearchBackward('{');
1263 if (nI
!= STRING_NOTFOUND
)
1265 for(nI
=nI
+1;nI
<rRet
.Len();nI
++)
1266 if (rRet
.GetChar(nI
) != ' ')
1278 rRet
.Erase(nSizeStartPos
);
1280 nCurSize
=nOldCurSize
;
1284 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,
1292 else if (nVariation
==2)
1293 rRet
+= " \\rangle ";
1298 else if (nVariation
==2)
1302 if ((nVariation
==0) || (nVariation
==2))
1303 rRet
+= " right rbrace ";
1305 rRet
+= " right none ";
1310 else if (nVariation
==2)
1316 else if (nVariation
==2)
1317 rRet
+= " \\rline ";
1322 else if (nVariation
==2)
1323 rRet
+= " \\rdline ";
1326 if (nVariation
== 0 || nVariation
== 2)
1327 rRet
+= " right rfloor ";
1328 else if (nVariation
==2)
1329 rRet
+= " right none ";
1334 else if (nVariation
==2)
1335 rRet
+= " \\rceil ";
1347 if (nVariation
== 1)
1383 ((nVariation
== 2) || (nVariation
== 1)))
1387 xub_StrLen nI
= rRet
.SearchBackward('{');
1388 if (nI
!= STRING_NOTFOUND
)
1390 for(nI
=nI
+1;nI
<rRet
.Len();nI
++)
1391 if (rRet
.GetChar(nI
) != ' ')
1403 rRet
.Erase(nSubSupStartPos
);
1409 ((nVariation
== 2) || (nVariation
== 1)))
1437 rRet
+= "overbrace";
1446 rRet
+= "underbrace";
1453 else if ((nPart
==1) &&
1454 ((nVariation
== 2) || (nVariation
== 1)))
1461 if (nVariation
== 0)
1491 rRet
+= "wideslash";
1510 if (nVariation
!= 2)
1517 else if ((nPart
== 1) && (nVariation
== 0))
1524 else if ((nPart
== 1) && (nVariation
== 1))
1526 else if ((nPart
== 2) && (nVariation
== 1))
1539 if ((nVariation
!= 0) && (nVariation
!= 3))
1546 else if ((nPart
== 1) &&
1547 ((nVariation
== 1) || (nVariation
==4)))
1554 else if ((nPart
== 1) && (nVariation
== 2))
1556 else if ((nPart
== 2) && (nVariation
== 2))
1570 if ((nVariation
!= 0) && (nVariation
!= 2))
1577 else if ((nPart
== 1) &&
1578 ((nVariation
== 1) || (nVariation
==3)))
1595 else if ((nPart
== 1) &&
1596 ((nVariation
== 1) || (nVariation
==2)))
1603 else if ((nPart
== 1) && (nVariation
== 0))
1605 else if ((nPart
== 2) && (nVariation
== 0))
1623 else if (nPart
== 1)
1637 ((nVariation
== 0) || (nVariation
== 1)))
1643 else if ((nPart
== 0) && (nVariation
== 2))
1645 else if ((nPart
== 1) && (nVariation
== 2))
1651 else if ((nPart
== 2) || ((((nPart
== 1) &&
1652 (nVariation
== 0)) || (nVariation
== 1))))
1665 newline
--; //there is another term to arrive
1671 else if (nVariation
==1)
1672 rRet
+= " \\lline ";
1673 else if (nVariation
==2)
1674 rRet
+= " \\rangle ";
1680 bSilent
= true; //Skip the optional brackets and/or
1681 //symbols that follow some of these
1682 //records. Foo Data.
1684 /*In matrices and piles we cannot separate equation
1685 *lines with the newline keyword*/
1694 nRet
= HandleChar(nTextStart
,nSetSize
,nLevel
,nTag
,nSelector
,
1695 nVariation
,bSilent
);
1700 nRet
= HandleTemplate(nLevel
,nSelector
,nVariation
,
1701 nLastTemplateBracket
);
1706 nRet
= HandlePile(nSetAlign
,nLevel
,nSelector
,nVariation
);
1707 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,nCurCol
,nCurRow
);
1712 nRet
= HandleMatrix(nLevel
,nSelector
,nVariation
);
1713 HandleMatrixSeparator(nMatrixRows
,nMatrixCols
,nCurCol
,nCurRow
);
1718 HandleEmblishments();
1722 for (i
=0;i
<nTabStops
;i
++)
1727 OSL_FAIL("Not seen in the wild Equation Ruler Field");
1732 *pS
>> aFont
.nTface
;
1734 The typeface number is the negative (which makes it
1735 positive) of the typeface value (unbiased) that appears in
1736 CHAR records that might follow a given FONT record
1738 aFont
.nTface
= 128-aFont
.nTface
;
1739 *pS
>> aFont
.nStyle
;
1740 aUserStyles
.insert(aFont
);
1741 std::vector
<sal_Char
> aSeq
;
1748 aSeq
.push_back(nChar8
);
1750 // Do nothing to the font name now in aSeq!?
1768 while (nRecord
!= END
&& !pS
->IsEof());
1777 /*Simply determine if we are at the end of a record or the end of a line,
1778 *with fiddley logic to see if we are in a matrix or a pile or neither
1780 Note we cannot tell until after the event that this is the last entry
1781 of a pile, so we must strip the last separator of a pile after this
1782 is detected in the PILE handler
1784 void MathType::HandleMatrixSeparator(int nMatrixRows
,int nMatrixCols
,
1785 int &rCurCol
,int &rCurRow
)
1789 if (rCurCol
== nMatrixCols
-1)
1791 if (rCurRow
!= nMatrixRows
-1)
1793 if (nMatrixRows
!=-1)
1802 if (nMatrixRows
!=-1)
1810 /* set the alignment of the following term, but starmath currently
1811 * cannot handle vertical alignment */
1812 void MathType::HandleAlign(sal_uInt8 nHorAlign
, sal_uInt8
/*nVAlign*/, int &rSetAlign
)
1830 /* set size of text, complexity due to overuse of signedness as a flag
1831 * indicator by mathtype file format*/
1832 sal_Bool
MathType::HandleSize(sal_Int16 nLstSize
,sal_Int16 nDefSize
, int &rSetSize
)
1837 if ((-nLstSize
/32 != nDefaultSize
) && (-nLstSize
/32 != nCurSize
))
1845 if (-nLstSize
/32 != nLastSize
)
1847 nLastSize
= nCurSize
;
1849 rRet
+= OUString::number(-nLstSize
/32);
1854 nCurSize
= -nLstSize
/32;
1859 /*sizetable should theoreticaly be filled with the default sizes
1860 *of the various font groupings matching starmaths equivalents
1861 in aTypeFaces, and a test would be done to see if the new font
1862 size would be the same as what starmath would have chosen for
1863 itself anyway in which case the size setting could be ignored*/
1864 nLstSize
= aSizeTable
[nLstSize
];
1865 nLstSize
= nLstSize
+ nDefSize
;
1866 if (nLstSize
!= nCurSize
)
1874 if (nLstSize
!= nLastSize
)
1876 nLastSize
= nCurSize
;
1878 rRet
+= OUString::number(nLstSize
);
1883 nCurSize
= nLstSize
;
1889 int MathType::ConvertFromStarMath( SfxMedium
& rMedium
)
1894 SvStream
*pStream
= rMedium
.GetOutStream();
1897 SvStorageRef pStor
= new SotStorage( pStream
, false );
1899 SvGlobalName
aGName(0x0002ce02L
, 0x0000, 0x0000,0xc0,0x00,
1900 0x00,0x00,0x00,0x00,0x00,0x46 );
1901 pStor
->SetClass( aGName
, 0, OUString("Microsoft Equation 3.0"));
1903 static sal_uInt8
const aCompObj
[] = {
1904 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1905 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1906 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1907 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1908 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1909 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1910 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1911 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1912 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1913 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1914 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1915 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1918 SvStorageStreamRef
xStor( pStor
->OpenSotStream(OUString("\1CompObj")));
1919 xStor
->Write(aCompObj
,sizeof(aCompObj
));
1921 static sal_uInt8
const aOle
[] = {
1922 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1924 0x00, 0x00, 0x00, 0x00
1926 SvStorageStreamRef
xStor2( pStor
->OpenSotStream(OUString("\1Ole")));
1927 xStor2
->Write(aOle
,sizeof(aOle
));
1931 SvStorageStreamRef xSrc
= pStor
->OpenSotStream(OUString("Equation Native"));
1932 if ( (!xSrc
.Is()) || (SVSTREAM_OK
!= xSrc
->GetError()))
1936 pS
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1938 pS
->SeekRel(EQNOLEFILEHDR_SIZE
); //Skip 28byte Header and fill it in later
1939 *pS
<< sal_uInt8(0x03);
1940 *pS
<< sal_uInt8(0x01);
1941 *pS
<< sal_uInt8(0x01);
1942 *pS
<< sal_uInt8(0x03);
1943 *pS
<< sal_uInt8(0x00);
1944 sal_uInt32 nSize
= pS
->Tell();
1945 nPendingAttributes
=0;
1948 *pS
<< sal_uInt8(END
);
1950 nSize
= pS
->Tell()-nSize
;
1952 EQNOLEFILEHDR
aHdr(nSize
+4+1);
1962 sal_uInt8
MathType::HandleNodes(SmNode
*pNode
,int nLevel
)
1965 switch(pNode
->GetType())
1968 HandleAttributes(pNode
,nLevel
);
1971 HandleText(pNode
,nLevel
);
1973 case NVERTICAL_BRACE
:
1974 HandleVerticalBrace(pNode
,nLevel
);
1977 HandleBrace(pNode
,nLevel
);
1980 HandleOperator(pNode
,nLevel
);
1983 HandleFractions(pNode
,nLevel
);
1986 HandleRoot(pNode
,nLevel
);
1990 SmTextNode
*pText
=(SmTextNode
*)pNode
;
1991 //if the token str and the result text are the same then this
1992 //is to be seen as text, else assume its a mathchar
1993 if (pText
->GetText() == OUString(pText
->GetToken().aText
))
1994 HandleText(pText
,nLevel
);
1996 HandleMath(pText
,nLevel
);
2000 HandleMath(pNode
,nLevel
);
2003 HandleSubSupScript(pNode
,nLevel
);
2007 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2008 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2009 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2010 HandleNodes(pTemp
,nLevel
+1);
2014 //Root Node, PILE equivalent, i.e. vertical stack
2015 HandleTable(pNode
,nLevel
);
2018 HandleSmMatrix((SmMatrixNode
*)pNode
,nLevel
);
2022 *pS
<< sal_uInt8(0x0a);
2023 *pS
<< sal_uInt8(LINE
);
2024 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2025 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2026 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2027 HandleNodes(pTemp
,nLevel
+1);
2028 *pS
<< sal_uInt8(END
);
2032 HandleMAlign(pNode
,nLevel
);
2035 *pS
<< sal_uInt8(CHAR
);
2036 *pS
<< sal_uInt8(0x98);
2037 if (pNode
->GetToken().eType
== TSBLANK
)
2038 *pS
<< sal_uInt16(0xEB04);
2040 *pS
<< sal_uInt16(0xEB05);
2044 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2045 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2046 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2047 HandleNodes(pTemp
,nLevel
+1);
2055 int MathType::StartTemplate(sal_uInt16 nSelector
,sal_uInt16 nVariation
)
2057 int nOldPending
=nPendingAttributes
;
2058 *pS
<< sal_uInt8(TMPL
); //Template
2059 *pS
<< sal_uInt8(nSelector
); //selector
2060 *pS
<< sal_uInt8(nVariation
); //variation
2061 *pS
<< sal_uInt8(0x00); //options
2062 *pS
<< sal_uInt8(LINE
);
2063 //theres just no way we can now handle any character
2064 //attributes (from mathtypes perspective) centered
2065 //over an expression but above template attribute
2066 //such as widevec and similar constructs
2067 //we have to drop them
2068 nPendingAttributes
=0;
2072 void MathType::EndTemplate(int nOldPendingAttributes
)
2074 *pS
<< sal_uInt8(END
); //end line
2075 *pS
<< sal_uInt8(END
); //end template
2076 nPendingAttributes
=nOldPendingAttributes
;
2080 void MathType::HandleSmMatrix(SmMatrixNode
*pMatrix
,int nLevel
)
2082 *pS
<< sal_uInt8(MATRIX
);
2083 *pS
<< sal_uInt8(0x00); //vAlign ?
2084 *pS
<< sal_uInt8(0x00); //h_just
2085 *pS
<< sal_uInt8(0x00); //v_just
2086 *pS
<< sal_uInt8(pMatrix
->GetNumRows()); //v_just
2087 *pS
<< sal_uInt8(pMatrix
->GetNumCols()); //v_just
2088 int nBytes
=(pMatrix
->GetNumRows()+1)*2/8;
2089 if (((pMatrix
->GetNumRows()+1)*2)%8)
2091 for (sal_uInt16 j
= 0; j
< nBytes
; j
++)
2092 *pS
<< sal_uInt8(0x00); //row_parts
2093 nBytes
=(pMatrix
->GetNumCols()+1)*2/8;
2094 if (((pMatrix
->GetNumCols()+1)*2)%8)
2096 for (sal_uInt16 k
= 0; k
< nBytes
; k
++)
2097 *pS
<< sal_uInt8(0x00); //col_parts
2098 sal_uInt16 nSize
= pMatrix
->GetNumSubNodes();
2099 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2100 if (SmNode
*pTemp
= pMatrix
->GetSubNode(i
))
2102 *pS
<< sal_uInt8(LINE
); //line
2103 HandleNodes(pTemp
,nLevel
+1);
2104 *pS
<< sal_uInt8(END
); //end line
2106 *pS
<< sal_uInt8(END
);
2110 //Root Node, PILE equivalent, i.e. vertical stack
2111 void MathType::HandleTable(SmNode
*pNode
,int nLevel
)
2113 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
2114 //The root of the starmath is a table, if
2115 //we convert this them each iteration of
2116 //conversion from starmath to mathtype will
2117 //add an extra unnecessary level to the
2118 //mathtype output stack which would grow
2119 //without bound in a multi step conversion
2122 *pS
<< sal_uInt8(0x0A); //initial size
2124 if ( nLevel
|| (nSize
>1))
2126 *pS
<< sal_uInt8(PILE
);
2127 *pS
<< sal_uInt8(nHAlign
); //vAlign ?
2128 *pS
<< sal_uInt8(0x01); //hAlign
2131 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
2132 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
2134 *pS
<< sal_uInt8(LINE
);
2135 HandleNodes(pTemp
,nLevel
+1);
2136 *pS
<< sal_uInt8(END
);
2138 if (nLevel
|| (nSize
>1))
2139 *pS
<< sal_uInt8(END
);
2143 void MathType::HandleRoot(SmNode
*pNode
,int nLevel
)
2146 *pS
<< sal_uInt8(TMPL
); //Template
2147 *pS
<< sal_uInt8(0x0D); //selector
2148 if (pNode
->GetSubNode(0))
2149 *pS
<< sal_uInt8(0x01); //variation
2151 *pS
<< sal_uInt8(0x00); //variation
2152 *pS
<< sal_uInt8(0x00); //options
2154 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2156 *pS
<< sal_uInt8(LINE
); //line
2157 HandleNodes(pTemp
,nLevel
+1);
2158 *pS
<< sal_uInt8(END
);
2161 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2163 *pS
<< sal_uInt8(LINE
); //line
2164 HandleNodes(pTemp
,nLevel
+1);
2165 *pS
<< sal_uInt8(END
);
2168 *pS
<< sal_uInt8(LINE
|0x10); //dummy line
2172 *pS
<< sal_uInt8(END
);
2175 sal_uInt8
MathType::HandleCScript(SmNode
*pNode
,SmNode
*pContent
,int nLevel
,
2176 sal_uLong
*pPos
,sal_Bool bTest
)
2178 sal_uInt8 nVariation2
=0xff;
2180 if (bTest
&& pNode
->GetSubNode(CSUP
+1))
2183 if (pNode
->GetSubNode(CSUB
+1))
2186 else if (pNode
->GetSubNode(CSUB
+1))
2189 if (nVariation2
!=0xff)
2193 *pS
<< sal_uInt8(TMPL
); //Template
2194 *pS
<< sal_uInt8(0x2B); //selector
2196 *pS
<< sal_uInt8(0x00); //options
2200 *pS
<< sal_uInt8(LINE
); //line
2201 HandleNodes(pContent
,nLevel
+1);
2202 *pS
<< sal_uInt8(END
); //line
2205 *pS
<< sal_uInt8(LINE
|0x10);
2207 *pS
<< sal_uInt8(0x0B);
2210 if (NULL
!= (pTemp
= pNode
->GetSubNode(CSUB
+1)))
2212 *pS
<< sal_uInt8(LINE
); //line
2213 HandleNodes(pTemp
,nLevel
+1);
2214 *pS
<< sal_uInt8(END
); //line
2217 *pS
<< sal_uInt8(LINE
|0x10);
2218 if (bTest
&& NULL
!= (pTemp
= pNode
->GetSubNode(CSUP
+1)))
2220 *pS
<< sal_uInt8(LINE
); //line
2221 HandleNodes(pTemp
,nLevel
+1);
2222 *pS
<< sal_uInt8(END
); //line
2225 *pS
<< sal_uInt8(LINE
|0x10);
2233 Sub and Sup scripts and another problem area, StarMath
2234 can have all possible options used at the same time, whereas
2235 Mathtype cannot. The ordering of the nodes for each system
2236 is quite different as well leading to some complexity
2238 void MathType::HandleSubSupScript(SmNode
*pNode
,int nLevel
)
2242 sal_uInt8 nVariation
=0xff;
2243 if (pNode
->GetSubNode(LSUP
+1))
2246 if (pNode
->GetSubNode(LSUB
+1))
2249 else if (NULL
!= (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2252 if (nVariation
!=0xff)
2254 *pS
<< sal_uInt8(TMPL
); //Template
2255 *pS
<< sal_uInt8(0x2c); //selector
2257 *pS
<< sal_uInt8(0x00); //options
2258 *pS
<< sal_uInt8(0x0B);
2260 if (NULL
!= (pTemp
= pNode
->GetSubNode(LSUB
+1)))
2262 *pS
<< sal_uInt8(LINE
); //line
2263 HandleNodes(pTemp
,nLevel
+1);
2264 *pS
<< sal_uInt8(END
); //line
2267 *pS
<< sal_uInt8(LINE
|0x10);
2268 if (NULL
!= (pTemp
= pNode
->GetSubNode(LSUP
+1)))
2270 *pS
<< sal_uInt8(LINE
); //line
2271 HandleNodes(pTemp
,nLevel
+1);
2272 *pS
<< sal_uInt8(END
); //line
2275 *pS
<< sal_uInt8(LINE
|0x10);
2276 *pS
<< sal_uInt8(END
);
2281 sal_uInt8 nVariation2
=HandleCScript(pNode
,NULL
,nLevel
);
2283 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2285 HandleNodes(pTemp
,nLevel
+1);
2288 if (nVariation2
!= 0xff)
2289 *pS
<< sal_uInt8(END
);
2291 if (NULL
!= (pNode
->GetSubNode(RSUP
+1)))
2294 if (pNode
->GetSubNode(RSUB
+1))
2297 else if (NULL
!= (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2300 if (nVariation
!=0xff)
2302 *pS
<< sal_uInt8(TMPL
); //Template
2303 *pS
<< sal_uInt8(0x0F); //selector
2305 *pS
<< sal_uInt8(0x00); //options
2306 *pS
<< sal_uInt8(0x0B);
2308 if (NULL
!= (pTemp
= pNode
->GetSubNode(RSUB
+1)))
2310 *pS
<< sal_uInt8(LINE
); //line
2311 HandleNodes(pTemp
,nLevel
+1);
2312 *pS
<< sal_uInt8(END
); //line
2315 *pS
<< sal_uInt8(LINE
|0x10);
2316 if (NULL
!= (pTemp
= pNode
->GetSubNode(RSUP
+1)))
2318 *pS
<< sal_uInt8(LINE
); //line
2319 HandleNodes(pTemp
,nLevel
+1);
2320 *pS
<< sal_uInt8(END
); //line
2323 *pS
<< sal_uInt8(LINE
|0x10);
2324 *pS
<< sal_uInt8(END
); //line
2327 //After subscript mathtype will keep the size of
2328 //normal text at the subscript size, sigh.
2329 *pS
<< sal_uInt8(0x0A);
2333 void MathType::HandleFractions(SmNode
*pNode
,int nLevel
)
2336 *pS
<< sal_uInt8(TMPL
); //Template
2337 *pS
<< sal_uInt8(0x0E); //selector
2338 *pS
<< sal_uInt8(0x00); //variation
2339 *pS
<< sal_uInt8(0x00); //options
2341 *pS
<< sal_uInt8(0x0A);
2342 *pS
<< sal_uInt8(LINE
); //line
2343 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2344 HandleNodes(pTemp
,nLevel
+1);
2345 *pS
<< sal_uInt8(END
);
2347 *pS
<< sal_uInt8(0x0A);
2348 *pS
<< sal_uInt8(LINE
); //line
2349 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2350 HandleNodes(pTemp
,nLevel
+1);
2351 *pS
<< sal_uInt8(END
);
2353 *pS
<< sal_uInt8(END
);
2357 void MathType::HandleBrace(SmNode
*pNode
,int nLevel
)
2360 SmNode
*pLeft
=pNode
->GetSubNode(0);
2361 SmNode
*pRight
=pNode
->GetSubNode(2);
2363 *pS
<< sal_uInt8(TMPL
); //Template
2365 sal_uInt8 nBSpec
=0x10;
2366 sal_uLong nLoc
= pS
->Tell();
2369 switch (pLeft
->GetToken().eType
)
2372 *pS
<< sal_uInt8(tmANGLE
); //selector
2373 *pS
<< sal_uInt8(0x00); //variation
2374 *pS
<< sal_uInt8(0x00); //options
2377 *pS
<< sal_uInt8(tmBRACE
); //selector
2378 *pS
<< sal_uInt8(0x00); //variation
2379 *pS
<< sal_uInt8(0x00); //options
2383 *pS
<< sal_uInt8(tmBRACK
); //selector
2384 *pS
<< sal_uInt8(0x00); //variation
2385 *pS
<< sal_uInt8(0x00); //options
2389 *pS
<< sal_uInt8(tmFLOOR
); //selector
2390 *pS
<< sal_uInt8(0x00); //variation
2391 *pS
<< sal_uInt8(0x00); //options
2394 *pS
<< sal_uInt8(tmBAR
); //selector
2395 *pS
<< sal_uInt8(0x00); //variation
2396 *pS
<< sal_uInt8(0x00); //options
2400 *pS
<< sal_uInt8(tmDBAR
); //selector
2401 *pS
<< sal_uInt8(0x00); //variation
2402 *pS
<< sal_uInt8(0x00); //options
2405 *pS
<< sal_uInt8(tmPAREN
); //selector
2406 *pS
<< sal_uInt8(0x00); //variation
2407 *pS
<< sal_uInt8(0x00); //options
2413 if (NULL
!= (pTemp
= pNode
->GetSubNode(1)))
2415 *pS
<< sal_uInt8(LINE
); //line
2416 HandleNodes(pTemp
,nLevel
+1);
2417 *pS
<< sal_uInt8(END
); //options
2421 HandleNodes(pLeft
,nLevel
+1);
2422 if (bIsReInterpBrace
)
2424 sal_uLong nLoc2
= pS
->Tell();
2426 *pS
<< sal_uInt8(0x2D);
2428 *pS
<< sal_uInt8(CHAR
);
2429 *pS
<< sal_uInt8(0x96);
2430 *pS
<< sal_uInt16(0xEC07);
2434 HandleNodes(pRight
,nLevel
+1);
2436 *pS
<< sal_uInt8(END
);
2440 void MathType::HandleVerticalBrace(SmNode
*pNode
,int nLevel
)
2443 *pS
<< sal_uInt8(TMPL
); //Template
2444 if (pNode
->GetToken().eType
== TUNDERBRACE
)
2445 *pS
<< sal_uInt8(tmLHBRACE
); //selector
2447 *pS
<< sal_uInt8(tmUHBRACE
); //selector
2448 *pS
<< sal_uInt8(0x01); //variation
2449 *pS
<< sal_uInt8(0x00); //options
2451 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
2453 *pS
<< sal_uInt8(LINE
); //line
2454 HandleNodes(pTemp
,nLevel
+1);
2455 *pS
<< sal_uInt8(END
); //options
2458 if (NULL
!= (pTemp
= pNode
->GetSubNode(2)))
2460 *pS
<< sal_uInt8(LINE
); //line
2461 HandleNodes(pTemp
,nLevel
+1);
2462 *pS
<< sal_uInt8(END
); //options
2464 *pS
<< sal_uInt8(END
);
2467 void MathType::HandleOperator(SmNode
*pNode
,int nLevel
)
2469 if (HandleLim(pNode
,nLevel
))
2473 sal_uInt8 nVariation
;
2475 switch (pNode
->GetToken().eType
)
2482 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2483 pNode
->GetSubNode(1),nLevel
,&nPos
,0);
2486 nVariation
=HandleCScript(pNode
->GetSubNode(0),
2487 pNode
->GetSubNode(1),nLevel
,&nPos
);
2491 sal_uInt8 nOldVariation
=nVariation
;
2492 sal_uInt8 nIntVariation
=nVariation
;
2495 if (nVariation
!= 0xff)
2499 if (nVariation
== 2)
2504 else if (nVariation
== 0)
2506 else if (nVariation
== 1)
2514 *pS
<< sal_uInt8(TMPL
);
2515 switch(pNode
->GetToken().eType
)
2518 if (nOldVariation
!= 0xff)
2519 *pS
<< sal_uInt8(0x18); //selector
2521 *pS
<< sal_uInt8(0x15); //selector
2522 *pS
<< nIntVariation
; //variation
2525 if (nOldVariation
!= 0xff)
2527 *pS
<< sal_uInt8(0x19);
2528 *pS
<< sal_uInt8(0x01);
2532 *pS
<< sal_uInt8(0x16);
2533 *pS
<< sal_uInt8(0x00);
2537 if (nOldVariation
!= 0xff)
2539 *pS
<< sal_uInt8(0x1a);
2540 *pS
<< sal_uInt8(0x01);
2544 *pS
<< sal_uInt8(0x17);
2545 *pS
<< sal_uInt8(0x00);
2549 if (nOldVariation
!= 0xff)
2551 *pS
<< sal_uInt8(0x18);
2552 *pS
<< sal_uInt8(0x02);
2556 *pS
<< sal_uInt8(0x15);
2557 *pS
<< sal_uInt8(0x03);
2561 if (nOldVariation
!= 0xff)
2563 *pS
<< sal_uInt8(0x19);
2564 *pS
<< sal_uInt8(0x00);
2568 *pS
<< sal_uInt8(0x16);
2569 *pS
<< sal_uInt8(0x02);
2573 if (nOldVariation
!= 0xff)
2575 *pS
<< sal_uInt8(0x1a);
2576 *pS
<< sal_uInt8(0x00);
2580 *pS
<< sal_uInt8(0x17);
2581 *pS
<< sal_uInt8(0x02);
2586 *pS
<< sal_uInt8(0x1d);
2590 *pS
<< sal_uInt8(0x1f);
2594 *pS
<< sal_uInt8(0x21);
2598 *pS
<< sal_uInt8(0x00); //options
2604 *pS
<< sal_uInt8(LINE
); //line
2605 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
2606 *pS
<< sal_uInt8(END
); //line
2607 *pS
<< sal_uInt8(LINE
|0x10);
2608 *pS
<< sal_uInt8(LINE
|0x10);
2612 *pS
<< sal_uInt8(0x0D);
2613 switch(pNode
->GetToken().eType
)
2617 *pS
<< sal_uInt8(CHAR
);
2618 *pS
<< sal_uInt8(0x86);
2619 *pS
<< sal_uInt16(0x2211);
2622 *pS
<< sal_uInt8(CHAR
);
2623 *pS
<< sal_uInt8(0x86);
2624 *pS
<< sal_uInt16(0x220F);
2627 *pS
<< sal_uInt8(CHAR
);
2628 *pS
<< sal_uInt8(0x8B);
2629 *pS
<< sal_uInt16(0x2210);
2633 *pS
<< sal_uInt8(CHAR
);
2634 *pS
<< sal_uInt8(0x86);
2635 *pS
<< sal_uInt16(0x222B);
2638 *pS
<< sal_uInt8(CHAR
);
2639 *pS
<< sal_uInt8(0x86);
2640 *pS
<< sal_uInt16(0x222B);
2643 *pS
<< sal_uInt8(CHAR
);
2644 *pS
<< sal_uInt8(0x86);
2645 *pS
<< sal_uInt16(0x222B);
2648 *pS
<< sal_uInt8(END
);
2649 *pS
<< sal_uInt8(0x0A);
2653 int MathType::HandlePile(int &rSetAlign
,int nLevel
,sal_uInt8 nSelector
,
2654 sal_uInt8 nVariation
)
2659 HandleAlign(nHAlign
,nVAlign
,rSetAlign
);
2661 rRet
+= " stack {\n";
2662 int nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
,-1,-1);
2663 rRet
.Erase(rRet
.Len()-3,2);
2674 int MathType::HandleMatrix(int nLevel
,sal_uInt8 nSelector
,
2675 sal_uInt8 nVariation
)
2677 sal_uInt8 nH_just
,nV_just
,nRows
,nCols
;
2683 int nBytes
= ((nRows
+1)*2)/8;
2684 if (((nRows
+1)*2)%8)
2686 pS
->SeekRel(nBytes
);
2687 nBytes
= ((nCols
+1)*2)/8;
2688 if (((nCols
+1)*2)%8)
2690 pS
->SeekRel(nBytes
);
2691 rRet
+= " matrix {\n";
2692 int nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
,nRows
,nCols
);
2694 xub_StrLen nI
= rRet
.SearchBackward('#');
2695 if ((nI
!= STRING_NOTFOUND
) && (nI
> 0))
2696 if (rRet
.GetChar(nI
-1) != '#') //missing column
2703 int MathType::HandleTemplate(int nLevel
,sal_uInt8
&rSelector
,
2704 sal_uInt8
&rVariation
, xub_StrLen
&rLastTemplateBracket
)
2706 sal_uInt8 nOption
; //This appears utterly unused
2710 OSL_ENSURE(rSelector
< 48,"Selector out of range");
2711 if ((rSelector
>= 21) && (rSelector
<=26))
2713 OSL_ENSURE(nOption
< 2,"Option out of range");
2715 else if (/*(rSelector >= 0) &&*/ (rSelector
<=12))
2717 OSL_ENSURE(nOption
< 3,"Option out of range");
2720 //For the (broken) case where one subscript template ends, and there is
2721 //another one after it, mathtype handles it as if the second one was
2722 //inside the first one and renders it as sub of sub
2724 if ( (rSelector
== 0xf) && (rLastTemplateBracket
!= STRING_NOTFOUND
) )
2727 for (xub_StrLen nI
= rLastTemplateBracket
+1; nI
< rRet
.Len(); nI
++ )
2728 if (rRet
.GetChar(nI
) != ' ')
2736 int nRet
= HandleRecords(nLevel
+1,rSelector
,rVariation
);
2740 rRet
.Erase(rLastTemplateBracket
,1);
2742 rLastTemplateBracket
= STRING_NOTFOUND
;
2744 if (rSelector
== 0xf)
2745 rLastTemplateBracket
= rRet
.SearchBackward('}');
2747 rLastTemplateBracket
= STRING_NOTFOUND
;
2749 rSelector
= sal::static_int_cast
< sal_uInt8
>(-1);
2753 void MathType::HandleEmblishments()
2774 nPostSup
= sPost
.Len();
2776 sPost
.InsertAscii(" ' ",nPostSup
-1);
2783 nPostSup
= sPost
.Len();
2785 sPost
.InsertAscii(" '' ",nPostSup
-1);
2791 sPost
+= " lsup {}";
2792 nPostlSup
= sPost
.Len();
2794 sPost
.InsertAscii(" ' ",nPostlSup
-1);
2807 rRet
+= " overstrike ";
2816 nPostSup
= sPost
.Len();
2818 sPost
.InsertAscii(" ''' ",nPostSup
-1);
2825 OSL_ENSURE(nEmbel
< 21,"Embel out of range");
2833 void MathType::HandleSetSize()
2856 int MathType::HandleChar(xub_StrLen
&rTextStart
,int &rSetSize
,int nLevel
,
2857 sal_uInt8 nTag
,sal_uInt8 nSelector
,sal_uInt8 nVariation
, sal_Bool bSilent
)
2864 //This is a candidate for function recognition, whatever
2868 sal_uInt8 nOldTypeFace
= nTypeFace
;
2880 bad character, old mathtype < 3 has these
2887 //A bit tricky, the character emblishments for
2888 //mathtype can all be listed after eachother, in
2889 //starmath some must go before the character and some
2890 //must go after. In addition some of the emblishments
2891 //may repeated and in starmath some of these groups
2892 //must be gathered together. sPost is the portion that
2893 //follows the char and nPostSup and nPostlSup are the
2894 //indexes at which this class of emblishment is
2897 nPostSup
= nPostlSup
= 0;
2898 int nOriglen
=rRet
.Len()-rTextStart
;
2899 rRet
+= " {"; // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2900 if ((!bSilent
) && ((nOriglen
) > 1))
2902 nRet
= HandleRecords(nLevel
+1,nSelector
,nVariation
);
2908 TypeFaceToString(aStr
,nOldTypeFace
);
2910 rRet
.Insert(aStr
,rTextStart
);
2913 TypeFaceToString(aStr
,nTypeFace
);
2919 rTextStart
= rRet
.Len();
2925 xub_StrLen nOldLen
= rRet
.Len();
2927 HandleSize(nLSize
,nDSize
,rSetSize
) ||
2928 (nOldTypeFace
!= nTypeFace
)
2931 if ((nOldLen
- rTextStart
) > 1)
2933 rRet
.InsertAscii("\"",nOldLen
);
2935 TypeFaceToString(aStr
,nOldTypeFace
);
2937 rRet
.Insert(aStr
,rTextStart
);
2939 rTextStart
= rRet
.Len();
2941 nOldLen
= rRet
.Len();
2942 if (!LookupChar(nChar
,rRet
,nVersion
,nTypeFace
))
2944 if (nOldLen
- rTextStart
> 1)
2946 rRet
.InsertAscii("\"",nOldLen
);
2948 TypeFaceToString(aStr
,nOldTypeFace
);
2950 rRet
.Insert(aStr
,rTextStart
);
2952 rTextStart
= rRet
.Len();
2954 lcl_PrependDummyTerm(rRet
, rTextStart
);
2957 if ((xfEMBELL(nTag
)) && (!bSilent
))
2959 rRet
+= '}'; // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2962 rTextStart
= rRet
.Len();
2967 sal_Bool
MathType::HandleLim(SmNode
*pNode
,int nLevel
)
2970 //Special case for the "lim" option in StarMath
2971 if ((pNode
->GetToken().eType
== TLIM
)
2972 || (pNode
->GetToken().eType
== TLIMSUP
)
2973 || (pNode
->GetToken().eType
== TLIMINF
)
2976 if (pNode
->GetSubNode(1))
2978 sal_uInt8 nVariation2
=HandleCScript(pNode
->GetSubNode(0),NULL
,
2981 *pS
<< sal_uInt8(0x0A);
2982 *pS
<< sal_uInt8(LINE
); //line
2983 *pS
<< sal_uInt8(CHAR
|0x10);
2984 *pS
<< sal_uInt8(0x82);
2985 *pS
<< sal_uInt16('l');
2986 *pS
<< sal_uInt8(CHAR
|0x10);
2987 *pS
<< sal_uInt8(0x82);
2988 *pS
<< sal_uInt16('i');
2989 *pS
<< sal_uInt8(CHAR
|0x10);
2990 *pS
<< sal_uInt8(0x82);
2991 *pS
<< sal_uInt16('m');
2993 if (pNode
->GetToken().eType
== TLIMSUP
)
2995 *pS
<< sal_uInt8(CHAR
); //some space
2996 *pS
<< sal_uInt8(0x98);
2997 *pS
<< sal_uInt16(0xEB04);
2999 *pS
<< sal_uInt8(CHAR
|0x10);
3000 *pS
<< sal_uInt8(0x82);
3001 *pS
<< sal_uInt16('s');
3002 *pS
<< sal_uInt8(CHAR
|0x10);
3003 *pS
<< sal_uInt8(0x82);
3004 *pS
<< sal_uInt16('u');
3005 *pS
<< sal_uInt8(CHAR
|0x10);
3006 *pS
<< sal_uInt8(0x82);
3007 *pS
<< sal_uInt16('p');
3009 else if (pNode
->GetToken().eType
== TLIMINF
)
3011 *pS
<< sal_uInt8(CHAR
); //some space
3012 *pS
<< sal_uInt8(0x98);
3013 *pS
<< sal_uInt16(0xEB04);
3015 *pS
<< sal_uInt8(CHAR
|0x10);
3016 *pS
<< sal_uInt8(0x82);
3017 *pS
<< sal_uInt16('i');
3018 *pS
<< sal_uInt8(CHAR
|0x10);
3019 *pS
<< sal_uInt8(0x82);
3020 *pS
<< sal_uInt16('n');
3021 *pS
<< sal_uInt8(CHAR
|0x10);
3022 *pS
<< sal_uInt8(0x82);
3023 *pS
<< sal_uInt16('f');
3027 *pS
<< sal_uInt8(CHAR
); //some space
3028 *pS
<< sal_uInt8(0x98);
3029 *pS
<< sal_uInt16(0xEB04);
3031 if (nVariation2
!= 0xff)
3033 *pS
<< sal_uInt8(END
);
3034 *pS
<< sal_uInt8(END
);
3036 HandleNodes(pNode
->GetSubNode(1),nLevel
+1);
3037 //*pS << sal_uInt8(END); //options
3044 void MathType::HandleMAlign(SmNode
*pNode
,int nLevel
)
3046 sal_uInt8 nPushedHAlign
=nHAlign
;
3047 switch(pNode
->GetToken().eType
)
3059 sal_uInt16 nSize
= pNode
->GetNumSubNodes();
3060 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
3061 if (SmNode
*pTemp
= pNode
->GetSubNode(i
))
3062 HandleNodes(pTemp
,nLevel
+1);
3063 nHAlign
=nPushedHAlign
;
3066 void MathType::HandleMath(SmNode
*pNode
, int /*nLevel*/)
3068 if (pNode
->GetToken().eType
== TMLINE
)
3070 *pS
<< sal_uInt8(END
);
3071 *pS
<< sal_uInt8(LINE
);
3075 SmMathSymbolNode
*pTemp
=(SmMathSymbolNode
*)pNode
;
3076 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3078 sal_Unicode nArse
= SmTextNode::ConvertSymbolToUnicode(pTemp
->GetText()[i
]);
3079 if ((nArse
== 0x2224) || (nArse
== 0x2288) || (nArse
== 0x2285) ||
3082 *pS
<< sal_uInt8(CHAR
|0x20);
3084 else if ((nPendingAttributes
) &&
3085 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3087 *pS
<< sal_uInt8(0x22);
3090 *pS
<< sal_uInt8(CHAR
); //char without formula recognition
3091 //The typeface seems to be MTEXTRA for unicode characters,
3092 //though how to determine when mathtype chooses one over
3093 //the other is unknown. This should do the trick
3096 if ( (nArse
== 0x2213) || (nArse
== 0x2218) ||
3097 (nArse
== 0x210F) || (
3098 (nArse
>= 0x22EE) && (nArse
<= 0x22FF)
3101 nBias
= 0xB; //typeface
3103 else if ((nArse
> 0x2000) || (nArse
== 0x00D7))
3104 nBias
= 0x6; //typeface
3105 else if (nArse
== 0x3d1)
3107 else if ((nArse
> 0xFF) && ((nArse
< 0x393) || (nArse
> 0x3c9)))
3108 nBias
= 0xB; //typeface
3109 else if ((nArse
== 0x2F) || (nArse
== 0x2225))
3110 nBias
= 0x2; //typeface
3112 nBias
= 0x3; //typeface
3114 *pS
<< sal_uInt8(nSpec
+nBias
+128); //typeface
3116 if (nArse
== 0x2224)
3118 *pS
<< sal_uInt16(0x7C);
3119 *pS
<< sal_uInt8(EMBEL
);
3120 *pS
<< sal_uInt8(0x0A);
3121 *pS
<< sal_uInt8(END
); //end embel
3122 *pS
<< sal_uInt8(END
); //end embel
3124 else if (nArse
== 0x2225)
3125 *pS
<< sal_uInt16(0xEC09);
3126 else if (nArse
== 0xE421)
3127 *pS
<< sal_uInt16(0x2265);
3128 else if (nArse
== 0x230A)
3129 *pS
<< sal_uInt16(0xF8F0);
3130 else if (nArse
== 0x230B)
3131 *pS
<< sal_uInt16(0xF8FB);
3132 else if (nArse
== 0xE425)
3133 *pS
<< sal_uInt16(0x2264);
3134 else if (nArse
== 0x226A)
3136 *pS
<< sal_uInt16(0x3C);
3137 *pS
<< sal_uInt8(CHAR
);
3138 *pS
<< sal_uInt8(0x98);
3139 *pS
<< sal_uInt16(0xEB01);
3140 *pS
<< sal_uInt8(CHAR
);
3141 *pS
<< sal_uInt8(0x86);
3142 *pS
<< sal_uInt16(0x3c);
3144 else if (nArse
== 0x2288)
3146 *pS
<< sal_uInt16(0x2286);
3147 *pS
<< sal_uInt8(EMBEL
);
3148 *pS
<< sal_uInt8(0x0A);
3149 *pS
<< sal_uInt8(END
); //end embel
3150 *pS
<< sal_uInt8(END
); //end embel
3152 else if (nArse
== 0x2289)
3154 *pS
<< sal_uInt16(0x2287);
3155 *pS
<< sal_uInt8(EMBEL
);
3156 *pS
<< sal_uInt8(0x0A);
3157 *pS
<< sal_uInt8(END
); //end embel
3158 *pS
<< sal_uInt8(END
); //end embel
3160 else if (nArse
== 0x2285)
3162 *pS
<< sal_uInt16(0x2283);
3163 *pS
<< sal_uInt8(EMBEL
);
3164 *pS
<< sal_uInt8(0x0A);
3165 *pS
<< sal_uInt8(END
); //end embel
3166 *pS
<< sal_uInt8(END
); //end embel
3171 nPendingAttributes
= 0;
3174 void MathType::HandleAttributes(SmNode
*pNode
,int nLevel
)
3176 int nOldPending
= 0;
3178 SmTextNode
*pIsText
= 0;
3180 if (NULL
!= (pTemp
= pNode
->GetSubNode(0)))
3182 pIsText
= (SmTextNode
*)pNode
->GetSubNode(1);
3184 switch (pTemp
->GetToken().eType
)
3187 //theres just no way we can now handle any character
3188 //attributes (from mathtypes perspective) centered
3189 //over an expression but above template attributes
3190 //such as widevec and similar constructs
3191 //we have to drop them
3192 nOldPending
= StartTemplate(0x2f,0x01);
3194 case TCHECK
: //Not Exportable
3195 case TACUTE
: //Not Exportable
3196 case TGRAVE
: //Not Exportable
3197 case TCIRCLE
: //Not Exportable
3198 case TWIDETILDE
: //Not Exportable
3199 case TWIDEHAT
: //Not Exportable
3202 nOldPending
= StartTemplate(0x10);
3204 case TOVERLINE
: //If the next node is not text
3205 //or text with more than one char
3206 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3207 (pIsText
->GetText().getLength() > 1))
3208 nOldPending
= StartTemplate(0x11);
3211 nPendingAttributes
++;
3217 HandleNodes(pIsText
,nLevel
+1);
3219 switch (pTemp
->GetToken().eType
)
3223 EndTemplate(nOldPending
);
3226 if ((pIsText
->GetToken().eType
!= TTEXT
) ||
3227 (pIsText
->GetText().getLength() > 1))
3228 EndTemplate(nOldPending
);
3234 //if there was no suitable place to put the attribute,
3235 //then we have to just give up on it
3236 if (nPendingAttributes
)
3237 nPendingAttributes
--;
3240 if ((nInsertion
!= 0) && NULL
!= (pTemp
= pNode
->GetSubNode(0)))
3242 sal_uLong nPos
= pS
->Tell();
3244 pS
->Seek(nInsertion
);
3245 switch(pTemp
->GetToken().eType
)
3247 case TACUTE
: //Not Exportable
3248 case TGRAVE
: //Not Exportable
3249 case TCIRCLE
: //Not Exportable
3252 *pS
<< sal_uInt8(2);
3255 *pS
<< sal_uInt8(3);
3258 *pS
<< sal_uInt8(4);
3261 *pS
<< sal_uInt8(8);
3264 *pS
<< sal_uInt8(9);
3267 *pS
<< sal_uInt8(11);
3270 *pS
<< sal_uInt8(16);
3273 if ((pIsText
->GetToken().eType
== TTEXT
) &&
3274 (pIsText
->GetText().getLength() == 1))
3275 *pS
<< sal_uInt8(17);
3278 *pS
<< sal_uInt8(20);
3286 *pS
<< sal_uInt8(17);
3289 *pS
<< sal_uInt8(0x2);
3297 void MathType::HandleText(SmNode
*pNode
, int /*nLevel*/)
3299 SmTextNode
*pTemp
=(SmTextNode
*)pNode
;
3300 for(sal_Int32 i
=0;i
<pTemp
->GetText().getLength();i
++)
3302 if ((nPendingAttributes
) &&
3303 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3305 *pS
<< sal_uInt8(0x22); //char, with attributes right
3306 //after the character
3309 *pS
<< sal_uInt8(CHAR
);
3311 sal_uInt8 nFace
= 0x1;
3312 if (pNode
->GetFont().GetItalic() == ITALIC_NORMAL
)
3314 else if (pNode
->GetFont().GetWeight() == WEIGHT_BOLD
)
3316 *pS
<< sal_uInt8(nFace
+128); //typeface
3317 sal_uInt16 nChar
= pTemp
->GetText()[i
];
3318 *pS
<< SmTextNode::ConvertSymbolToUnicode(nChar
);
3320 //Mathtype can only have these sort of character
3321 //attributes on a single character, starmath can put them
3322 //anywhere, when the entity involved is a text run this is
3323 //a large effort to place the character attribute on the
3324 //central mathtype character so that it does pretty much
3325 //what the user probably has in mind. The attributes
3326 //filled in here are dummy ones which are replaced in the
3327 //ATTRIBUT handler if a suitable location for the
3328 //attributes was found here. Unfortunately it is
3329 //possible for starmath to place character attributes on
3330 //entities which cannot occur in mathtype e.g. a Summation
3331 //symbol so these attributes may be lost
3332 if ((nPendingAttributes
) &&
3333 (i
== ((pTemp
->GetText().getLength()+1)/2)-1))
3335 *pS
<< sal_uInt8(EMBEL
);
3336 while (nPendingAttributes
)
3338 *pS
<< sal_uInt8(2);
3339 //wedge the attributes in here and clear
3341 nPendingAttributes
--;
3343 nInsertion
=pS
->Tell();
3344 *pS
<< sal_uInt8(END
); //end embel
3345 *pS
<< sal_uInt8(END
); //end embel
3350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */