116 while (pID && !pID->
IsNull())
118 bool bAlreadySeen = !aSeen.
insert(pID).second;
120 throw std::runtime_error(
"loop in conversion");
142 while (pID && !pID->
IsNull())
144 bool bAlreadySeen = !aSeen.
insert(pID).second;
146 throw std::runtime_error(
"loop in conversion");
166 if (pTableLayout !=
nullptr)
205 return (dWidth + dLeft + dRight);
214 sal_Int32 nWidth = 0;
220 SAL_WARN(
"lwp",
"missing table layout, early return");
226 SAL_WARN(
"lwp",
"missing table, early return");
229 double dDefaultWidth = pTable->
GetWidth();
234 for(sal_uInt16
i =0;
i< nCol;
i++)
238 double dColumnWidth = dDefaultWidth;
240 while (pColumnLayout)
242 bool bAlreadySeen = !aSeen.
insert(pColumnLayout).second;
244 throw std::runtime_error(
"loop in conversion");
247 dColumnWidth = pColumnLayout->
GetWidth();
250 pColumnID = &pColumnLayout->
GetNext();
253 dWidth += dColumnWidth;
272 std::unique_ptr<XFShadow> pXFShadow(
GetXFShadow());
275 pTableStyle->
SetShadow(pXFShadow->GetPosition(), pXFShadow->GetOffset(), pXFShadow->GetColor());
344 aPoint = pGeometry->GetOrigin();
399 m_pFrame->Parse(xXFFrame.get(),
static_cast<sal_uInt16
>(nStart));
407 pCont->
Add(xXFFrame.get());
417 std::unique_ptr<XFFrameStyle> xFrameStyle(
new XFFrameStyle);
418 m_pFrame->RegisterStyle(xFrameStyle);
425 , m_pDefaultCellLayout(nullptr)
426 , m_bConverted(false)
463 bool bAlreadySeen = !aSeen.
insert(pRowLayout).second;
465 throw std::runtime_error(
"loop in conversion");
474 pRowID = &pRowLayout->
GetNext();
553 throw std::range_error(
"corrupt LwpTableLayout");
557 throw std::range_error(
"corrupt LwpTableLayout");
562 std::unique_ptr<bool[]> pWidthCalculated(
new bool[nCols] );
563 for(sal_uInt16
i=0;
i<nCols;
i++)
565 pWidthCalculated[
i] =
false;
569 double dDefaultColumn = pTable->
GetWidth();
570 sal_uInt16 nJustifiableColumn = nCols;
579 while (pColumnLayout)
581 bool bAlreadySeen = !aSeen.
insert(pColumnLayout).second;
583 throw std::runtime_error(
"loop in conversion");
588 throw std::range_error(
"corrupt LwpTableLayout");
593 pWidthCalculated[nColId] =
true;
594 dTableWidth -= pColumnLayout->
GetWidth();
595 nJustifiableColumn --;
598 pColumnID = &pColumnLayout->
GetNext();
603 if (nJustifiableColumn == 0 && nCols != 0)
605 nJustifiableColumn ++;
608 pWidthCalculated[nCols-1] =
false;
609 dTableWidth +=
m_aColumns[nCols-1]->GetWidth();
614 dTableWidth = dDefaultColumn;
620 dDefaultColumn = nJustifiableColumn ? dTableWidth/nJustifiableColumn : 0;
623 std::unique_ptr<XFColStyle> xColStyle(
new XFColStyle);
624 xColStyle->SetWidth(
static_cast<float>(dDefaultColumn));
631 for(
i=0;
i<nCols;
i++)
636 if(!pWidthCalculated[
i])
656 if (pTable ==
nullptr)
663 std::unique_ptr<XFRowStyle> xRowStyle(
new XFRowStyle);
666 xRowStyle->SetMinRowHeight(
static_cast<float>(pTable->
GetHeight()));
670 xRowStyle->SetRowHeight(
static_cast<float>(pTable->
GetHeight()));
683 pRowID = &pRowLayout->
GetNext();
700 if (pTable ==
nullptr)
702 SAL_WARN(
"lwp",
"missing table, early return");
714 throw std::runtime_error(
"max legal row exceeded");
716 throw std::runtime_error(
"max legal column exceeded");
726 std::unique_ptr<XFTableStyle> xTableStyle(
new XFTableStyle);
776 throw std::runtime_error(
"missing super table");
781 throw std::runtime_error(
"this table is already parsed");
794 sal_uInt16 nContentRow = 0;
801 sal_uInt16 nStartHeadRow;
802 sal_uInt16 nEndHeadRow;
804 if (nStartHeadRow == 0)
808 SAL_WARN(
"lwp",
"truncating HeadingRow for fuzzing performance");
809 nEndHeadRow = nStartHeadRow + 128;
846 throw std::runtime_error(
"already added to a container");
860 sal_uInt16 nContentRow;
866 ConvertTable(pTmpTable,nStartHeadRow,nEndHeadRow,0,nCol);
868 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
869 std::vector<sal_uInt8> CellMark(nRowNum);
873 XFRow* pXFRow = pTmpTable->GetRow(1);
874 pXFTable->AddHeaderRow(pXFRow);
875 pTmpTable->RemoveRow(1);
876 nContentRow = nEndHeadRow;
881 const bool bFindFlag =
FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
885 SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
886 nContentRow = nEndHeadRow;
890 XFRow* pXFRow = pTmpTable->GetRow(1);
891 pXFTable->AddHeaderRow(pXFRow);
892 pTmpTable->RemoveRow(1);
896 SAL_WARN(
"lwp",
"row 0 is unknown");
900 nContentRow = iter->second->GetCurMaxSpannedRows(0,nCol);
920 std::unique_ptr<XFRowStyle> xRowStyle(
new XFRowStyle);
923 throw std::runtime_error(
"missing row");
930 *xRowStyle = *pTempRowStyle;
932 for (
i=1;
i<=nRowNum;
i++)
943 xRowStyle->SetRowHeight(
static_cast<float>(fHeight));
945 xXFRow->SetStyleName(pXFStyleManager->
AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
954 for (
i=1;
i<=nRowNum;
i++)
961 xNewCell = pOldRow->
GetCell(j);
962 xNewRow->AddCell(xNewCell);
964 xSubTable1->AddRow(xNewRow);
968 xXFCell1->Add(xSubTable1.get());
969 xXFCell1->SetColumnSpaned(nFirstColSpann);
970 xXFRow->AddCell(xXFCell1);
972 for (
i=1;
i<=nRowNum;
i++)
977 for(sal_Int32 j=pCellMark[
i]+1;j<=pOldRow->
GetCellCount();j++)
979 xNewCell = pOldRow->
GetCell(j);
980 xNewRow->AddCell(xNewCell);
982 xSubTable2->AddRow(xNewRow);
986 xXFCell2->Add(xSubTable2.get());
987 xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
988 xXFRow->AddCell(xXFCell2);
990 pXFTable->AddHeaderRow(xXFRow.get());
993 for (
i=1;
i<=nRowNum;
i++)
1011 bool bFindFlag =
false;
1016 sal_uInt16 nRowLoop;
1020 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1023 for(
sal_uInt8 nCellLoop=1; nCellLoop<
i+1; nCellLoop++)
1025 pTmpRow = pXFTable->
GetRow(nRowLoop);
1032 if (nColSpan > nMaxColSpan)
1033 nMaxColSpan = nColSpan;
1034 rCellMark.at(nRowLoop) = 0;
1038 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1040 pTmpRow = pXFTable->
GetRow(nRowLoop);
1042 sal_Int32 nCellMark = 0;
1043 for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->
GetCellCount(); nCellLoop++)
1048 if (
nCount == nMaxColSpan)
1050 nCellMark = nCellLoop;
1057 rCellMark.at(nRowLoop) = nCellMark;
1059 for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1061 if (rCellMark.at(nRowLoop) == 0)
1064 if (nRowLoop == nRowNum+1)
1097 SAL_WARN(
"lwp",
"already trying to convert this range");
1106 std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1108 for (sal_uInt16
i=nStartRow;
i<nEndRow;)
1126 pRow->
ConvertRow(pXFTable,nStartCol,nEndCol);
1145 if( !pFoundry )
return;
1157 bool bAlreadySeenTable = !aTableSeen.
insert(pTableRange).second;
1158 if (bAlreadySeenTable)
1159 throw std::runtime_error(
"loop in conversion");
1161 if (aID == aTableID)
1165 pTableRange = pTableRange->
GetNext();
1186 bool bAlreadySeenOuter = !aOuterSeen.
insert(pRowList).second;
1187 if (bAlreadySeenOuter)
1188 throw std::runtime_error(
"loop in conversion");
1189 sal_uInt16 nRowID = pRowList->
GetRowID();
1196 bool bAlreadySeen = !aSeen.
insert(pCellList).second;
1198 throw std::runtime_error(
"loop in conversion");
1206 throw std::runtime_error(
"Hidden cell would not be in cellsmap");
1209 pCellList->
Convert(pCell,
this);
1222 SAL_WARN(
"lwp",
"bad PutCellVals");
1247 bool bColorMod =
false;
1250 if (!sNumfmt.isEmpty())
1254 if ( aColor != aNullColor )
1262 std::unique_ptr<XFParaStyle> xOverStyle(
new XFParaStyle);
1266 *xOverStyle = *pStyle;
1277 XFColor aColor = xFont->GetColor();
1278 if (aColor == aNullColor)
1282 pNewFont->SetColor(aColor);
1283 xOverStyle->SetFont(pNewFont);
1288 xOverStyle->SetStyleName(
"");
1308 for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1313 while (pColumnLayout)
1315 if (pColumnLayout->
GetColumnID() == (iLoop+nStartCol))
1317 pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->
GetStyleName());
1320 pColID = &pColumnLayout->
GetNext();
1338 sal_uInt16 nRow = pTable->
GetRow();
1340 sal_uInt16 nEffectRows;
1341 std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1342 std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1346 for (sal_uInt16
i=0;
i<nRow; )
1354 pRowLayout= iter1->second;
1364 for (sal_uInt16 j =
i+1; j<nEffectRows; j++)
1369 pEffectRow = iter2->second;
1394 for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1410 xRow->AddCell(xCell);
1413 pXFTable->AddRow(xRow);
1425 m_CellsMap.insert({{nRow1, nCol1}, {nRow2, nCol2}}, pXFCell);
1436 auto results =
m_CellsMap.search({{nRow, nCol}, {nRow, nCol}}, rt_type::search_type::overlap);
1437 if (results.begin() == results.end())
1440 return std::prev(results.end())->GetCell();
1455 pRowID = &pRowLayout->
GetNext();
1487 std::unique_ptr<XFColStyle> xColStyle(
new XFColStyle);
1488 xColStyle->SetWidth(
static_cast<float>(dCalculatedWidth));
virtual OUString GetStyleName()=0
@descr: return the style name.
const OUString & str() const
const OUString & GetNumfmtName() const
rtl::Reference< XFCell > DoConvertCell(LwpObjectID aTableID, sal_uInt16 nRow, sal_uInt16 nCol)
sal_uInt8 GetColID() const
sal_uInt16 GetRowID() const
sal_uInt8 GetColumnID() const
LwpObjectID const & GetNextID()
virtual void Convert(XFCell *pCell, LwpTableLayout *pCellsMap=nullptr)
const LwpObjectID & GetFolderID() const
lwpcolor class (red, green, blue, extra)
bool IsValidColor() const
sal_uInt32 To24Color()
@descr return the BGR format
bool IsJustifiable() const
LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
double GetWidth() override
sal_uInt32 GetColumnID() const
virtual ~LwpColumnLayout() override
void Read() override
@descr Read name of LwpDLNFVList from object stream
LwpObjectID & GetParent()
LwpObjectID & GetChildHead()
LwpAtomHolder & GetName()
LwpObjectID & GetChildTail()
VO_HEADHOLDER, LwpDLVListHeadHolder, contains an id to the head of LwpDLVList.
LwpObjectID & GetHeadID()
LwpObjectID & GetPrevious()
LwpObjectID const & GetChildHeadID()
LwpNumberManager & GetNumberManager()
For register frame style and parse frame.
XFStyleManager * GetXFStyleManager()
static LwpGlobalMgr * GetInstance(LwpSvStream *pSvStream=nullptr)
void Read() override
@descr Read name of LwpDLNFVList from object stream
XFShadow * GetXFShadow()
@descr: create xfshadow
virtual rtl::Reference< LwpVirtualLayout > GetContainerLayout() override
@descr get the layout that containers the current frame layout
sal_Int32 GetMinimumWidth()
LwpObjectID & GetContent()
std::unique_ptr< XFBGImage > GetXFBGImage()
@descr: Create and return xfbgimage object for watermark
virtual double GetWidth() override
@descr: Get layout height
std::unique_ptr< XFBGImage > GetFillPattern()
@descr: Get the fill pattern style.
bool IsPatternFill()
@descr: Whether the fill is pattern fill or not
LwpColor * GetBackColor()
@descr: Get background color.
LwpLayoutGeometry * GetGeometry()
@descr: Get the geometry of current layout
bool IsSizeRightToContent()
const LwpObjectID & GetTableRangeID() const
void ReadIndexed(LwpSvStream *pStrm)
@descr Read object id with indexed format from stream if index>0, lowid is get from time table per th...
rtl::Reference< LwpObject > obj(VO_TYPE tag=VO_INVALID) const
@descr get object from object factory per the object id
stream class for LwpObject body data provide stream like interface to read object data
sal_uInt16 QuickReaduInt16(bool *pFailure=nullptr)
@descr Quick read sal_uInt32
void SkipExtra()
@descr skip extra bytes
sal_Int32 QuickReadInt32()
@descr Quick read sal_Int32
void SetFoundry(LwpFoundry *pFoundry)
virtual void RegisterStyle()
@descr default register style function
std::unique_ptr< LwpObjectStream > m_pObjStrm
LwpFoundry * GetFoundry()
LwpObjectID & GetObjectID()
LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
void Read() override
read table layout
virtual ~LwpParallelColumnsLayout() override
virtual sal_uInt8 GetRelativeType() override
@descr: Get relative type
void Read() override
@descr Read name of LwpDLNFVList from object stream
void CollectMergeInfo()
collect merge cell info when register row styles
void SetRowMap()
register row style
void ConvertRow(rtl::Reference< XFTable > const &pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
Parse rows with connect cell.
sal_uInt16 GetRowID() const
void ConvertCommonRow(rtl::Reference< XFTable > const &pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
convert row with rowlayout,but no merge cells
void SetCellSplit(sal_uInt16 nEffectRows)
split merge cells in this row
bool GetMergeCellFlag() const
check if the row has merge cell
virtual void RegisterStyle() override
register row style
sal_uInt16 GetCurMaxSpannedRows(sal_uInt8 nStartCol, sal_uInt8 nEndCol)
get max spanned row numbers in a given column range
sal_uInt16 GetRowID() const
LwpObjectID const & GetChildHeadID()
LwpObjectID const & GetNextID()
void Read() override
Read super table layout record.
LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
virtual ~LwpSuperGlossaryLayout() override
void Read() override
Read super table layout record.
virtual ~LwpSuperParallelColumnLayout() override
LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
VO_SUPERTABLELAYOUT object.
void ApplyBackColor(XFTableStyle *pTableStyle)
Apply back color to table.
void ApplyBackGround(XFTableStyle *pTableStyle)
Apply background to table style.
void Read() override
Read super table layout record.
double GetWidth() override
Get width of frame outside table.
void RegisterNewStyle()
Register super table layout style.
void RegisterFrameStyle()
register frame style
bool IsSizeRightToContent()
Judge whether table size is according to content, borrowed from Word Pro code.
LwpSuperTableLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
void ApplyPatternFill(XFTableStyle *pTableStyle)
Apply pattern fill to table style.
void ApplyShadow(XFTableStyle *pTableStyle)
Apply shadow to table.
bool IsJustifiable()
Judge whether table is justifiable, borrowed from Word Pro code.
LwpTableHeadingLayout * GetTableHeadingLayout()
Get effective heading table layout, the one just before table layout is the only one which is effecti...
void XFConvert(XFContentContainer *pCont) override
Add table to container.
std::unique_ptr< LwpFrame > m_pFrame
void ApplyWatermark(XFTableStyle *pTableStyle)
Apply watermark to table.
double GetTableWidth()
Get width of table.
LwpTableLayout * GetTableLayout()
Get child table layout.
virtual void XFConvertFrame(XFContentContainer *pCont, sal_Int32 nStart=0, sal_Int32 nEnd=0, bool bAll=false) override
convert frame which anchor to page
virtual ~LwpSuperTableLayout() override
void ApplyAlignment(XFTableStyle *pTableStyle)
Apply alignment to table.
encapsulate XInputStream to provide SvStream like interfaces
VO_TABLEHEADINGLAYOUT object.
void Read() override
read table heading layout
virtual ~LwpTableHeadingLayout() override
void GetStartEndRow(sal_uInt16 &nStartRow, sal_uInt16 &nEndRow)
get start and end row number of table heading
LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
VO_TABLELAYOUT object and functions for registering styles and converting tables.
void PutCellVals(LwpFoundry *pFoundry, LwpObjectID aTableID)
apply numeric value and formula to cell
LwpCellLayout * GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
Get neighbour cell by specifying ROW+COL.
std::vector< LwpCellLayout * > m_WordProCellsMap
std::map< sal_uInt16, LwpRowLayout * > m_RowsMap
void SplitConflictCells()
split conflict merged cells
LwpSuperTableLayout * GetSuperTableLayout()
Get parent super table layout of table layout.
sal_uInt16 ConvertHeadingRow(rtl::Reference< XFTable > const &pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
convert heading row
std::vector< LwpColumnLayout * > m_aColumns
OUString m_DefaultColumnStyleName
void RegisterRows()
register all row styles
LwpRowLayout * GetRowLayout(sal_uInt16 nRow)
@descr Get row layout by row id
static bool FindSplitColMark(XFTable *pXFTable, std::vector< sal_uInt8 > &rCellMark, sal_uInt8 &nMaxColSpan)
find if the heading rows can be split to 2 cells
void ConvertTable(rtl::Reference< XFTable > const &pXFTable, sal_uInt16 nStartRow, sal_uInt16 nEndRow, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
convert word pro table to SODC table
LwpObjectID & GetColumnLayoutHead()
LwpObjectID m_ColumnLayout
void PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1.
void SplitRowToCells(XFTable *pTmpTable, rtl::Reference< XFTable > const &pXFTable, sal_uInt8 nFirstColSpann, const sal_uInt8 *pCellMark)
rtl::Reference< XFTable > m_pXFTable
void ConvertDefaultRow(rtl::Reference< XFTable > const &pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol, sal_uInt16 nRowID)
add default row which are missing in the file
void ParseTable()
read table layout
void RegisterColumns()
analyze all columns to get whole table width and width of all columns
void RegisterStyle() override
register table style, if needed, including frame style
LwpCellLayout * m_pDefaultCellLayout
void TraverseTable()
traverse all table cells
LwpObjectID * SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
search the cell map
void SetCellsMap(sal_uInt16 nRow1, sal_uInt8 nCol1, sal_uInt16 nRow2, sal_uInt8 nCol2, XFCell *pXFCell)
set cell map info
OUString m_DefaultRowStyleName
LwpTable * GetTable()
Get table pointer.
LwpTableLayout(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
OUString GetColumnWidth(sal_uInt16 nCol)
Get column style name by column ID.
void XFConvert(XFContentContainer *pCont) override
Convert table.
std::vector< TableConvertAttempt > m_aConvertingStack
XFCell * GetCellsMap(sal_uInt16 nRow, sal_uInt8 nCol)
get cell map info
void Read() override
read table layout
void ConvertColumn(rtl::Reference< XFTable > const &pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
Parse all cols of table.
LwpTableRange * GetNext()
const LwpObjectID & GetTableID() const
const LwpObjectID & GetCellRangeID() const
sal_uInt16 GetRow() const
sal_uInt16 GetColumn() const
LwpObjectID & GetDefaultCellStyle()
void Read() override
@descr Read name of LwpDLNFVList from object stream
bool IsRelativeAnchored()
@descr: whether it is relative anchored layout
const OUString & GetStyleName() const
double GetMarginsValue(sal_uInt8 nWhichSide)
bool IsCell()
@descr: Whether this layout is cell layout or not
virtual LWP_LAYOUT_TYPE GetLayoutType()
@ LWP_TABLE_HEADING_LAYOUT
@descr Table cell object.
sal_Int32 GetColSpaned() const
@descr return cell column span property.
Column style, it has only one property-the column width.
virtual void Add(XFContent *pContent)
@descr Add content.
rtl::Reference< XFContent > FindFirstContent(enumXFContent type)
@descr helper function, find first content by type.
const OUString & GetStyleName() const
: return the style name.
virtual void SetStyleName(const OUString &style)
: All content except XFTextContent can have a style.
Floating frame on any page.
@descr The font struct of openoffice xml filter.
Style for all frame objects.
Base class for all frame object,include drawing,image,text-box.
const XFColor & GetColor() const
Style object for aragraph.
bool GetNumberRight() const
void SetAlignType(enumXFAlignType eAlign)
@descr Set alignment property of the paragraph.
Paragraph object for SODC.
void SetMinRowHeight(double height)
XFCell * GetCell(sal_Int32 col) const
sal_Int32 GetCellCount() const
Style manager for the filter.
IXFStyle * FindStyle(std::u16string_view name)
IXFStyleRet AddStyle(std::unique_ptr< IXFStyle > pStyle)
XFParaStyle * FindParaStyle(std::u16string_view name)
void SetBackColor(XFColor const &color)
void SetAlign(enumXFAlignType eAlign, double offset=0)
void SetShadow(enumXFShadowPos pos, double offset, XFColor color)
void SetBackImage(std::unique_ptr< XFBGImage > &rImage)
XFRow * GetRow(sal_Int32 row)
void RemoveRow(sal_uInt16 row)
sal_Int32 GetColumnCount()
std::pair< const_iterator, bool > insert(Value &&x)
#define SAL_WARN(area, stream)
const sal_uInt8 MARGIN_RIGHT
const sal_uInt8 MARGIN_LEFT
For LWP filter architecture prototype - row layouts.
For LWP filter architecture prototype - table object.
static bool operator==(const TableConvertAttempt &a, const TableConvertAttempt &b)
For LWP filter architecture prototype - table layouts.
For LWP filter architecture prototype - table object.
constexpr OUStringLiteral first