| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ |
| |
| |
| #include <svl/itemiter.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/outdev.hxx> |
| |
| #include <toolkit/helper/vclunohelper.hxx> |
| #include <com/sun/star/form/XFormsSupplier.hpp> |
| #include <com/sun/star/form/XForm.hpp> |
| #include <com/sun/star/form/XImageProducerSupplier.hpp> |
| #include <com/sun/star/form/XFormController.hpp> |
| #include <com/sun/star/frame/XStorable.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/drawing/XConnectableShape.hpp> |
| #include <com/sun/star/drawing/XConnectorShape.hpp> |
| #include <com/sun/star/drawing/XShape.hpp> |
| #include <com/sun/star/drawing/XControlShape.hpp> |
| #include <com/sun/star/drawing/XShapeAligner.hpp> |
| #include <com/sun/star/drawing/XShapeGroup.hpp> |
| #include <com/sun/star/drawing/XUniversalShapeDescriptor.hpp> |
| #include <com/sun/star/drawing/XShapeMirror.hpp> |
| #include <com/sun/star/drawing/XShapeArranger.hpp> |
| #include <com/sun/star/drawing/XDrawPage.hpp> |
| #include <com/sun/star/drawing/XDrawPageSupplier.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
| #include <com/sun/star/container/XIndexContainer.hpp> |
| #include <com/sun/star/text/VertOrientation.hpp> |
| #include <com/sun/star/text/TextContentAnchorType.hpp> |
| #include <comphelper/extract.hxx> |
| #include <comphelper/stlunosequence.hxx> |
| #include <com/sun/star/beans/XPropertyContainer.hpp> |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| |
| #include <algorithm> |
| #include <functional> |
| #include <hintids.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/wghtitem.hxx> |
| #include <editeng/crsditem.hxx> |
| #include <editeng/udlnitem.hxx> |
| #include <editeng/postitem.hxx> |
| #include <filter/msfilter/msocximex.hxx> |
| #include <errhdl.hxx> |
| #include <unotextrange.hxx> |
| #include <doc.hxx> |
| #include <docary.hxx> |
| #include <docsh.hxx> |
| #include <numrule.hxx> |
| #include <paratr.hxx> |
| #include <charatr.hxx> |
| #include <charfmt.hxx> |
| #include <ndtxt.hxx> |
| #include <expfld.hxx> |
| #include <fmtfld.hxx> |
| #include <flddropdown.hxx> |
| #include "writerhelper.hxx" |
| #include "writerwordglue.hxx" |
| #include "ww8par.hxx" |
| #include "ww8par2.hxx" // wg. Listen-Attributen in Styles |
| |
| #include <IMark.hxx> |
| #include <unotools/fltrcfg.hxx> |
| #include <xmloff/odffields.hxx> |
| |
| #include <stdio.h> |
| #include <algorithm> |
| |
| using namespace com::sun::star; |
| using namespace sw::util; |
| using namespace sw::types; |
| using namespace sw::mark; |
| |
| //----------------------------------------- |
| // UNO-Controls |
| //----------------------------------------- |
| |
| //cmc, OCX i.e. word 97 form controls |
| eF_ResT SwWW8ImplReader::Read_F_OCX( WW8FieldDesc*, String& ) |
| { |
| if( bObj && nPicLocFc ) |
| nObjLocFc = nPicLocFc; |
| bEmbeddObj = true; |
| return FLD_TEXT; |
| } |
| |
| eF_ResT SwWW8ImplReader::Read_F_FormTextBox( WW8FieldDesc* pF, String& rStr ) |
| { |
| WW8FormulaEditBox aFormula(*this); |
| |
| if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) { |
| ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_EDIT); |
| } |
| |
| /* #80205# |
| Here we have a small complication. This formula control contains |
| the default text that is displayed if you edit the form field in |
| the "default text" area. But MSOffice does not display that |
| information, instead it display the result of the field, |
| MSOffice just uses the default text of the control as its |
| initial value for the displayed default text. So we will swap in |
| the field result into the formula here in place of the default |
| text. |
| */ |
| |
| const SvtFilterOptions* pOpt = SvtFilterOptions::Get(); |
| const sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields()); |
| |
| if (!bUseEnhFields) |
| { |
| aFormula.sDefault = GetFieldResult(pF); |
| |
| #if 0 // why not? (flr) |
| //substituting Unicode spacing 0x2002 with double space for layout |
| aFormula.sDefault.SearchAndReplaceAll( |
| String(static_cast< sal_Unicode >(0x2002)), |
| CREATE_CONST_ASC(" ")); |
| #endif |
| |
| SwInputField aFld( |
| static_cast<SwInputFieldType*>(rDoc.GetSysFldType( RES_INPUTFLD )), |
| aFormula.sDefault, |
| aFormula.sTitle, |
| INP_TXT, |
| 0 ); |
| aFld.SetHelp(aFormula.sHelp); |
| aFld.SetToolTip(aFormula.sToolTip); |
| |
| rDoc.InsertPoolItem( *pPaM, SwFmtFld(aFld), 0 ); |
| return FLD_OK; |
| } |
| else |
| { |
| WW8PLCFx_Book* pB = pPlcxMan->GetBook(); |
| String aBookmarkName; |
| if (pB!=NULL) { |
| WW8_CP currentCP=pF->nSCode; |
| WW8_CP currentLen=pF->nLen; |
| |
| sal_uInt16 bkmFindIdx; |
| String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx); |
| |
| if (aBookmarkFind.Len()>0) { |
| pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark bookmark as consumed, such that tl'll not get inserted as a "normal" bookmark again |
| if (aBookmarkFind.Len()>0) { |
| aBookmarkName=aBookmarkFind; |
| } |
| } |
| } |
| |
| if (pB!=NULL && aBookmarkName.Len()==0) { |
| aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle); |
| } |
| |
| |
| if (aBookmarkName.Len()>0) { |
| maFieldStack.back().SetBookmarkName(aBookmarkName); |
| maFieldStack.back().SetBookmarkType(::rtl::OUString::createFromAscii(ODF_FORMTEXT)); |
| maFieldStack.back().getParameters()[::rtl::OUString::createFromAscii("Description")] = uno::makeAny(::rtl::OUString(aFormula.sToolTip)); |
| maFieldStack.back().getParameters()[::rtl::OUString::createFromAscii("Name")] = uno::makeAny(::rtl::OUString(aFormula.sTitle)); |
| } |
| return FLD_TEXT; |
| } |
| } |
| |
| eF_ResT SwWW8ImplReader::Read_F_FormCheckBox( WW8FieldDesc* pF, String& rStr ) |
| { |
| WW8FormulaCheckBox aFormula(*this); |
| |
| if (!pFormImpl) |
| pFormImpl = new SwMSConvertControls(mpDocShell, pPaM); |
| |
| if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) |
| ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_CHECKBOX); |
| const SvtFilterOptions* pOpt = SvtFilterOptions::Get(); |
| sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields()); |
| |
| if (!bUseEnhFields) |
| { |
| pFormImpl->InsertFormula(aFormula); |
| return FLD_OK; |
| } |
| else |
| { |
| String aBookmarkName; |
| WW8PLCFx_Book* pB = pPlcxMan->GetBook(); |
| if (pB!=NULL) { |
| WW8_CP currentCP=pF->nSCode; |
| WW8_CP currentLen=pF->nLen; |
| |
| sal_uInt16 bkmFindIdx; |
| String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx); |
| |
| if (aBookmarkFind.Len()>0) { |
| pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field |
| if (aBookmarkFind.Len()>0) { |
| aBookmarkName=aBookmarkFind; |
| } |
| } |
| } |
| |
| if (pB!=NULL && aBookmarkName.Len()==0) { |
| aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle); |
| } |
| |
| if (aBookmarkName.Len()>0) |
| { |
| IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( ); |
| IFieldmark* pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeNoTextFieldBookmark( |
| *pPaM, aBookmarkName, |
| rtl::OUString::createFromAscii( ODF_FORMCHECKBOX ) ) ); |
| ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?"); |
| if (pFieldmark!=NULL) { |
| IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters(); |
| ICheckboxFieldmark* pCheckboxFm = dynamic_cast<ICheckboxFieldmark*>(pFieldmark); |
| (*pParameters)[::rtl::OUString::createFromAscii(ODF_FORMCHECKBOX_NAME)] = uno::makeAny(::rtl::OUString(aFormula.sTitle)); |
| (*pParameters)[::rtl::OUString::createFromAscii(ODF_FORMCHECKBOX_HELPTEXT)] = uno::makeAny(::rtl::OUString(aFormula.sToolTip)); |
| if(pCheckboxFm) |
| pCheckboxFm->SetChecked(aFormula.nChecked); |
| // set field data here... |
| } |
| } |
| return FLD_OK; |
| } |
| } |
| |
| eF_ResT SwWW8ImplReader::Read_F_FormListBox( WW8FieldDesc* pF, String& rStr) |
| { |
| WW8FormulaListBox aFormula(*this); |
| |
| if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) |
| ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_DROPDOWN); |
| |
| const SvtFilterOptions* pOpt = SvtFilterOptions::Get(); |
| sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields()); |
| |
| if (!bUseEnhFields) |
| { |
| SwDropDownField aFld((SwDropDownFieldType*)rDoc.GetSysFldType(RES_DROPDOWN)); |
| |
| aFld.SetName(aFormula.sTitle); |
| aFld.SetHelp(aFormula.sHelp); |
| aFld.SetToolTip(aFormula.sToolTip); |
| |
| if (!aFormula.maListEntries.empty()) |
| { |
| aFld.SetItems(aFormula.maListEntries); |
| int nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0; |
| aFld.SetSelectedItem(aFormula.maListEntries[nIndex]); |
| } |
| |
| rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0); |
| return FLD_OK; |
| } |
| else |
| { |
| // TODO: review me |
| String aBookmarkName; |
| WW8PLCFx_Book* pB = pPlcxMan->GetBook(); |
| if (pB!=NULL) |
| { |
| WW8_CP currentCP=pF->nSCode; |
| WW8_CP currentLen=pF->nLen; |
| |
| sal_uInt16 bkmFindIdx; |
| String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx); |
| |
| if (aBookmarkFind.Len()>0) |
| { |
| pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field |
| if (aBookmarkFind.Len()>0) |
| aBookmarkName=aBookmarkFind; |
| } |
| } |
| |
| if (pB!=NULL && aBookmarkName.Len()==0) |
| aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle); |
| |
| if (aBookmarkName.Len()>0) |
| { |
| IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( ); |
| IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( |
| pMarksAccess->makeNoTextFieldBookmark( *pPaM, aBookmarkName, |
| ::rtl::OUString::createFromAscii( ODF_FORMDROPDOWN ) ) ); |
| ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?"); |
| if ( pFieldmark != NULL ) |
| { |
| uno::Sequence< ::rtl::OUString > vListEntries(aFormula.maListEntries.size()); |
| ::std::copy(aFormula.maListEntries.begin(), aFormula.maListEntries.end(), ::comphelper::stl_begin(vListEntries)); |
| (*pFieldmark->GetParameters())[::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_LISTENTRY)] = uno::makeAny(vListEntries); |
| sal_Int32 nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0; |
| (*pFieldmark->GetParameters())[::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_RESULT)] = uno::makeAny(nIndex); |
| // set field data here... |
| } |
| } |
| |
| return FLD_OK; |
| } |
| } |
| |
| void SwWW8ImplReader::DeleteFormImpl() |
| { |
| delete pFormImpl, pFormImpl = 0; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // WW8ListManager oeffentliche Methoden stehen ganz am Ende |
| //------------------------- ============ --------------- ============ -------- |
| |
| |
| |
| // Hilfs-Deklarationen /////////////////////////////////////////////////////// |
| // |
| // Style Id's for each level |
| typedef sal_uInt16 WW8aIdSty[WW8ListManager::nMaxLevel]; |
| // Zeichenattribute aus GrpprlChpx |
| typedef SfxItemSet* WW8aISet[WW8ListManager::nMaxLevel]; |
| // Zeichen Style Pointer |
| typedef SwCharFmt* WW8aCFmt[WW8ListManager::nMaxLevel]; |
| |
| struct WW8LST // nur DIE Eintraege, die WIR benoetigen! |
| { |
| WW8aIdSty aIdSty; // Style Id's for each level, |
| // nIStDNil if no style linked |
| sal_uInt32 nIdLst; // Unique List ID |
| sal_uInt32 nTplC; // Unique template code - Was ist das bloss? |
| sal_uInt8 bSimpleList:1; // Flag: Liste hat nur EINEN Level |
| sal_uInt8 bRestartHdn:1; // WW6-Kompatibilitaets-Flag: |
| // true if the list should start numbering over |
| }; // at the beginning of each section |
| |
| struct WW8LFO // nur DIE Eintraege, die WIR benoetigen! |
| { |
| SwNumRule* pNumRule; // Parent NumRule |
| sal_uInt32 nIdLst; // Unique List ID |
| sal_uInt8 nLfoLvl; // count of levels whose format is overridden |
| bool bSimpleList; |
| }; |
| |
| struct WW8LVL // nur DIE Eintraege, die WIR benoetigen! |
| { |
| long nStartAt; // start at value for this value |
| long nV6DxaSpace;// Ver6-Compatible: min Space between Num anf text::Paragraph |
| long nV6Indent; // Ver6-Compatible: Breite des Prefix Textes; ggfs. zur |
| // Definition d. Erstzl.einzug nutzen! |
| // Absatzattribute aus GrpprlPapx |
| sal_uInt16 nDxaLeft; // linker Einzug |
| short nDxaLeft1; // Erstzeilen-Einzug |
| |
| sal_uInt8 nNFC; // number format code |
| // Offset der Feldkodes im Num-X-String |
| sal_uInt8 aOfsNumsXCH[WW8ListManager::nMaxLevel]; |
| sal_uInt8 nLenGrpprlChpx; // length, in bytes, of the LVL's grpprlChpx |
| sal_uInt8 nLenGrpprlPapx; // length, in bytes, of the LVL's grpprlPapx |
| sal_uInt8 nAlign: 2; // alignment (left, right, centered) of the number |
| sal_uInt8 bLegal: 1; // egal |
| sal_uInt8 bNoRest:1; // egal |
| sal_uInt8 bV6Prev:1; // Ver6-Compatible: number will include previous levels |
| sal_uInt8 bV6PrSp:1; // Ver6-Compatible: egal |
| sal_uInt8 bV6: 1; // falls true , beachte die V6-Compatible Eintraege! |
| sal_uInt8 bDummy: 1; // (macht das Byte voll) |
| |
| }; |
| |
| struct WW8LFOLVL |
| { |
| long nStartAt; // start-at value if bFormat==false and bStartAt == true |
| // (if bFormat==true, the start-at is stored in the LVL) |
| sal_uInt8 nLevel; // the level to be overridden |
| // dieses Byte ist _absichtlich_ nicht in das folgende Byte hineingepackt !! |
| // (siehe Kommentar unten bei struct WW8LFOInfo) |
| |
| sal_uInt8 bStartAt :1; // true if the start-at value is overridden |
| sal_uInt8 bFormat :1; // true if the formatting is overriden |
| |
| WW8LFOLVL() : |
| nStartAt(1), nLevel(0), bStartAt(1), bFormat(0) {} |
| }; |
| |
| // in den ListenInfos zu speichernde Daten /////////////////////////////////// |
| // |
| struct WW8LSTInfo // sortiert nach nIdLst (in WW8 verwendete Listen-Id) |
| { |
| std::vector<ww::bytes> maParaSprms; |
| WW8aIdSty aIdSty; // Style Id's for each level |
| WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx |
| WW8aCFmt aCharFmt; // Zeichen Style Pointer |
| |
| SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer |
| sal_uInt32 nIdLst; // WW8Id dieser Liste |
| sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet |
| sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird, |
| // oder beim Reader-Ende geloescht werden sollte |
| |
| WW8LSTInfo(SwNumRule* pNumRule_, WW8LST& aLST) |
| : pNumRule(pNumRule_), nIdLst(aLST.nIdLst), |
| bSimpleList(aLST.bSimpleList), bUsedInDoc(0) |
| { |
| memcpy( aIdSty, aLST.aIdSty, sizeof( aIdSty )); |
| memset(&aItemSet, 0, sizeof( aItemSet )); |
| memset(&aCharFmt, 0, sizeof( aCharFmt )); |
| } |
| |
| }; |
| |
| // in den ListenFormatOverrideInfos zu speichernde Daten ///////////////////// |
| // |
| struct WW8LFOInfo // unsortiert, d.h. Reihenfolge genau wie im WW8 Stream |
| { |
| std::vector<ww::bytes> maParaSprms; |
| std::vector<WW8LFOLVL> maOverrides; |
| SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer |
| // entweder: Liste in LSTInfos oder eigene Liste |
| // (im Ctor erstmal die aus den LSTInfos merken) |
| |
| sal_uInt32 nIdLst; // WW8-Id der betreffenden Liste |
| sal_uInt8 nLfoLvl; // count of levels whose format is overridden |
| // Ja, ich natuerlich koennten wir nLfoLvl (mittels :4) noch in das folgende |
| // Byte mit hineinpacken, doch waere das eine ziemliche Fehlerquelle, |
| // an dem Tag, wo MS ihr Listenformat auf mehr als 15 Level aufbohren. |
| |
| sal_uInt8 bOverride :1;// Flag, ob die NumRule nicht in maLSTInfos steht, |
| // sondern fuer pLFOInfos NEU angelegt wurde |
| sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet |
| sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird, |
| // oder beim Reader-Ende geloescht werden sollte |
| sal_uInt8 bLSTbUIDSet :1;// Flag, ob bUsedInDoc in maLSTInfos gesetzt wurde, |
| // und nicht nochmals gesetzt zu werden braucht |
| WW8LFOInfo(const WW8LFO& rLFO); |
| }; |
| |
| WW8LFOInfo::WW8LFOInfo(const WW8LFO& rLFO) |
| : maParaSprms(WW8ListManager::nMaxLevel) |
| , maOverrides(WW8ListManager::nMaxLevel) |
| , pNumRule(rLFO.pNumRule) |
| , nIdLst(rLFO.nIdLst) |
| , nLfoLvl(rLFO.nLfoLvl) |
| , bOverride(rLFO.nLfoLvl ? true : false) |
| , bSimpleList(rLFO.bSimpleList) |
| , bUsedInDoc(0) |
| , bLSTbUIDSet(0) |
| { |
| } |
| |
| SV_IMPL_PTRARR( WW8LFOInfos, WW8LFOInfo_Ptr ); |
| |
| |
| // Hilfs-Methoden //////////////////////////////////////////////////////////// |
| // |
| |
| // finden der Sprm-Parameter-Daten, falls Sprm im Grpprl enthalten |
| sal_uInt8* WW8ListManager::GrpprlHasSprm(sal_uInt16 nId, sal_uInt8& rSprms, |
| sal_uInt8 nLen) |
| { |
| sal_uInt8* pSprms = &rSprms; |
| sal_uInt16 i=0; |
| while (i < nLen) |
| { |
| sal_uInt16 nAktId = maSprmParser.GetSprmId(pSprms); |
| if( nAktId == nId ) // Sprm found |
| return pSprms + maSprmParser.DistanceToData(nId); |
| |
| // gib Zeiger auf Daten |
| sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSprms); |
| i = i + x; |
| pSprms += x; |
| } |
| return 0; // Sprm not found |
| } |
| |
| class ListWithId : public std::unary_function<const WW8LSTInfo *, bool> |
| { |
| private: |
| sal_uInt32 mnIdLst; |
| public: |
| explicit ListWithId(sal_uInt32 nIdLst) : mnIdLst(nIdLst) {} |
| bool operator() (const WW8LSTInfo *pEntry) const |
| { return (pEntry->nIdLst == mnIdLst); } |
| }; |
| |
| // Zugriff ueber die List-Id des LST Eintrags |
| WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const |
| { |
| std::vector<WW8LSTInfo *>::const_iterator aResult = |
| std::find_if(maLSTInfos.begin(),maLSTInfos.end(),ListWithId(nIdLst)); |
| if (aResult == maLSTInfos.end()) |
| return 0; |
| return *aResult; |
| } |
| |
| void lcl_CopyGreaterEight(String &rDest, String &rSrc, |
| xub_StrLen nStart, xub_StrLen nLen = STRING_LEN) |
| { |
| if (nLen == STRING_LEN) |
| nLen = rSrc.Len(); |
| for (xub_StrLen nI = nStart; nI < nLen; ++nI) |
| { |
| sal_Unicode nChar = rSrc.GetChar(nI); |
| if (nChar > WW8ListManager::nMaxLevel) |
| rDest.Append(nChar); |
| } |
| } |
| |
| bool WW8ListManager::ReadLVL( |
| SwNumFmt& rNumFmt, |
| SfxItemSet*& rpItemSet, |
| sal_uInt16 nLevelStyle, |
| bool bSetStartNo, |
| std::deque< bool > &rNotReallyThere, |
| sal_uInt16 nLevel, |
| ww::bytes &rParaSprms ) |
| { |
| sal_uInt8 aBits1; |
| sal_uInt16 nStartNo = 0; // Start-Nr. fuer den Writer |
| SvxExtNumType eType; // Writer-Num-Typ |
| SvxAdjust eAdj; // Ausrichtung (Links/rechts/zent.) |
| sal_Unicode cBullet(0x2190); // default safe bullet |
| |
| sal_Unicode cGrfBulletCP(USHRT_MAX); |
| |
| String sPrefix; |
| String sPostfix; |
| WW8LVL aLVL; |
| // |
| // 1. LVLF einlesen |
| // |
| memset(&aLVL, 0, sizeof( aLVL )); |
| rSt >> aLVL.nStartAt; |
| rSt >> aLVL.nNFC; |
| rSt >> aBits1; |
| if( 0 != rSt.GetError() ) return false; |
| aLVL.nAlign = (aBits1 & 0x03); |
| if( aBits1 & 0x10 ) aLVL.bV6Prev = true; |
| if( aBits1 & 0x20 ) aLVL.bV6PrSp = true; |
| if( aBits1 & 0x40 ) aLVL.bV6 = true; |
| bool bLVLOkB = true; |
| sal_uInt8 nLevelB = 0; |
| for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB) |
| { |
| rSt >> aLVL.aOfsNumsXCH[ nLevelB ]; |
| if( 0 != rSt.GetError() ) |
| { |
| bLVLOkB = false; |
| break; |
| } |
| } |
| |
| if( !bLVLOkB ) |
| return false; |
| |
| sal_uInt8 ixchFollow; |
| rSt >> ixchFollow; |
| if (ixchFollow == 0) |
| rReader.maTracer.Log(sw::log::eTabInNumbering); |
| rSt >> aLVL.nV6DxaSpace; |
| rSt >> aLVL.nV6Indent; |
| rSt >> aLVL.nLenGrpprlChpx; |
| rSt >> aLVL.nLenGrpprlPapx; |
| rSt.SeekRel( 2 ); |
| if( 0 != rSt.GetError()) return false; |
| |
| // |
| // 2. ggfs. PAPx einlesen und nach Einzug-Werten suchen |
| // |
| // --> OD 2008-06-04 #i86652# - read tab setting |
| short nTabPos = 0; |
| // <-- |
| if( aLVL.nLenGrpprlPapx ) |
| { |
| sal_uInt8 aGrpprlPapx[ 255 ]; |
| if(aLVL.nLenGrpprlPapx != rSt.Read(&aGrpprlPapx,aLVL.nLenGrpprlPapx)) |
| return false; |
| // "sprmPDxaLeft" pap.dxaLeft;dxa;word; |
| sal_uInt8* pSprm; |
| if ( |
| (0 != (pSprm = GrpprlHasSprm(0x840F,aGrpprlPapx[0],aLVL.nLenGrpprlPapx))) || |
| (0 != (pSprm = GrpprlHasSprm(0x845E,aGrpprlPapx[0],aLVL.nLenGrpprlPapx))) |
| ) |
| { |
| sal_uInt8 *pBegin = pSprm-2; |
| for(int i=0;i<4;++i) |
| rParaSprms.push_back(*pBegin++); |
| short nDxaLeft = SVBT16ToShort( pSprm ); |
| aLVL.nDxaLeft = (0 < nDxaLeft) ? (sal_uInt16)nDxaLeft |
| : (sal_uInt16)(-nDxaLeft); |
| } |
| |
| // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word; |
| if ( |
| (0 != (pSprm = GrpprlHasSprm(0x8411,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) || |
| (0 != (pSprm = GrpprlHasSprm(0x8460,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) |
| ) |
| { |
| sal_uInt8 *pBegin = pSprm-2; |
| for(int i=0;i<4;++i) |
| rParaSprms.push_back(*pBegin++); |
| aLVL.nDxaLeft1 = SVBT16ToShort( pSprm ); |
| } |
| |
| // --> OD 2008-06-04 #i86652# - read tab setting |
| if(0 != (pSprm = GrpprlHasSprm(0xC615,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) |
| { |
| bool bDone = false; |
| if (*(pSprm-1) == 5) |
| { |
| if (*pSprm++ == 0) //nDel |
| { |
| if (*pSprm++ == 1) //nIns |
| { |
| nTabPos = SVBT16ToShort(pSprm); |
| pSprm+=2; |
| if (*pSprm == 6) //type |
| { |
| bDone = true; |
| } |
| } |
| } |
| } |
| ASSERT(bDone, "tab setting in numbering is " |
| "of unexpected configuration"); |
| } |
| if ( rNumFmt.GetPositionAndSpaceMode() == |
| SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) |
| { |
| // If there is a tab setting with a larger value, then use that. |
| // Ideally we would allow tabs to be used in numbering fields and set |
| // this on the containing paragraph which would make it actually work |
| // most of the time. |
| if ( nTabPos != 0 ) |
| { |
| const sal_uInt16 nDesired = aLVL.nDxaLeft + aLVL.nDxaLeft1; |
| |
| bool bDoAdjust = false; |
| if ( nDesired < aLVL.nDxaLeft ) |
| { |
| if ( nDesired < nTabPos && nTabPos < aLVL.nDxaLeft ) |
| { |
| bDoAdjust = true; |
| } |
| } |
| else |
| { |
| if ( aLVL.nDxaLeft < nTabPos && nTabPos < nDesired ) |
| { |
| bDoAdjust = true; |
| } |
| } |
| |
| if (bDoAdjust) |
| { |
| aLVL.nDxaLeft = (0 < nTabPos) |
| ? (sal_uInt16)nTabPos |
| : (sal_uInt16)(-nTabPos); |
| |
| aLVL.nDxaLeft1 = nDesired - aLVL.nDxaLeft; |
| } |
| } |
| } |
| // <-- |
| } |
| // |
| // 3. ggfs. CHPx einlesen und |
| // |
| sal_uInt16 nWitchPicIsBullet = USHRT_MAX; |
| bool bIsPicBullet = false; |
| |
| if( aLVL.nLenGrpprlChpx ) |
| { |
| sal_uInt8 aGrpprlChpx[ 255 ]; |
| memset(&aGrpprlChpx, 0, sizeof( aGrpprlChpx )); |
| if(aLVL.nLenGrpprlChpx != rSt.Read(&aGrpprlChpx, aLVL.nLenGrpprlChpx)) |
| return false; |
| |
| //For i120928,parse the graphic info of bullets |
| sal_uInt8 *pSprmWhichPis = GrpprlHasSprm(0x6887,aGrpprlChpx[0],aLVL.nLenGrpprlChpx); |
| sal_uInt8 *pSprmIsPicBullet = GrpprlHasSprm(0x4888,aGrpprlChpx[0],aLVL.nLenGrpprlChpx); |
| if (pSprmWhichPis) |
| { |
| nWitchPicIsBullet = *pSprmWhichPis; |
| } |
| if (pSprmIsPicBullet) |
| { |
| bIsPicBullet = (*pSprmIsPicBullet) & 0x0001; |
| } |
| |
| // neues ItemSet fuer die Zeichenattribute anlegen |
| rpItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN, |
| RES_CHRATR_END - 1 ); |
| |
| // Reader-ItemSet-Pointer darauf zeigen lassen |
| rReader.SetAktItemSet( rpItemSet ); |
| // Reader-Style auf den Style dieses Levels setzen |
| sal_uInt16 nOldColl = rReader.GetNAktColl(); |
| sal_uInt16 nNewColl = nLevelStyle; |
| if (ww::stiNil == nNewColl) |
| nNewColl = 0; |
| rReader.SetNAktColl( nNewColl ); |
| |
| // Nun den GrpprlChpx einfach durchnudeln: die Read_xy() Methoden |
| // in WW8PAR6.CXX rufen ganz normal ihr NewAttr() oder GetFmtAttr() |
| // und diese merken am besetzten Reader-ItemSet-Pointer, dass dieser |
| // spezielle ItemSet relevant ist - und nicht ein Stack oder Style! |
| sal_uInt16 nOldFlags1 = rReader.GetToggleAttrFlags(); |
| sal_uInt16 nOldFlags2 = rReader.GetToggleBiDiAttrFlags(); |
| short nLen = aLVL.nLenGrpprlChpx; |
| sal_uInt8* pSprms1 = &aGrpprlChpx[0]; |
| while (0 < nLen) |
| { |
| sal_uInt16 nL1 = rReader.ImportSprm( pSprms1 ); |
| nLen = nLen - nL1; |
| pSprms1 += nL1; |
| } |
| // Reader-ItemSet-Pointer und Reader-Style zuruecksetzen |
| rReader.SetAktItemSet( 0 ); |
| rReader.SetNAktColl( nOldColl ); |
| rReader.SetToggleAttrFlags(nOldFlags1); |
| rReader.SetToggleBiDiAttrFlags(nOldFlags2); |
| } |
| // |
| // 4. den Nummerierungsstring einlesen: ergibt Prefix und Postfix |
| // |
| String sNumString(WW8Read_xstz(rSt, 0, false)); |
| |
| // |
| // 5. gelesene Werte in Writer Syntax umwandeln |
| // |
| if( 0 <= aLVL.nStartAt ) |
| nStartNo = (sal_uInt16)aLVL.nStartAt; |
| |
| switch( aLVL.nNFC ) |
| { |
| case 0: |
| eType = SVX_NUM_ARABIC; |
| break; |
| case 1: |
| eType = SVX_NUM_ROMAN_UPPER; |
| break; |
| case 2: |
| eType = SVX_NUM_ROMAN_LOWER; |
| break; |
| case 3: |
| eType = SVX_NUM_CHARS_UPPER_LETTER_N; |
| break; |
| case 4: |
| eType = SVX_NUM_CHARS_LOWER_LETTER_N; |
| break; |
| case 5: |
| // eigentlich: ORDINAL |
| eType = SVX_NUM_ARABIC; |
| break; |
| case 23: |
| case 25: //#114412# |
| eType = SVX_NUM_CHAR_SPECIAL; |
| //For i120928,type info |
| if (bIsPicBullet) |
| { |
| eType = SVX_NUM_BITMAP; |
| } |
| |
| break; |
| case 255: |
| eType = SVX_NUM_NUMBER_NONE; |
| break; |
| default: |
| // take default |
| eType = SVX_NUM_ARABIC; |
| break; |
| } |
| |
| //If a number level is not going to be used, then record this fact |
| if (SVX_NUM_NUMBER_NONE == eType) |
| rNotReallyThere[nLevel] = true; |
| |
| /* |
| If a number level was not used (i.e. is in NotReallyThere), and that |
| number level appears at one of the positions in the display string of the |
| list, then it effectively is not there at all. So remove that level entry |
| from a copy of the aOfsNumsXCH. |
| */ |
| std::vector<sal_uInt8> aOfsNumsXCH; |
| typedef std::vector<sal_uInt8>::iterator myIter; |
| aOfsNumsXCH.reserve(nMaxLevel); |
| |
| for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB) |
| aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]); |
| |
| for(nLevelB = 0; nLevelB <= nLevel; ++nLevelB) |
| { |
| sal_uInt8 nPos = aOfsNumsXCH[nLevelB]; |
| if (nPos && sNumString.GetChar(nPos-1) < nMaxLevel) |
| { |
| if (rNotReallyThere[nLevelB]) |
| aOfsNumsXCH[nLevelB] = 0; |
| } |
| } |
| myIter aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0); |
| myIter aEnd = aOfsNumsXCH.end(); |
| // --> OD 2006-01-16 #i60633# - suppress access on <aOfsNumsXCH.end()> |
| if ( aIter != aEnd ) |
| { |
| // Somehow the first removed vector element, at which <aIter> |
| // points to, isn't reset to zero. |
| // Investigation is needed to clarify why. It seems that only |
| // special arrays are handled correctly by this code. |
| ++aIter; |
| while (aIter != aEnd) |
| { |
| (*aIter) = 0; |
| ++aIter; |
| } |
| } |
| // <-- |
| |
| sal_uInt8 nUpperLevel = 0; // akt. Anzeigetiefe fuer den Writer |
| for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB) |
| { |
| if (!nUpperLevel && !aOfsNumsXCH[nLevelB]) |
| nUpperLevel = nLevelB; |
| } |
| |
| // falls kein NULL als Terminierungs-Char kam, |
| // ist die Liste voller Indices, d.h. alle Plaetze sind besetzt, |
| // also sind alle Level anzuzeigen |
| if (!nUpperLevel) |
| nUpperLevel = nMaxLevel; |
| |
| if (SVX_NUM_CHAR_SPECIAL == eType) |
| { |
| cBullet = sNumString.Len() ? sNumString.GetChar(0) : 0x2190; |
| |
| if (!cBullet) // unsave control code? |
| cBullet = 0x2190; |
| } else if (SVX_NUM_BITMAP == eType) //For i120928,position index info of graphic |
| { |
| cGrfBulletCP = nWitchPicIsBullet; // This is a bullet picture ID |
| } else |
| { |
| /* |
| #83154#, #82192#, #i173#, #109158# |
| Our aOfsNumsXCH seems generally to be an array that contains the |
| offset into sNumString of locations where the numbers should be |
| filled in, so if the first "fill in a number" slot is greater than |
| 1 there is a "prefix" before the number |
| */ |
| //First number appears at |
| sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0]; |
| xub_StrLen nFirstNoIndex = |
| nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : STRING_LEN; |
| lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex); |
| |
| //Next number appears at |
| if (nUpperLevel) |
| { |
| sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1]; |
| xub_StrLen nNextNoIndex = |
| nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex -1 : STRING_LEN; |
| if (nNextNoIndex != STRING_LEN) |
| ++nNextNoIndex; |
| if (sNumString.Len() > nNextNoIndex) |
| lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex); |
| } |
| |
| /* |
| We use lcl_CopyGreaterEight because once if we have removed unused |
| number indexes from the aOfsNumsXCH then placeholders remain in |
| sNumString which must not be copied into the final numbering strings |
| */ |
| } |
| |
| switch( aLVL.nAlign ) |
| { |
| case 0: |
| eAdj = SVX_ADJUST_LEFT; |
| break; |
| case 1: |
| eAdj = SVX_ADJUST_CENTER; |
| break; |
| case 2: |
| eAdj = SVX_ADJUST_RIGHT; |
| break; |
| case 3: |
| // Writer here cannot do block justification |
| eAdj = SVX_ADJUST_LEFT; |
| break; |
| default: |
| // undefied value |
| ASSERT( !this, "Value of aLVL.nAlign is not supported" ); |
| // take default |
| eAdj = SVX_ADJUST_LEFT; |
| break; |
| } |
| |
| // 6. entsprechendes NumFmt konfigurieren |
| if( bSetStartNo ) |
| rNumFmt.SetStart( nStartNo ); |
| rNumFmt.SetNumberingType( static_cast< sal_Int16 >(eType) ); |
| rNumFmt.SetNumAdjust( eAdj ); |
| |
| if( SVX_NUM_CHAR_SPECIAL == eType ) |
| { |
| // first character of the Prefix-Text is the Bullet |
| rNumFmt.SetBulletChar(cBullet); |
| // Don't forget: unten, nach dem Bauen eventueller Styles auch noch |
| // SetBulletFont() rufen !!! |
| } |
| //For i120928,position index info |
| else if (SVX_NUM_BITMAP == eType) |
| { |
| rNumFmt.SetGrfBulletCP(cGrfBulletCP); |
| } |
| else |
| { |
| // reminder: Garnix ist default Prefix |
| if( sPrefix.Len() ) |
| rNumFmt.SetPrefix( sPrefix ); |
| // reminder: Point is default Postfix |
| rNumFmt.SetSuffix( sPostfix ); |
| rNumFmt.SetIncludeUpperLevels( nUpperLevel ); |
| } |
| |
| // --> OD 2008-06-04 #i89181# |
| if ( rNumFmt.GetPositionAndSpaceMode() == |
| SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) |
| { |
| if (eAdj == SVX_ADJUST_RIGHT) |
| { |
| rNumFmt.SetAbsLSpace(aLVL.nDxaLeft); |
| rNumFmt.SetFirstLineOffset(-aLVL.nDxaLeft); |
| rNumFmt.SetCharTextDistance(-aLVL.nDxaLeft1); |
| } |
| else |
| { |
| rNumFmt.SetAbsLSpace( aLVL.nDxaLeft ); |
| rNumFmt.SetFirstLineOffset(aLVL.nDxaLeft1); |
| } |
| } |
| else |
| { |
| rNumFmt.SetIndentAt( aLVL.nDxaLeft ); |
| rNumFmt.SetFirstLineIndent(aLVL.nDxaLeft1); |
| rNumFmt.SetListtabPos( nTabPos ); |
| SvxNumberFormat::SvxNumLabelFollowedBy eNumLabelFollowedBy = SvxNumberFormat::LISTTAB; |
| switch ( ixchFollow ) |
| { |
| case 0: |
| { |
| eNumLabelFollowedBy = SvxNumberFormat::LISTTAB; |
| } |
| break; |
| case 1: |
| { |
| eNumLabelFollowedBy = SvxNumberFormat::SPACE; |
| } |
| break; |
| case 2: |
| { |
| eNumLabelFollowedBy = SvxNumberFormat::NOTHING; |
| } |
| break; |
| } |
| rNumFmt.SetLabelFollowedBy( eNumLabelFollowedBy ); |
| } |
| |
| return true; |
| } |
| |
| void WW8ListManager::AdjustLVL( sal_uInt8 nLevel, SwNumRule& rNumRule, |
| WW8aISet& rListItemSet, WW8aCFmt& rCharFmt, bool& bNewCharFmtCreated, |
| String sPrefix ) |
| { |
| bNewCharFmtCreated = false; |
| SfxItemSet* pThisLevelItemSet; |
| SfxItemSet* pLowerLevelItemSet; |
| sal_uInt8 nIdenticalItemSetLevel; |
| const SfxPoolItem* pItem; |
| |
| SwNumFmt aNumFmt = rNumRule.Get( nLevel ); |
| |
| pThisLevelItemSet = rListItemSet[ nLevel ]; |
| |
| if( pThisLevelItemSet && pThisLevelItemSet->Count()) |
| { |
| nIdenticalItemSetLevel = nMaxLevel; |
| SfxItemIter aIter( *pThisLevelItemSet ); |
| for (sal_uInt8 nLowerLevel = 0; nLowerLevel < nLevel; ++nLowerLevel) |
| { |
| pLowerLevelItemSet = rListItemSet[ nLowerLevel ]; |
| if( pLowerLevelItemSet |
| && (pLowerLevelItemSet->Count() == pThisLevelItemSet->Count()) ) |
| { |
| nIdenticalItemSetLevel = nLowerLevel; |
| sal_uInt16 nWhich = aIter.GetCurItem()->Which(); |
| while (true) |
| { |
| if( // ggfs. passenden pItem im pLowerLevelItemSet finden |
| (SFX_ITEM_SET != pLowerLevelItemSet->GetItemState( |
| nWhich, false, &pItem ) ) |
| || // virtuellen "!=" Operator anwenden |
| (*pItem != *aIter.GetCurItem() ) ) |
| // falls kein Item mit gleicher nWhich gefunden oder Werte |
| // der Items ungleich, Ungleichheit merken und abbrechen! |
| { |
| nIdenticalItemSetLevel = nMaxLevel; |
| break; |
| } |
| if( aIter.IsAtEnd() ) |
| break; |
| nWhich = aIter.NextItem()->Which(); |
| } |
| |
| if( nIdenticalItemSetLevel != nMaxLevel ) |
| break; |
| } |
| } |
| |
| SwCharFmt* pFmt; |
| if (nMaxLevel == nIdenticalItemSetLevel) |
| { |
| // Style definieren |
| String aName( sPrefix.Len() ? sPrefix : rNumRule.GetName() ); |
| (aName += 'z') += String::CreateFromInt32( nLevel ); |
| |
| // const Wegcasten |
| pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt()); |
| bNewCharFmtCreated = true; |
| // Attribute reinsetzen |
| pFmt->SetFmtAttr( *pThisLevelItemSet ); |
| } |
| else |
| { |
| // passenden Style hier anhaengen |
| pFmt = rCharFmt[ nIdenticalItemSetLevel ]; |
| } |
| |
| // merken |
| rCharFmt[ nLevel ] = pFmt; |
| |
| // |
| // Style an das NumFormat haengen |
| // |
| aNumFmt.SetCharFmt( pFmt ); |
| } |
| //Modify for #119405 by chengjh, 2012-08-16 |
| //Ensure the default char fmt is initialized for any level of num ruler if no customized attr |
| else |
| { |
| SwCharFmt* pFmt = aNumFmt.GetCharFmt(); |
| if ( !pFmt) |
| { |
| String aName( sPrefix.Len() ? sPrefix : rNumRule.GetName() ); |
| (aName += 'z') += String::CreateFromInt32( nLevel ); |
| |
| pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt()); |
| bNewCharFmtCreated = true; |
| rCharFmt[ nLevel ] = pFmt; |
| aNumFmt.SetCharFmt( pFmt ); |
| } |
| } |
| //End |
| // |
| // ggfs. Bullet Font an das NumFormat haengen |
| // |
| if( SVX_NUM_CHAR_SPECIAL == aNumFmt.GetNumberingType() ) |
| { |
| SwCharFmt* pFmt = aNumFmt.GetCharFmt(); |
| Font aFont; |
| if( !pFmt ) |
| { |
| // --> OD 2006-06-27 #b6440955# |
| // aFont = SwNumRule::GetDefBulletFont(); |
| aFont = numfunc::GetDefBulletFont(); |
| // <-- |
| } |
| else |
| { |
| const SvxFontItem& rFontItem = pFmt->GetFont(); |
| aFont.SetFamily( rFontItem.GetFamily() ); |
| aFont.SetName( rFontItem.GetFamilyName() ); |
| aFont.SetStyleName( rFontItem.GetStyleName() ); |
| aFont.SetPitch( rFontItem.GetPitch() ); |
| aFont.SetCharSet( rFontItem.GetCharSet() ); |
| } |
| aNumFmt.SetBulletFont( &aFont ); |
| } |
| // |
| // und wieder rein in die NumRule |
| // |
| rNumRule.Set(nLevel, aNumFmt); |
| } |
| |
| SwNumRule* WW8ListManager::CreateNextRule(bool bSimple) |
| { |
| // wird erstmal zur Bildung des Style Namens genommen |
| String sPrefix(CREATE_CONST_ASC("WW8Num")); |
| sPrefix += String::CreateFromInt32(nUniqueList++); |
| // --> OD 2008-06-04 #i86652# |
| // sal_uInt16 nRul = rDoc.MakeNumRule(rDoc.GetUniqueNumRuleName(&sPrefix)); |
| sal_uInt16 nRul = |
| rDoc.MakeNumRule( rDoc.GetUniqueNumRuleName(&sPrefix), 0, sal_False, |
| SvxNumberFormat::LABEL_ALIGNMENT ); |
| // <-- |
| SwNumRule* pMyNumRule = rDoc.GetNumRuleTbl()[nRul]; |
| pMyNumRule->SetAutoRule(false); |
| pMyNumRule->SetContinusNum(bSimple); |
| return pMyNumRule; |
| } |
| |
| SwNumRule* WW8ListManager::GetNumRule(sal_uInt16 i) |
| { |
| if ( i < maLSTInfos.size() ) |
| return maLSTInfos[i]->pNumRule; |
| else |
| return 0; |
| } |
| |
| // oeffentliche Methoden ///////////////////////////////////////////////////// |
| // |
| WW8ListManager::WW8ListManager( |
| SvStream& rSt_, |
| SwWW8ImplReader& rReader_ ) |
| : maSprmParser( rReader_.GetFib().GetFIBVersion() ) |
| , rReader(rReader_) |
| , rDoc(rReader.GetDoc()) |
| , rFib(rReader.GetFib()) |
| , rSt(rSt_) |
| , maLSTInfos() |
| , pLFOInfos( NULL ) |
| , nUniqueList( 1 ) |
| , maStyleInList() |
| { |
| // LST und LFO gibts erst ab WW8 |
| if( ( 8 > rFib.nVersion ) |
| || ( rFib.fcPlcfLst == rFib.fcPlfLfo ) |
| || ( !rFib.lcbPlcfLst ) |
| || ( !rFib.lcbPlfLfo ) ) return; // offensichtlich keine Listen da |
| |
| // Arrays anlegen |
| pLFOInfos = new WW8LFOInfos; |
| bool bLVLOk = true; |
| sal_uInt8 aBits1; |
| |
| nLastLFOPosition = USHRT_MAX; |
| long nOriginalPos = rSt.Tell(); |
| // |
| // 1. PLCF LST auslesen und die Listen Vorlagen im Writer anlegen |
| // |
| rSt.Seek( rFib.fcPlcfLst ); |
| sal_uInt16 nListCount; |
| rSt >> nListCount; |
| bool bOk = 0 < nListCount; |
| if( bOk ) |
| { |
| WW8LST aLST; |
| // |
| // 1.1 alle LST einlesen |
| // |
| for (sal_uInt16 nList=0; nList < nListCount; ++nList) |
| { |
| bOk = false; |
| memset(&aLST, 0, sizeof( aLST )); |
| sal_uInt16 nLevel; |
| // |
| // 1.1.1 Daten einlesen |
| // |
| rSt >> aLST.nIdLst; |
| rSt >> aLST.nTplC; |
| for (nLevel = 0; nLevel < nMaxLevel; ++nLevel) |
| rSt >> aLST.aIdSty[ nLevel ]; |
| |
| |
| rSt >> aBits1; |
| |
| rSt.SeekRel( 1 ); |
| |
| if (rSt.GetError()) |
| break; |
| |
| if( aBits1 & 0x01 ) |
| aLST.bSimpleList = true; |
| if( aBits1 & 0x02 ) |
| aLST.bRestartHdn = true; |
| |
| // 1.1.2 new NumRule inserted in Doc and WW8LSTInfo marked |
| |
| /* |
| #i1869# |
| In word 2000 microsoft got rid of creating new "simple lists" with |
| only 1 level, all new lists are created with 9 levels. To hack it |
| so that the list types formerly known as simple lists still have |
| their own tab page to themselves one of the reserved bits is used |
| to show that a given list is to be in the simple list tabpage. |
| This has now nothing to do with the actual number of list level a |
| list has, only how many will be shown in the user interface. |
| |
| i.e. create a simple list in 2000 and open it in 97 and 97 will |
| claim (correctly) that it is an outline list. We can set our |
| continous flag in these lists to store this information. |
| */ |
| SwNumRule* pMyNumRule = CreateNextRule( |
| aLST.bSimpleList || (aBits1 & 0x10)); |
| |
| WW8LSTInfo* pLSTInfo = new WW8LSTInfo(pMyNumRule, aLST); |
| maLSTInfos.push_back(pLSTInfo); |
| bOk = true; |
| } |
| } |
| |
| if( bOk ) |
| { |
| // |
| // 1.2 alle LVL aller aLST einlesen |
| // |
| sal_uInt8 nLevel; |
| sal_uInt16 nLSTInfos = static_cast< sal_uInt16 >(maLSTInfos.size()); |
| for (sal_uInt16 nList = 0; nList < nLSTInfos; ++nList) |
| { |
| bOk = false; |
| WW8LSTInfo* pListInfo = maLSTInfos[nList]; |
| if( !pListInfo || !pListInfo->pNumRule ) break; |
| SwNumRule& rMyNumRule = *pListInfo->pNumRule; |
| // |
| // 1.2.1 betreffende(n) LVL(s) fuer diese aLST einlesen |
| // |
| sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel); |
| std::deque<bool> aNotReallyThere; |
| aNotReallyThere.resize(nMaxLevel); |
| pListInfo->maParaSprms.resize(nMaxLevel); |
| for (nLevel = 0; nLevel < nLvlCount; ++nLevel) |
| { |
| SwNumFmt aNumFmt( rMyNumRule.Get( nLevel ) ); |
| // LVLF einlesen |
| bLVLOk = ReadLVL( aNumFmt, pListInfo->aItemSet[nLevel], |
| pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel, |
| pListInfo->maParaSprms[nLevel]); |
| if( !bLVLOk ) |
| break; |
| // und in die rMyNumRule aufnehmen |
| rMyNumRule.Set( nLevel, aNumFmt ); |
| } |
| if( !bLVLOk ) |
| break; |
| // |
| // 1.2.2 die ItemPools mit den CHPx Einstellungen der verschiedenen |
| // Level miteinander vergleichen und ggfs. Style(s) erzeugen |
| // |
| bool bDummy; |
| for (nLevel = 0; nLevel < nLvlCount; ++nLevel) |
| { |
| AdjustLVL( nLevel, rMyNumRule, pListInfo->aItemSet, |
| pListInfo->aCharFmt, bDummy ); |
| } |
| // |
| // 1.2.3 ItemPools leeren und loeschen |
| // |
| for (nLevel = 0; nLevel < nLvlCount; ++nLevel) |
| delete pListInfo->aItemSet[ nLevel ]; |
| bOk = true; |
| } |
| } |
| if( !bOk ) |
| { |
| // Fehler aufgetreten - LSTInfos abraeumen !!! |
| |
| ; |
| } |
| |
| // |
| // 2. PLF LFO auslesen und speichern |
| // |
| long nLfoCount(0); |
| if (bOk) |
| { |
| rSt.Seek(rFib.fcPlfLfo); |
| rSt >> nLfoCount; |
| if (0 >= nLfoCount) |
| bOk = false; |
| } |
| |
| if(bOk) |
| { |
| WW8LFO aLFO; |
| // |
| // 2.1 alle LFO einlesen |
| // |
| for (sal_uInt16 nLfo = 0; nLfo < nLfoCount; ++nLfo) |
| { |
| bOk = false; |
| memset(&aLFO, 0, sizeof( aLFO )); |
| rSt >> aLFO.nIdLst; |
| rSt.SeekRel( 8 ); |
| rSt >> aLFO.nLfoLvl; |
| rSt.SeekRel( 3 ); |
| // soviele Overrides existieren |
| if ((nMaxLevel < aLFO.nLfoLvl) || rSt.GetError()) |
| break; |
| |
| // die Parent NumRule der entsprechenden Liste ermitteln |
| WW8LSTInfo* pParentListInfo = GetLSTByListId(aLFO.nIdLst); |
| if (pParentListInfo) |
| { |
| // hier, im ersten Schritt, erst mal diese NumRule festhalten |
| aLFO.pNumRule = pParentListInfo->pNumRule; |
| |
| // hat die Liste mehrere Level ? |
| aLFO.bSimpleList = pParentListInfo->bSimpleList; |
| } |
| // und rein ins Merk-Array mit dem Teil |
| WW8LFOInfo* pLFOInfo = new WW8LFOInfo(aLFO); |
| if ( pParentListInfo != NULL ) |
| { |
| //Copy the basic paragraph properties for each level from the |
| //original list into the list format override levels. |
| int nMaxSize = pParentListInfo->maParaSprms.size(); |
| pLFOInfo->maParaSprms.resize(nMaxSize); |
| for (int i = 0; i < nMaxSize; ++i) |
| { |
| pLFOInfo->maParaSprms[i] = pParentListInfo->maParaSprms[i]; |
| } |
| |
| const sal_uInt16 nLFOInfoArrayPos = pLFOInfos->Count(); |
| for ( sal_uInt8 j = 0 ; j < nMaxLevel; ++j ) |
| { |
| maStyleInList[pParentListInfo->aIdSty[j]] = nLFOInfoArrayPos; |
| } |
| } |
| pLFOInfos->Insert( pLFOInfo, pLFOInfos->Count() ); |
| bOk = true; |
| } |
| } |
| if( bOk ) |
| { |
| // |
| // 2.2 fuer alle LFO die zugehoerigen LFOLVL einlesen |
| // |
| sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0; |
| for (sal_uInt16 nLfo = 0; nLfo < nLFOInfos; ++nLfo) |
| { |
| bOk = false; |
| WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLfo ); |
| if (!pLFOInfo) |
| break; |
| // stehen hierfuer ueberhaupt LFOLVL an ? |
| if( pLFOInfo->bOverride ) |
| { |
| WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst); |
| if (!pParentListInfo) //e.g. #112324# |
| break; |
| // |
| // 2.2.1 eine neue NumRule fuer diese Liste anlegen |
| // |
| SwNumRule* pParentNumRule = pLFOInfo->pNumRule; |
| ASSERT(pParentNumRule, "ww: Impossible lists, please report"); |
| if( !pParentNumRule ) |
| break; |
| // Nauemsprefix aufbauen: fuer NumRule-Name (eventuell) |
| // und (falls vorhanden) fuer Style-Name (dann auf jeden Fall) |
| String sPrefix(CREATE_CONST_ASC( "WW8NumSt" )); |
| sPrefix += String::CreateFromInt32( nLfo + 1 ); |
| // jetzt dem pNumRule seinen RICHTIGEN Wert zuweisen !!! |
| // (bis dahin war hier die Parent NumRule vermerkt ) |
| // |
| // Dazu erst mal nachsehen, ob ein Style diesen LFO |
| // referenziert: |
| if( USHRT_MAX > rReader.StyleUsingLFO( nLfo ) ) |
| { |
| sal_uInt16 nRul = rDoc.MakeNumRule( |
| rDoc.GetUniqueNumRuleName( &sPrefix ), pParentNumRule); |
| pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ]; |
| pLFOInfo->pNumRule->SetAutoRule(false); |
| } |
| else |
| { |
| sal_uInt16 nRul = rDoc.MakeNumRule( |
| rDoc.GetUniqueNumRuleName(), pParentNumRule); |
| pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ]; |
| pLFOInfo->pNumRule->SetAutoRule(true); // = default |
| } |
| // |
| // 2.2.2 alle LFOLVL (und ggfs. LVL) fuer die neue NumRule |
| // einlesen |
| // |
| WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx |
| WW8aCFmt aCharFmt; // Zeichen Style Pointer |
| memset(&aItemSet, 0, sizeof( aItemSet )); |
| memset(&aCharFmt, 0, sizeof( aCharFmt )); |
| |
| //2.2.2.0 skip inter-group of override header ? |
| //See #i25438# for why I moved this here, compare |
| //that original bugdoc's binary to what it looks like |
| //when resaved with word, i.e. there is always a |
| //4 byte header, there might be more than one if |
| //that header was 0xFFFFFFFF, e.g. #114412# ? |
| sal_uInt32 nTest; |
| rSt >> nTest; |
| do |
| rSt >> nTest; |
| while (nTest == 0xFFFFFFFF); |
| rSt.SeekRel(-4); |
| |
| std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel); |
| sal_uInt8 nLevel = 0; |
| for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel) |
| { |
| WW8LFOLVL aLFOLVL; |
| bLVLOk = false; |
| |
| // |
| // 2.2.2.1 den LFOLVL einlesen |
| // |
| rSt >> aLFOLVL.nStartAt; |
| rSt >> aBits1; |
| rSt.SeekRel( 3 ); |
| if (rSt.GetError()) |
| break; |
| |
| // beachte: Die Witzbolde bei MS quetschen die |
| // Override-Level-Nummer in vier Bits hinein, damit sie |
| // wieder einen Grund haben, ihr Dateiformat zu aendern, |
| // falls ihnen einfaellt, dass sie eigentlich doch gerne |
| // bis zu 16 Listen-Level haetten. Wir tun das *nicht* |
| // (siehe Kommentar oben bei "struct |
| // WW8LFOInfo") |
| aLFOLVL.nLevel = aBits1 & 0x0F; |
| if( (0xFF > aBits1) && |
| (nMaxLevel > aLFOLVL.nLevel) ) |
| { |
| if (aBits1 & 0x10) |
| aLFOLVL.bStartAt = true; |
| else |
| aLFOLVL.bStartAt = false; |
| // |
| // 2.2.2.2 eventuell auch den zugehoerigen LVL einlesen |
| // |
| SwNumFmt aNumFmt( |
| pLFOInfo->pNumRule->Get(aLFOLVL.nLevel)); |
| if (aBits1 & 0x20) |
| { |
| aLFOLVL.bFormat = true; |
| // falls bStartup true, hier den Startup-Level |
| // durch den im LVL vermerkten ersetzen LVLF |
| // einlesen |
| bLVLOk = ReadLVL(aNumFmt, aItemSet[nLevel], |
| pParentListInfo->aIdSty[nLevel], |
| aLFOLVL.bStartAt, aNotReallyThere, nLevel, |
| pLFOInfo->maParaSprms[nLevel]); |
| |
| if (!bLVLOk) |
| break; |
| } |
| else if (aLFOLVL.bStartAt) |
| { |
| aNumFmt.SetStart( |
| writer_cast<sal_uInt16>(aLFOLVL.nStartAt)); |
| } |
| // |
| // 2.2.2.3 das NumFmt in die NumRule aufnehmen |
| // |
| pLFOInfo->pNumRule->Set(aLFOLVL.nLevel, aNumFmt); |
| } |
| bLVLOk = true; |
| |
| if (nMaxLevel > aLFOLVL.nLevel) |
| pLFOInfo->maOverrides[aLFOLVL.nLevel] = aLFOLVL; |
| } |
| if( !bLVLOk ) |
| break; |
| // |
| // 2.2.3 die LVL der neuen NumRule anpassen |
| // |
| sal_uInt16 aFlagsNewCharFmt = 0; |
| bool bNewCharFmtCreated = false; |
| for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel) |
| { |
| AdjustLVL( nLevel, *pLFOInfo->pNumRule, aItemSet, aCharFmt, |
| bNewCharFmtCreated, sPrefix ); |
| if( bNewCharFmtCreated ) |
| aFlagsNewCharFmt += (1 << nLevel); |
| } |
| // |
| // 2.2.4 ItemPools leeren und loeschen |
| // |
| for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel) |
| delete aItemSet[ nLevel ]; |
| bOk = true; |
| } |
| } |
| } |
| if( !bOk ) |
| { |
| // Fehler aufgetreten - LSTInfos und LFOInfos abraeumen !!! |
| ; |
| } |
| // und schon sind wir fertig! |
| rSt.Seek( nOriginalPos ); |
| } |
| |
| WW8ListManager::~WW8ListManager() |
| { |
| /* |
| named lists remain in doc!!! |
| unnamed lists are deleted when unused |
| pLFOInfos are in any case destructed |
| */ |
| for(std::vector<WW8LSTInfo *>::iterator aIter = maLSTInfos.begin(); |
| aIter != maLSTInfos.end(); ++aIter) |
| { |
| if ((*aIter)->pNumRule && !(*aIter)->bUsedInDoc && |
| (*aIter)->pNumRule->IsAutoRule()) |
| { |
| rDoc.DelNumRule((*aIter)->pNumRule->GetName()); |
| } |
| delete *aIter; |
| } |
| |
| if (pLFOInfos) |
| { |
| for(sal_uInt16 nInfo = pLFOInfos->Count(); nInfo; ) |
| { |
| WW8LFOInfo *pActInfo = pLFOInfos->GetObject(--nInfo); |
| if (pActInfo->bOverride && pActInfo->pNumRule |
| && !pActInfo->bUsedInDoc && pActInfo->pNumRule->IsAutoRule()) |
| { |
| rDoc.DelNumRule( pActInfo->pNumRule->GetName() ); |
| } |
| } |
| delete pLFOInfos; |
| } |
| } |
| |
| sal_uInt16 WW8ListManager::GetPossibleLFOPosition( |
| const sal_uInt16 nStyleID, |
| const sal_uInt8 nGivenListLevel ) |
| { |
| sal_uInt16 nPossibleLFOPosition = USHRT_MAX; |
| |
| StyleInList::iterator aItr = maStyleInList.find( nStyleID ); |
| if ( aItr != maStyleInList.end() |
| && aItr->second < pLFOInfos->Count() ) |
| { |
| WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( aItr->second ); |
| WW8LSTInfo* pParentListInfo = GetLSTByListId( pLFOInfo->nIdLst ); |
| if ( pParentListInfo != NULL |
| && pParentListInfo->aIdSty[nGivenListLevel] == nStyleID ) |
| { |
| nPossibleLFOPosition = aItr->second; |
| } |
| } |
| |
| return nPossibleLFOPosition; |
| } |
| |
| |
| bool IsEqualFormatting(const SwNumRule &rOne, const SwNumRule &rTwo) |
| { |
| bool bRet = |
| ( |
| rOne.GetRuleType() == rTwo.GetRuleType() && |
| rOne.IsContinusNum() == rTwo.IsContinusNum() && |
| rOne.IsAbsSpaces() == rTwo.IsAbsSpaces() && |
| rOne.GetPoolFmtId() == rTwo.GetPoolFmtId() && |
| rOne.GetPoolHelpId() == rTwo.GetPoolHelpId() && |
| rTwo.GetPoolHlpFileId() == rTwo.GetPoolHlpFileId() |
| ); |
| |
| if (bRet) |
| { |
| for (sal_uInt8 n = 0; n < MAXLEVEL; ++n ) |
| { |
| //The SvxNumberFormat compare, not the SwNumFmt compare |
| const SvxNumberFormat &rO = rOne.Get(n); |
| const SvxNumberFormat &rT = rTwo.Get(n); |
| if (!(rO == rT)) |
| { |
| bRet = false; |
| break; |
| } |
| } |
| } |
| return bRet; |
| } |
| |
| SwNumRule* WW8ListManager::GetNumRuleForActivation(sal_uInt16 nLFOPosition, |
| const sal_uInt8 nLevel, std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode) |
| { |
| sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0; |
| if( nLFOInfos <= nLFOPosition ) |
| return 0; |
| |
| WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLFOPosition ); |
| |
| if( !pLFOInfo ) |
| return 0; |
| |
| bool bFirstUse = !pLFOInfo->bUsedInDoc; |
| pLFOInfo->bUsedInDoc = true; |
| |
| if( !pLFOInfo->pNumRule ) |
| return 0; |
| |
| // #i25545# |
| // --> OD 2009-03-12 #i100132# - a number format does not have to exist on given list level |
| // SwNumFmt pFmt(*(pLFOInfo->pNumRule->GetNumFmt(nLevel))); |
| SwNumFmt pFmt(pLFOInfo->pNumRule->Get(nLevel)); |
| // <-- |
| if (rReader.IsRightToLeft() && nLastLFOPosition != nLFOPosition) { |
| if ( pFmt.GetNumAdjust() == SVX_ADJUST_RIGHT) |
| pFmt.SetNumAdjust(SVX_ADJUST_LEFT); |
| else if ( pFmt.GetNumAdjust() == SVX_ADJUST_LEFT) |
| pFmt.SetNumAdjust(SVX_ADJUST_RIGHT); |
| pLFOInfo->pNumRule->Set(nLevel, pFmt); |
| } |
| nLastLFOPosition = nLFOPosition; |
| /* |
| #i1869# |
| If this list has had its bits set in word 2000 to pretend that it is a |
| simple list from the point of view of the user, then it is almost |
| certainly a simple continous list, and we will try to keep it like that. |
| Otherwise when we save again it will be shown as the true outline list |
| that it is, confusing the user that just wanted what they thought was a |
| simple list. On the otherhand it is possible that some of the other levels |
| were used by the user, in which case we will not pretend anymore that it |
| is a simple list. Something that word 2000 does anyway, that 97 didn't, to |
| my bewilderment. |
| */ |
| if (nLevel && pLFOInfo->pNumRule->IsContinusNum()) |
| pLFOInfo->pNumRule->SetContinusNum(false); |
| |
| if( (!pLFOInfo->bOverride) && (!pLFOInfo->bLSTbUIDSet) ) |
| { |
| WW8LSTInfo* pParentListInfo = GetLSTByListId( pLFOInfo->nIdLst ); |
| if( pParentListInfo ) |
| pParentListInfo->bUsedInDoc = true; |
| pLFOInfo->bLSTbUIDSet = true; |
| } |
| |
| if (pLFOInfo->maParaSprms.size() > nLevel) |
| rParaSprms = pLFOInfo->maParaSprms[nLevel]; |
| |
| SwNumRule *pRet = pLFOInfo->pNumRule; |
| |
| bool bRestart(false); |
| sal_uInt16 nStart(0); |
| bool bNewstart(false); |
| /* |
| Note: If you fiddle with this then you have to make sure that #i18322# |
| #i13833#, #i20095# and #112466# continue to work |
| |
| Check if there were overrides for this level |
| */ |
| if (pLFOInfo->bOverride && nLevel < pLFOInfo->nLfoLvl) |
| { |
| WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst); |
| ASSERT(pParentListInfo, "ww: Impossible lists, please report"); |
| if (pParentListInfo && pParentListInfo->pNumRule) |
| { |
| const WW8LFOLVL &rOverride = pLFOInfo->maOverrides[nLevel]; |
| bool bNoChangeFromParent = |
| IsEqualFormatting(*pRet, *(pParentListInfo->pNumRule)); |
| |
| //If so then I think word still uses the parent (maybe) |
| if (bNoChangeFromParent) |
| { |
| pRet = pParentListInfo->pNumRule; |
| |
| //did it not affect start at value ? |
| if (bFirstUse) |
| { |
| if (rOverride.bStartAt) |
| { |
| const SwNumFmt &rFmt = |
| pParentListInfo->pNumRule->Get(nLevel); |
| if ( |
| rFmt.GetStart() == |
| pLFOInfo->maOverrides[nLevel].nStartAt |
| ) |
| { |
| bRestart = true; |
| } |
| else |
| { |
| bNewstart = true; |
| nStart = writer_cast<sal_uInt16> |
| (pLFOInfo->maOverrides[nLevel].nStartAt); |
| } |
| } |
| } |
| |
| pParentListInfo->bUsedInDoc = true; |
| } |
| } |
| } |
| |
| if (pNode) |
| { |
| pNode->SetAttrListLevel(nLevel); |
| |
| if (bRestart || bNewstart) //#112466# (I think) |
| pNode->SetListRestart(true); |
| if (bNewstart) |
| pNode->SetAttrListRestartValue(nStart); |
| } |
| return pRet; |
| } |
| |
| |
| //---------------------------------------------------------------------------- |
| // SwWW8ImplReader: anhaengen einer Liste an einen Style oder Absatz |
| //---------------------------------------------------------------------------- |
| bool SwWW8ImplReader::SetTxtFmtCollAndListLevel( |
| const SwPaM& rRg, |
| SwWW8StyInf& rStyleInfo) |
| { |
| bool bRes = true; |
| if( rStyleInfo.pFmt && rStyleInfo.bColl ) |
| { |
| bRes = rDoc.SetTxtFmtColl(rRg, (SwTxtFmtColl*)rStyleInfo.pFmt) ? true : false; |
| SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode(); |
| ASSERT( pTxtNode != NULL, "No Text-Node at PaM-Position" ); |
| if ( pTxtNode == NULL ) |
| { |
| // make code robust |
| return bRes; |
| } |
| |
| const SwNumRule * pNumRule = pTxtNode->GetNumRule(); // #i27610# |
| |
| if( !IsInvalidOrToBeMergedTabCell() |
| && ! (pNumRule && pNumRule->IsOutlineRule()) ) // #i27610# |
| { |
| pTxtNode->ResetAttr( RES_PARATR_NUMRULE ); |
| } |
| |
| if ( USHRT_MAX > rStyleInfo.nLFOIndex |
| && WW8ListManager::nMaxLevel > rStyleInfo.nListLevel ) |
| { |
| const bool bApplyListStyle = false; |
| RegisterNumFmtOnTxtNode( rStyleInfo.nLFOIndex, rStyleInfo.nListLevel, bApplyListStyle ); |
| } |
| } |
| return bRes; |
| } |
| |
| void UseListIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt) |
| { |
| if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) |
| { |
| const long nAbsLSpace = rFmt.GetAbsLSpace(); |
| const long nListFirstLineIndent = GetListFirstLineIndent(rFmt); |
| SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE)); |
| aLR.SetTxtLeft(nAbsLSpace); |
| aLR.SetTxtFirstLineOfst(writer_cast<short>(nListFirstLineIndent)); |
| rStyle.pFmt->SetFmtAttr(aLR); |
| rStyle.bListReleventIndentSet = true; |
| } |
| } |
| |
| void SetStyleIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt) |
| { |
| if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) |
| { |
| SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE)); |
| if (rStyle.bListReleventIndentSet) |
| { |
| SyncIndentWithList( aLR, rFmt, false, false ); |
| } |
| else |
| { |
| aLR.SetTxtLeft(0); |
| aLR.SetTxtFirstLineOfst(0); |
| } |
| rStyle.pFmt->SetFmtAttr(aLR); |
| } |
| } |
| |
| void SwWW8ImplReader::SetStylesList( |
| sal_uInt16 nStyle, |
| sal_uInt16 nActLFO, |
| sal_uInt8 nActLevel) |
| { |
| SwWW8StyInf &rStyleInf = pCollA[nStyle]; |
| if (rStyleInf.bValid) |
| { |
| ASSERT(pAktColl, "Cannot be called outside of style import"); |
| // Phase 1: Nummerierungsattribute beim Einlesen einer StyleDef |
| if( pAktColl ) |
| { |
| // jetzt nur die Parameter vermerken: die tatsaechliche Liste wird |
| // spaeter drangehaengt, wenn die Listendefinitionen gelesen sind... |
| if ( |
| (USHRT_MAX > nActLFO) && |
| (WW8ListManager::nMaxLevel > nActLevel) |
| ) |
| { |
| rStyleInf.nLFOIndex = nActLFO; |
| rStyleInf.nListLevel = nActLevel; |
| |
| if ( |
| (USHRT_MAX > nActLFO) && |
| (WW8ListManager::nMaxLevel > nActLevel) |
| ) |
| { |
| std::vector<sal_uInt8> aParaSprms; |
| SwNumRule *pNmRule = |
| pLstManager->GetNumRuleForActivation(nActLFO, |
| nActLevel, aParaSprms); |
| if (pNmRule) |
| UseListIndent(rStyleInf, pNmRule->Get(nActLevel)); |
| } |
| } |
| } |
| } |
| } |
| |
| void SwWW8ImplReader::RegisterNumFmtOnStyle( sal_uInt16 nStyle ) |
| { |
| SwWW8StyInf &rStyleInf = pCollA[nStyle]; |
| if (rStyleInf.bValid && rStyleInf.pFmt) |
| { |
| //Save old pre-list modified indent, which are the word indent values |
| rStyleInf.maWordLR = |
| ItemGet<SvxLRSpaceItem>(*rStyleInf.pFmt, RES_LR_SPACE); |
| |
| // Phase 2: aktualisieren der StyleDef nach einlesen aller Listen |
| SwNumRule* pNmRule = 0; |
| const sal_uInt16 nLFO = rStyleInf.nLFOIndex; |
| const sal_uInt8 nLevel = rStyleInf.nListLevel; |
| if ( |
| (USHRT_MAX > nLFO) && |
| (WW8ListManager::nMaxLevel > nLevel) |
| ) |
| { |
| std::vector<sal_uInt8> aParaSprms; |
| pNmRule = |
| pLstManager->GetNumRuleForActivation( nLFO, nLevel, aParaSprms ); |
| |
| if ( pNmRule != NULL ) |
| { |
| if ( rStyleInf.IsWW8BuiltInHeadingStyle() |
| && rStyleInf.HasWW8OutlineLevel() ) |
| { |
| rStyleInf.pOutlineNumrule = pNmRule; |
| } |
| else |
| { |
| rStyleInf.pFmt->SetFmtAttr( SwNumRuleItem( pNmRule->GetName() ) ); |
| rStyleInf.bHasStyNumRule = true; |
| } |
| } |
| } |
| |
| if (pNmRule) |
| SetStyleIndent(rStyleInf, pNmRule->Get(nLevel)); |
| } |
| } |
| |
| void SwWW8ImplReader::RegisterNumFmtOnTxtNode( |
| sal_uInt16 nActLFO, |
| sal_uInt8 nActLevel, |
| const bool bSetAttr) |
| { |
| // beachte: die Methode haengt die NumRule an den Text Node, falls |
| // bSetAttr (dann muessen natuerlich vorher die Listen gelesen sein) |
| // stellt sie NUR den Level ein, im Vertrauen darauf, dass am STYLE eine |
| // NumRule haengt - dies wird NICHT ueberprueft !!! |
| |
| if (pLstManager) // sind die Listendeklarationen gelesen? |
| { |
| std::vector<sal_uInt8> aParaSprms; |
| SwTxtNode* pTxtNd = pPaM->GetNode()->GetTxtNode(); |
| ASSERT(pTxtNd, "Kein Text-Node an PaM-Position"); |
| |
| const SwNumRule* pRule = |
| bSetAttr |
| ? pLstManager->GetNumRuleForActivation( nActLFO, nActLevel, aParaSprms, pTxtNd) |
| : 0; |
| |
| if ( pRule != NULL || !bSetAttr) |
| { |
| if ( bSetAttr |
| && pTxtNd->GetNumRule() != pRule |
| && pTxtNd->GetNumRule() != rDoc.GetOutlineNumRule() ) |
| { |
| pTxtNd->SetAttr( SwNumRuleItem( pRule->GetName() ) ); |
| } |
| |
| pTxtNd->SetAttrListLevel(nActLevel); |
| // - <IsCounted()> state of text node has to be adjusted accordingly. |
| if ( /*nActLevel >= 0 &&*/ nActLevel < MAXLEVEL ) |
| { |
| pTxtNd->SetCountedInList( true ); |
| } |
| |
| // Direct application of the list level formatting no longer |
| // needed for list levels of mode LABEL_ALIGNMENT |
| bool bApplyListLevelIndentDirectlyAtPara( true ); |
| { |
| if ( pTxtNd->GetNumRule() && nActLevel < MAXLEVEL ) |
| { |
| const SwNumFmt& rFmt = pTxtNd->GetNumRule()->Get( nActLevel ); |
| if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) |
| { |
| bApplyListLevelIndentDirectlyAtPara = false; |
| } |
| } |
| } |
| if ( bApplyListLevelIndentDirectlyAtPara ) |
| { |
| SfxItemSet aListIndent(rDoc.GetAttrPool(), RES_LR_SPACE, |
| RES_LR_SPACE); |
| const SvxLRSpaceItem *pItem = (const SvxLRSpaceItem*)( |
| GetFmtAttr(RES_LR_SPACE)); |
| ASSERT(pItem, "impossible"); |
| if (pItem) |
| aListIndent.Put(*pItem); |
| |
| /* |
| Take the original paragraph sprms attached to this list level |
| formatting and apply them to the paragraph. I'm convinced that |
| this is exactly what word does. |
| */ |
| if (short nLen = static_cast< short >(aParaSprms.size())) |
| { |
| SfxItemSet* pOldAktItemSet = pAktItemSet; |
| SetAktItemSet(&aListIndent); |
| |
| sal_uInt8* pSprms1 = &aParaSprms[0]; |
| while (0 < nLen) |
| { |
| sal_uInt16 nL1 = ImportSprm(pSprms1); |
| nLen = nLen - nL1; |
| pSprms1 += nL1; |
| } |
| |
| SetAktItemSet(pOldAktItemSet); |
| } |
| |
| const SvxLRSpaceItem *pLR = |
| HasItem<SvxLRSpaceItem>(aListIndent, RES_LR_SPACE); |
| ASSERT(pLR, "Impossible"); |
| if (pLR) |
| { |
| pCtrlStck->NewAttr(*pPaM->GetPoint(), *pLR); |
| pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE); |
| } |
| } |
| } |
| } |
| } |
| |
| void SwWW8ImplReader::RegisterNumFmt(sal_uInt16 nActLFO, sal_uInt8 nActLevel) |
| { |
| // sind wir erst beim Einlesen der StyleDef ? |
| if (pAktColl) |
| SetStylesList( nAktColl , nActLFO, nActLevel); |
| else |
| RegisterNumFmtOnTxtNode(nActLFO, nActLevel); |
| } |
| |
| void SwWW8ImplReader::Read_ListLevel(sal_uInt16, const sal_uInt8* pData, |
| short nLen) |
| { |
| if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox()) |
| return; |
| |
| if( nLen < 0 ) |
| { |
| // aktuelle Liste ist hier zu Ende, was ist zu tun ??? |
| nListLevel = WW8ListManager::nMaxLevel; |
| if (pStyles && !bVer67) |
| pStyles->nWwNumLevel = 0; |
| } |
| else |
| { |
| // Sicherheitspruefung auf NIL Pointer |
| if( !pData ) return; |
| // die Streamdaten sind hier Null basiert, so wie wir es brauchen |
| nListLevel = *pData; |
| |
| if (pStyles && !bVer67) |
| { |
| /* |
| #94672# |
| if this is the case, then if the numbering is actually stored in |
| winword 6 format, and its likely that sprmPIlvl has been abused |
| to set the ww6 list level information which we will need when we |
| reach the true ww6 list def. So set it now |
| */ |
| pStyles->nWwNumLevel = nListLevel; |
| } |
| |
| if (WW8ListManager::nMaxLevel <= nListLevel ) |
| { |
| // handle invalid list level value by reseting it |
| nListLevel = WW8ListManager::nMaxLevel; |
| } |
| else if ( nLFOPosition < USHRT_MAX |
| && nListLevel < WW8ListManager::nMaxLevel ) |
| { |
| RegisterNumFmt( nLFOPosition, nListLevel ); |
| // reset kept list attributes |
| nLFOPosition = USHRT_MAX; |
| nListLevel = WW8ListManager::nMaxLevel; |
| } |
| else if ( pLstManager != NULL |
| && pAktColl != NULL ) |
| { |
| const sal_uInt16 nPossibleLFOPosition = |
| pLstManager->GetPossibleLFOPosition( nAktColl, nListLevel ); |
| if ( nPossibleLFOPosition < USHRT_MAX ) |
| { |
| // temporary register Style without reseting kept list attributes |
| RegisterNumFmt( nPossibleLFOPosition, nListLevel ); |
| } |
| } |
| } |
| } |
| |
| void SwWW8ImplReader::Read_LFOPosition( |
| sal_uInt16, |
| const sal_uInt8* pData, |
| short nLen) |
| { |
| if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox()) |
| return; |
| |
| if( nLen < 0 ) |
| { |
| // aktueller Level ist hier zu Ende, was ist zu tun ??? |
| nLFOPosition = USHRT_MAX; |
| nListLevel = WW8ListManager::nMaxLevel; |
| } |
| else |
| { |
| // Sicherheitspruefung auf NIL Pointer |
| if( !pData ) |
| return; |
| short nData = SVBT16ToShort( pData ); |
| if( 0 >= nData ) |
| { |
| /* |
| #94672# discussion |
| If you have a paragraph in word with left and/or hanging indent |
| and remove its numbering, then the indentation appears to get |
| reset, but not back to the base style, instead its goes to a blank |
| setting. |
| Unless its a broken ww6 list in 97 in which case more hackery is |
| required, some more details about that in |
| ww8par6.cxx#SwWW8ImplReader::Read_LR |
| */ |
| |
| if (pAktColl) |
| { |
| pAktColl->SetFmtAttr(*GetDfltAttr( RES_PARATR_NUMRULE)); |
| pAktColl->SetFmtAttr(SvxLRSpaceItem(RES_LR_SPACE)); //#94672# |
| } |
| else if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode()) |
| { |
| pTxtNode->ResetAttr( RES_PARATR_NUMRULE ); |
| pTxtNode->SetCountedInList(false); |
| |
| /* |
| #i24553# |
| Hmm, I can't remove outline numbering on a per txtnode basis, |
| but I can set some normal numbering, and that overrides outline |
| numbering, and then I can say when I come to say that I want no |
| number on the normal numbering rule, that should all work out |
| |
| #115901# |
| No special outline number in textnode any more |
| */ |
| if (pTxtNode->IsOutline()) |
| { |
| // Assure that the numbering rule, which is retrieved at |
| // the paragraph is the outline numbering rule, instead of |
| // incorrectly setting the chosen outline rule. |
| // Note: The chosen outline rule doesn't have to correspond |
| // to the outline rule |
| if ( pTxtNode->GetNumRule() != rDoc.GetOutlineNumRule() ) |
| { |
| pTxtNode->SetAttr( |
| SwNumRuleItem( rDoc.GetOutlineNumRule()->GetName() ) ); |
| } |
| } |
| |
| //#94672# |
| pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxLRSpaceItem(RES_LR_SPACE)); |
| pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE); |
| } |
| nLFOPosition = USHRT_MAX; |
| } |
| else |
| { |
| nLFOPosition = (sal_uInt16)nData-1; |
| /* |
| #94672# |
| If we are a ww8+ style with ww7- style lists then there is a |
| bizarre broken word bug where when the list is removed from a para |
| the ww6 list first line indent still affects the first line |
| indentation. Setting this flag will allow us to recover from this |
| braindeadness |
| */ |
| if ( pAktColl |
| && (nLFOPosition == 2047-1) ) |
| { |
| pCollA[nAktColl].bHasBrokenWW6List = true; |
| } |
| |
| // die Streamdaten sind hier 1 basiert, wir ziehen EINS ab |
| if (USHRT_MAX > nLFOPosition) |
| { |
| if (nLFOPosition != 2047-1) //Normal ww8+ list behaviour |
| { |
| if ( nListLevel == WW8ListManager::nMaxLevel ) |
| { |
| nListLevel = 0; |
| if ( pAktColl != NULL ) |
| { |
| // temporary register Style without reseting kept list attributes |
| RegisterNumFmt( nLFOPosition, nListLevel ); |
| } |
| } |
| else if (WW8ListManager::nMaxLevel > nListLevel) |
| { |
| RegisterNumFmt(nLFOPosition, nListLevel); |
| // reset kept list attributes |
| nLFOPosition = USHRT_MAX; |
| nListLevel = WW8ListManager::nMaxLevel; |
| } |
| } |
| else if (pPlcxMan && pPlcxMan->HasParaSprm(0xC63E)) |
| { |
| /* |
| #i8114# Horrific backwards compatible ww7- lists in ww8+ docs |
| */ |
| Read_ANLevelNo(13 /*equiv ww7- sprm no*/, &nListLevel, 1); |
| } |
| } |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------- |
| // ------------------------- Reading Controls ------------------------ |
| // ------------------------------------------------------------------- |
| |
| bool SwWW8ImplReader::ImportFormulaControl(WW8FormulaControl &aFormula, |
| WW8_CP nStart, SwWw8ControlType nWhich ) |
| { |
| bool bRet=false; |
| /* |
| * Save the reader state and process the sprms for this anchor cp. |
| * Doing so will set the nPicLocFc to the offset to find the hypertext |
| * data in the data stream. |
| */ |
| WW8_CP nEndCp = nStart+1; //Only interested in the single 0x01 character |
| |
| WW8ReaderSave aSave(this,nStart); |
| |
| WW8PLCFManResult aRes; |
| nStart = pPlcxMan->Where(); |
| while(nStart <= nEndCp) |
| { |
| if ( pPlcxMan->Get(&aRes) |
| && aRes.pMemPos && aRes.nSprmId ) |
| { |
| //only interested in sprms which would set nPicLocFc |
| if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) ) |
| { |
| Read_PicLoc( aRes.nSprmId, aRes.pMemPos + |
| mpSprmParser->DistanceToData(aRes.nSprmId), 4); |
| break; |
| } |
| } |
| (*pPlcxMan)++; |
| nStart = pPlcxMan->Where(); |
| } |
| sal_uLong nOffset = nPicLocFc; |
| aSave.Restore(this); |
| |
| sal_uLong nOldPos = pDataStream->Tell(); |
| WW8_PIC aPic; |
| pDataStream->Seek( nOffset); |
| PicRead( pDataStream, &aPic, bVer67); |
| |
| if((aPic.lcb > 0x3A) && !pDataStream->GetError() ) |
| { |
| aFormula.FormulaRead(nWhich,pDataStream); |
| bRet = true; |
| } |
| |
| /* |
| There is a problem with aPic, the WW8_PIC is always used even though it |
| is too big for the WW95 files, it needs to be modified to check the |
| version C. |
| */ |
| pDataStream->Seek( nOldPos ); |
| return(bRet); |
| } |
| |
| sal_Bool SwMSConvertControls::InsertFormula(WW8FormulaControl &rFormula) |
| { |
| sal_Bool bRet = sal_False; |
| |
| const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory = |
| GetServiceFactory(); |
| |
| if(!rServiceFactory.is()) |
| return sal_False; |
| |
| awt::Size aSz; |
| uno::Reference< form::XFormComponent> xFComp; |
| |
| if (sal_True == (bRet = rFormula.Import(rServiceFactory, xFComp, aSz))) |
| { |
| uno::Reference <drawing::XShape> xShapeRef; |
| if (sal_True == (bRet = InsertControl(xFComp, aSz, &xShapeRef, false))) |
| GetShapes()->add(xShapeRef); |
| } |
| return bRet; |
| } |
| |
| void WW8FormulaControl::FormulaRead(SwWw8ControlType nWhich, |
| SvStream *pDataStream) |
| { |
| sal_uInt8 nField; |
| sal_uInt8 nHeaderByte; |
| |
| int nType=0; |
| *pDataStream >> nHeaderByte; |
| if (nHeaderByte == 0xFF) //Guesswork time, difference between 97 and 95 ? |
| { |
| pDataStream->SeekRel(3); |
| *pDataStream >> nHeaderByte; |
| nType=1; |
| } |
| fUnknown = nHeaderByte & 0x3; |
| fDropdownIndex = (nHeaderByte & 0x7C) >> 2; |
| *pDataStream >> nField; |
| fToolTip = nField & 0x01; |
| fNoMark = (nField & 0x02)>>1; |
| fUseSize = (nField & 0x04)>>2; |
| fNumbersOnly= (nField & 0x08)>>3; |
| fDateOnly = (nField & 0x10)>>4; |
| fUnused = (nField & 0xE0)>>5; |
| *pDataStream >> nSize; |
| |
| *pDataStream >> hpsCheckBox; |
| if (nType == 0) |
| pDataStream->SeekRel(2); //Guess |
| |
| rtl_TextEncoding eEnc = rRdr.eStructCharSet; |
| sTitle = !nType ? WW8ReadPString(*pDataStream, eEnc, true) |
| : WW8Read_xstz(*pDataStream, 0, true); |
| |
| if (nWhich == WW8_CT_CHECKBOX) |
| { |
| *pDataStream >> nDefaultChecked; |
| nChecked = nDefaultChecked; |
| |
| sal_uInt8 iRes = (nHeaderByte >> 2) & 0x1F; |
| switch (iRes) |
| { |
| case 1: //checked |
| nChecked = true; |
| break; |
| case 25: //undefined, Undefined checkboxes are treated as unchecked |
| case 0: //unchecked |
| nChecked = false; |
| break; |
| default: |
| ASSERT(!this, "unknown option, please report to cmc"); |
| break; |
| } |
| } |
| else if (nWhich == WW8_CT_DROPDOWN) |
| *pDataStream >> nChecked; |
| else |
| { |
| sDefault = !nType ? WW8ReadPString(*pDataStream, eEnc, true) |
| : WW8Read_xstz(*pDataStream, 0, true); |
| } |
| |
| sFormatting = !nType ? WW8ReadPString(*pDataStream, eEnc, true) |
| : WW8Read_xstz(*pDataStream, 0, true); |
| |
| sHelp = !nType ? WW8ReadPString(*pDataStream, eEnc, true) |
| : WW8Read_xstz(*pDataStream, 0, true); |
| |
| if (nWhich == WW8_CT_DROPDOWN) //is this the case ? |
| fToolTip = true; |
| |
| if( fToolTip ) |
| { |
| sToolTip = !nType ? WW8ReadPString(*pDataStream, eEnc, true) |
| : WW8Read_xstz(*pDataStream, 0, true); |
| } |
| |
| if (nWhich == WW8_CT_DROPDOWN) |
| { |
| bool bAllOk = true; |
| pDataStream->SeekRel(4 * (nType ? 2 : 1)); |
| sal_uInt16 nDummy; |
| *pDataStream >> nDummy; |
| sal_uInt32 nNoStrings; |
| if (!nType) |
| { |
| sal_uInt16 nWord95NoStrings; |
| *pDataStream >> nWord95NoStrings; |
| nNoStrings = nWord95NoStrings; |
| *pDataStream >> nWord95NoStrings; |
| if (nNoStrings != nWord95NoStrings) |
| bAllOk = false; |
| nNoStrings = nWord95NoStrings; |
| sal_uInt16 nDummy2; |
| *pDataStream >> nDummy2; |
| if (nDummy2 != 0) |
| bAllOk = false; |
| *pDataStream >> nDummy2; |
| if (nDummy2 != 0xA) |
| bAllOk = false; |
| if (!bAllOk) //Not as expected, don't risk it at all. |
| nNoStrings = 0; |
| for (sal_uInt16 nI = 0; nI < nNoStrings; ++nI) |
| pDataStream->SeekRel(2); |
| } |
| else |
| { |
| if (nDummy != 0xFFFF) |
| bAllOk = false; |
| *pDataStream >> nNoStrings; |
| } |
| ASSERT(bAllOk, |
| "Unknown formfield dropdown list structure. Report to cmc"); |
| if (!bAllOk) //Not as expected, don't risk it at all. |
| nNoStrings = 0; |
| maListEntries.reserve(nNoStrings); |
| for (sal_uInt32 nI = 0; nI < nNoStrings; ++nI) |
| { |
| String sEntry = !nType ? WW8ReadPString(*pDataStream, eEnc, false) |
| : WW8Read_xstz(*pDataStream, 0, false); |
| maListEntries.push_back(sEntry); |
| } |
| } |
| } |
| |
| WW8FormulaListBox::WW8FormulaListBox(SwWW8ImplReader &rR) |
| : WW8FormulaControl( CREATE_CONST_ASC(SL::aListBox), rR) |
| { |
| } |
| |
| //Miserable hack to get a hardcoded guesstimate of the size of a list dropdown |
| //box's first entry to set as the lists default size |
| awt::Size SwWW8ImplReader::MiserableDropDownFormHack(const String &rString, |
| uno::Reference<beans::XPropertySet>& rPropSet) |
| { |
| awt::Size aRet; |
| struct CtrlFontMapEntry |
| { |
| sal_uInt16 nWhichId; |
| const sal_Char* pPropNm; |
| }; |
| const CtrlFontMapEntry aMapTable[] = |
| { |
| { RES_CHRATR_COLOR, "TextColor" }, |
| { RES_CHRATR_FONT, "FontName" }, |
| { RES_CHRATR_FONTSIZE, "FontHeight" }, |
| { RES_CHRATR_WEIGHT, "FontWeight" }, |
| { RES_CHRATR_UNDERLINE, "FontUnderline" }, |
| { RES_CHRATR_CROSSEDOUT, "FontStrikeout" }, |
| { RES_CHRATR_POSTURE, "FontSlant" }, |
| { 0, 0 } |
| }; |
| |
| Font aFont; |
| uno::Reference< beans::XPropertySetInfo > xPropSetInfo = |
| rPropSet->getPropertySetInfo(); |
| |
| uno::Any aTmp; |
| for (const CtrlFontMapEntry* pMap = aMapTable; pMap->nWhichId; ++pMap) |
| { |
| bool bSet = true; |
| const SfxPoolItem* pItem = GetFmtAttr( pMap->nWhichId ); |
| ASSERT(pItem, "Impossible"); |
| if (!pItem) |
| continue; |
| |
| switch ( pMap->nWhichId ) |
| { |
| case RES_CHRATR_COLOR: |
| { |
| String pNm; |
| if (xPropSetInfo->hasPropertyByName(pNm = C2U("TextColor"))) |
| { |
| aTmp <<= (sal_Int32)((SvxColorItem*)pItem)->GetValue().GetColor(); |
| rPropSet->setPropertyValue(pNm, aTmp); |
| } |
| } |
| aFont.SetColor(((SvxColorItem*)pItem)->GetValue()); |
| break; |
| case RES_CHRATR_FONT: |
| { |
| const SvxFontItem *pFontItem = (SvxFontItem *)pItem; |
| String pNm; |
| if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontStyleName"))) |
| { |
| aTmp <<= rtl::OUString( pFontItem->GetStyleName()); |
| rPropSet->setPropertyValue( pNm, aTmp ); |
| } |
| if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontFamily"))) |
| { |
| aTmp <<= (sal_Int16)pFontItem->GetFamily(); |
| rPropSet->setPropertyValue( pNm, aTmp ); |
| } |
| if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontCharset"))) |
| { |
| aTmp <<= (sal_Int16)pFontItem->GetCharSet(); |
| rPropSet->setPropertyValue( pNm, aTmp ); |
| } |
| if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontPitch"))) |
| { |
| aTmp <<= (sal_Int16)pFontItem->GetPitch(); |
| rPropSet->setPropertyValue( pNm, aTmp ); |
| } |
| |
| aTmp <<= rtl::OUString( pFontItem->GetFamilyName()); |
| aFont.SetName( pFontItem->GetFamilyName() ); |
| aFont.SetStyleName( pFontItem->GetStyleName() ); |
| aFont.SetFamily( pFontItem->GetFamily() ); |
| aFont.SetCharSet( pFontItem->GetCharSet() ); |
| aFont.SetPitch( pFontItem->GetPitch() ); |
| } |
| break; |
| |
| case RES_CHRATR_FONTSIZE: |
| { |
| Size aSize( aFont.GetSize().Width(), |
| ((SvxFontHeightItem*)pItem)->GetHeight() ); |
| aTmp <<= ((float)aSize.Height()) / 20.0; |
| |
| aFont.SetSize(OutputDevice::LogicToLogic(aSize, MAP_TWIP, |
| MAP_100TH_MM)); |
| } |
| break; |
| |
| case RES_CHRATR_WEIGHT: |
| aTmp <<= (float)VCLUnoHelper::ConvertFontWeight( |
| ((SvxWeightItem*)pItem)->GetWeight() ); |
| aFont.SetWeight( ((SvxWeightItem*)pItem)->GetWeight() ); |
| break; |
| |
| case RES_CHRATR_UNDERLINE: |
| aTmp <<= (sal_Int16)(((SvxUnderlineItem*)pItem)->GetLineStyle()); |
| aFont.SetUnderline(((SvxUnderlineItem*)pItem)->GetLineStyle()); |
| break; |
| |
| case RES_CHRATR_CROSSEDOUT: |
| aTmp <<= (sal_Int16)( ((SvxCrossedOutItem*)pItem)->GetStrikeout() ); |
| aFont.SetStrikeout( ((SvxCrossedOutItem*)pItem)->GetStrikeout() ); |
| break; |
| |
| case RES_CHRATR_POSTURE: |
| aTmp <<= (sal_Int16)( ((SvxPostureItem*)pItem)->GetPosture() ); |
| aFont.SetItalic( ((SvxPostureItem*)pItem)->GetPosture() ); |
| break; |
| |
| default: |
| bSet = false; |
| break; |
| } |
| |
| if (bSet && xPropSetInfo->hasPropertyByName(C2U(pMap->pPropNm))) |
| rPropSet->setPropertyValue(C2U(pMap->pPropNm), aTmp); |
| } |
| // now calculate the size of the control |
| OutputDevice* pOut = Application::GetDefaultDevice(); |
| ASSERT(pOut, "Impossible"); |
| if (pOut) |
| { |
| pOut->Push( PUSH_FONT | PUSH_MAPMODE ); |
| pOut->SetMapMode( MapMode( MAP_100TH_MM )); |
| pOut->SetFont( aFont ); |
| aRet.Width = pOut->GetTextWidth(rString); |
| aRet.Width += 500; //plus size of button, total hack territory |
| aRet.Height = pOut->GetTextHeight(); |
| pOut->Pop(); |
| } |
| return aRet; |
| } |
| |
| sal_Bool WW8FormulaListBox::Import(const uno::Reference < |
| lang::XMultiServiceFactory> &rServiceFactory, |
| uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz ) |
| { |
| uno::Reference<uno::XInterface> xCreate = rServiceFactory->createInstance( |
| C2U("com.sun.star.form.component.ComboBox")); |
| if( !xCreate.is() ) |
| return sal_False; |
| |
| rFComp = uno::Reference<form::XFormComponent>(xCreate, uno::UNO_QUERY); |
| if( !rFComp.is() ) |
| return sal_False; |
| |
| uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY); |
| |
| uno::Any aTmp; |
| if (sTitle.Len()) |
| aTmp <<= rtl::OUString(sTitle); |
| else |
| aTmp <<= rtl::OUString(sName); |
| xPropSet->setPropertyValue(C2U("Name"), aTmp ); |
| |
| if (sToolTip.Len()) |
| { |
| aTmp <<= rtl::OUString(sToolTip); |
| xPropSet->setPropertyValue(C2U("HelpText"), aTmp ); |
| } |
| |
| sal_Bool bDropDown(sal_True); |
| xPropSet->setPropertyValue(C2U("Dropdown"), cppu::bool2any(bDropDown)); |
| |
| if (!maListEntries.empty()) |
| { |
| sal_uInt32 nLen = maListEntries.size(); |
| uno::Sequence< ::rtl::OUString > aListSource(nLen); |
| for (sal_uInt32 nI = 0; nI < nLen; ++nI) |
| aListSource[nI] = rtl::OUString(maListEntries[nI]); |
| aTmp <<= aListSource; |
| xPropSet->setPropertyValue(C2U("StringItemList"), aTmp ); |
| |
| if (fDropdownIndex < nLen) |
| { |
| aTmp <<= aListSource[fDropdownIndex]; |
| } |
| else |
| { |
| aTmp <<= aListSource[0]; |
| } |
| |
| xPropSet->setPropertyValue(C2U("DefaultText"), aTmp ); |
| |
| rSz = rRdr.MiserableDropDownFormHack(maListEntries[0], xPropSet); |
| } |
| else |
| { |
| static const sal_Unicode aBlank[] = |
| { |
| 0x2002,0x2002,0x2002,0x2002,0x2002 |
| }; |
| rSz = rRdr.MiserableDropDownFormHack(String(aBlank), xPropSet); |
| } |
| |
| return sal_True; |
| } |
| |
| WW8FormulaCheckBox::WW8FormulaCheckBox(SwWW8ImplReader &rR) |
| : WW8FormulaControl( CREATE_CONST_ASC(SL::aCheckBox), rR) |
| { |
| } |
| |
| static void lcl_AddToPropertyContainer |
| (uno::Reference<beans::XPropertySet> xPropSet, |
| const rtl::OUString & rPropertyName, const rtl::OUString & rValue) |
| { |
| uno::Reference<beans::XPropertySetInfo> xPropSetInfo = |
| xPropSet->getPropertySetInfo(); |
| if (xPropSetInfo.is() && |
| ! xPropSetInfo->hasPropertyByName(rPropertyName)) |
| { |
| uno::Reference<beans::XPropertyContainer> |
| xPropContainer(xPropSet, uno::UNO_QUERY); |
| uno::Any aAny(C2U("")); |
| xPropContainer->addProperty |
| (rPropertyName, |
| static_cast<sal_Int16>(beans::PropertyAttribute::BOUND | |
| beans::PropertyAttribute::REMOVABLE), |
| aAny); |
| } |
| |
| uno::Any aAnyValue(rValue); |
| xPropSet->setPropertyValue(rPropertyName, aAnyValue ); |
| } |
| |
| sal_Bool WW8FormulaCheckBox::Import(const uno::Reference < |
| lang::XMultiServiceFactory> &rServiceFactory, |
| uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz ) |
| { |
| uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance( |
| C2U("com.sun.star.form.component.CheckBox")); |
| if( !xCreate.is() ) |
| return sal_False; |
| |
| rFComp = uno::Reference< form::XFormComponent >( xCreate, uno::UNO_QUERY ); |
| if( !rFComp.is() ) |
| return sal_False; |
| |
| uno::Reference< beans::XPropertySet > xPropSet( xCreate, uno::UNO_QUERY ); |
| |
| rSz.Width = 16 * hpsCheckBox; |
| rSz.Height = 16 * hpsCheckBox; |
| |
| uno::Any aTmp; |
| if (sTitle.Len()) |
| aTmp <<= rtl::OUString(sTitle); |
| else |
| aTmp <<= rtl::OUString(sName); |
| xPropSet->setPropertyValue(C2U("Name"), aTmp ); |
| |
| aTmp <<= (sal_Int16)nChecked; |
| xPropSet->setPropertyValue(C2U("DefaultState"), aTmp); |
| |
| if( sToolTip.Len() ) |
| lcl_AddToPropertyContainer(xPropSet, C2U("HelpText"), sToolTip); |
| |
| if( sHelp.Len() ) |
| lcl_AddToPropertyContainer(xPropSet, C2U("HelpF1Text"), sHelp); |
| |
| return sal_True; |
| |
| } |
| |
| WW8FormulaEditBox::WW8FormulaEditBox(SwWW8ImplReader &rR) |
| : WW8FormulaControl( CREATE_CONST_ASC(SL::aTextField) ,rR) |
| { |
| } |
| |
| sal_Bool SwMSConvertControls::InsertControl( |
| const uno::Reference< form::XFormComponent > & rFComp, |
| const awt::Size& rSize, uno::Reference< drawing::XShape > *pShape, |
| sal_Bool bFloatingCtrl) |
| { |
| const uno::Reference< container::XIndexContainer > &rComps = GetFormComps(); |
| uno::Any aTmp( &rFComp, ::getCppuType((const uno::Reference< |
| form::XFormComponent >*)0) ); |
| rComps->insertByIndex( rComps->getCount(), aTmp ); |
| |
| const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory = |
| GetServiceFactory(); |
| if( !rServiceFactory.is() ) |
| return sal_False; |
| |
| uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance( |
| C2U("com.sun.star.drawing.ControlShape")); |
| if( !xCreate.is() ) |
| return sal_False; |
| |
| uno::Reference< drawing::XShape > xShape = |
| uno::Reference< drawing::XShape >(xCreate, uno::UNO_QUERY); |
| |
| DBG_ASSERT(xShape.is(), "XShape nicht erhalten"); |
| xShape->setSize(rSize); |
| |
| uno::Reference< beans::XPropertySet > xShapePropSet( |
| xCreate, uno::UNO_QUERY ); |
| |
| //I lay a small bet that this will change to |
| //sal_Int16 nTemp=TextContentAnchorType::AS_CHARACTER; |
| sal_Int16 nTemp; |
| if (bFloatingCtrl) |
| nTemp= text::TextContentAnchorType_AT_PARAGRAPH; |
| else |
| nTemp= text::TextContentAnchorType_AS_CHARACTER; |
| |
| aTmp <<= nTemp; |
| xShapePropSet->setPropertyValue(C2U("AnchorType"), aTmp ); |
| |
| nTemp= text::VertOrientation::TOP; |
| aTmp <<= nTemp; |
| xShapePropSet->setPropertyValue(C2U("VertOrient"), aTmp ); |
| |
| uno::Reference< text::XText > xDummyTxtRef; |
| uno::Reference< text::XTextRange > xTxtRg = |
| new SwXTextRange( *pPaM, xDummyTxtRef ); |
| |
| aTmp.setValue(&xTxtRg,::getCppuType(( |
| uno::Reference< text::XTextRange >*)0)); |
| xShapePropSet->setPropertyValue(C2U("TextRange"), aTmp ); |
| |
| // Das Control-Model am Control-Shape setzen |
| uno::Reference< drawing::XControlShape > xControlShape( xShape, |
| uno::UNO_QUERY ); |
| uno::Reference< awt::XControlModel > xControlModel( rFComp, |
| uno::UNO_QUERY ); |
| xControlShape->setControl( xControlModel ); |
| |
| if (pShape) |
| *pShape = xShape; |
| |
| return sal_True; |
| } |
| |
| /* vi:set tabstop=4 shiftwidth=4 expandtab: */ |
| |
| |
| |