update dev300-m58
[ooovba.git] / sw / source / filter / ww8 / ww8par3.cxx
blobbc24b73793f03e3ae03209e14397f2685876ed8e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8par3.cxx,v $
10 * $Revision: 1.93.92.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <svtools/itemiter.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/outdev.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <com/sun/star/form/XFormsSupplier.hpp>
42 #include <com/sun/star/form/XForm.hpp>
43 #include <com/sun/star/form/XImageProducerSupplier.hpp>
44 #include <com/sun/star/form/XFormController.hpp>
45 #include <com/sun/star/frame/XStorable.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/drawing/XConnectableShape.hpp>
48 #include <com/sun/star/drawing/XConnectorShape.hpp>
49 #include <com/sun/star/drawing/XShape.hpp>
50 #include <com/sun/star/drawing/XControlShape.hpp>
51 #include <com/sun/star/drawing/XShapeAligner.hpp>
52 #include <com/sun/star/drawing/XShapeGroup.hpp>
53 #include <com/sun/star/drawing/XUniversalShapeDescriptor.hpp>
54 #include <com/sun/star/drawing/XShapeMirror.hpp>
55 #include <com/sun/star/drawing/XShapeArranger.hpp>
56 #include <com/sun/star/drawing/XDrawPage.hpp>
57 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
60 #include <com/sun/star/container/XIndexContainer.hpp>
61 #include <com/sun/star/text/VertOrientation.hpp>
62 #include <com/sun/star/text/TextContentAnchorType.hpp>
63 #include <comphelper/extract.hxx>
64 #include <com/sun/star/beans/XPropertyContainer.hpp>
65 #include <com/sun/star/beans/PropertyAttribute.hpp>
67 #include <algorithm>
68 #include <functional>
69 #include <hintids.hxx>
70 #include <svx/fontitem.hxx>
71 #include <svx/lrspitem.hxx>
72 #include <svx/fhgtitem.hxx>
73 #include <svx/colritem.hxx>
74 #include <svx/wghtitem.hxx>
75 #include <svx/crsditem.hxx>
76 #include <svx/udlnitem.hxx>
77 #include <svx/postitem.hxx>
78 #include <svx/msocximex.hxx>
79 #include <errhdl.hxx>
80 #include <unoobj.hxx>
81 #include <doc.hxx>
82 #include <docary.hxx>
83 #include <docsh.hxx>
84 #include <numrule.hxx>
85 #include <paratr.hxx>
86 #include <charatr.hxx>
87 #include <charfmt.hxx>
88 #include <ndtxt.hxx>
89 #include <expfld.hxx>
90 #include <fmtfld.hxx>
91 #include <flddropdown.hxx>
92 #include "writerhelper.hxx"
93 #include "writerwordglue.hxx"
94 #include "ww8par.hxx"
95 #include "ww8par2.hxx" // wg. Listen-Attributen in Styles
97 #include <IMark.hxx>
98 #include <svtools/fltrcfg.hxx>
99 #include <ecmaflds.hxx>
101 #include <stdio.h>
103 using namespace com::sun::star;
104 using namespace sw::util;
105 using namespace sw::types;
106 using namespace sw::mark;
108 //-----------------------------------------
109 // UNO-Controls
110 //-----------------------------------------
112 //cmc, OCX i.e. word 97 form controls
113 eF_ResT SwWW8ImplReader::Read_F_OCX( WW8FieldDesc*, String& )
115 if( bObj && nPicLocFc )
116 nObjLocFc = nPicLocFc;
117 bEmbeddObj = true;
118 return FLD_TEXT;
121 eF_ResT SwWW8ImplReader::Read_F_FormTextBox( WW8FieldDesc* pF, String& rStr )
123 WW8FormulaEditBox aFormula(*this);
125 if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) {
126 ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_EDIT);
129 /* #80205#
130 Here we have a small complication. This formula control contains
131 the default text that is displayed if you edit the form field in
132 the "default text" area. But MSOffice does not display that
133 information, instead it display the result of the field,
134 MSOffice just uses the default text of the control as its
135 initial value for the displayed default text. So we will swap in
136 the field result into the formula here in place of the default
137 text.
140 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
141 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
143 if (!bUseEnhFields) {
144 aFormula.sDefault = GetFieldResult(pF);
146 #if 0 // why not? (flr)
147 //substituting Unicode spacing 0x2002 with double space for layout
148 aFormula.sDefault.SearchAndReplaceAll(
149 String(static_cast< sal_Unicode >(0x2002)),
150 CREATE_CONST_ASC(" "));
151 #endif
153 SwInputField aFld((SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
154 aFormula.sDefault , aFormula.sTitle , INP_TXT, 0 );
155 aFld.SetHelp(aFormula.sHelp);
156 aFld.SetToolTip(aFormula.sToolTip);
158 rDoc.Insert(*pPaM, SwFmtFld(aFld), 0);
159 return FLD_OK;
160 } else {
161 WW8PLCFx_Book* pB = pPlcxMan->GetBook();
162 String aBookmarkName;
163 if (pB!=NULL) {
164 WW8_CP currentCP=pF->nSCode;
165 WW8_CP currentLen=pF->nLen;
167 USHORT bkmFindIdx;
168 String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
170 if (aBookmarkFind.Len()>0) {
171 pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark bookmark as consumed, such that tl'll not get inserted as a "normal" bookmark again
172 if (aBookmarkFind.Len()>0) {
173 aBookmarkName=aBookmarkFind;
178 if (pB!=NULL && aBookmarkName.Len()==0) {
179 aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
183 if (aBookmarkName.Len()>0) {
184 maFieldStack.back().SetBookmarkName(aBookmarkName);
185 maFieldStack.back().SetBookmarkType(::rtl::OUString::createFromAscii(ECMA_FORMTEXT));
186 maFieldStack.back().AddParam(::rtl::OUString::createFromAscii("Description"), aFormula.sToolTip);
187 maFieldStack.back().AddParam(::rtl::OUString::createFromAscii("Name"), aFormula.sTitle);
189 return FLD_TEXT;
193 eF_ResT SwWW8ImplReader::Read_F_FormCheckBox( WW8FieldDesc* pF, String& rStr )
195 WW8FormulaCheckBox aFormula(*this);
197 if (!pFormImpl)
198 pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
200 if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
201 ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_CHECKBOX);
202 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
203 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
205 if (!bUseEnhFields) {
206 pFormImpl->InsertFormula(aFormula);
207 return FLD_OK;
208 } else {
209 String aBookmarkName;
210 WW8PLCFx_Book* pB = pPlcxMan->GetBook();
211 if (pB!=NULL) {
212 WW8_CP currentCP=pF->nSCode;
213 WW8_CP currentLen=pF->nLen;
215 USHORT bkmFindIdx;
216 String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
218 if (aBookmarkFind.Len()>0) {
219 pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
220 if (aBookmarkFind.Len()>0) {
221 aBookmarkName=aBookmarkFind;
226 if (pB!=NULL && aBookmarkName.Len()==0) {
227 aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
230 if (aBookmarkName.Len()>0)
232 IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
233 IFieldmark* pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeNoTextFieldBookmark(
234 *pPaM, aBookmarkName,
235 rtl::OUString::createFromAscii( ECMA_FORMCHECKBOX ) ) );
236 ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
237 if (pFieldmark!=NULL) {
238 pFieldmark->addParam(
239 rtl::OUString::createFromAscii(ECMA_FORMCHECKBOX_NAME),
240 rtl::OUString( aFormula.sTitle ) );
241 pFieldmark->addParam(
242 rtl::OUString::createFromAscii(ECMA_FORMCHECKBOX_HELPTEXT), aFormula.sToolTip);
243 pFieldmark->addParam(
244 rtl::OUString::createFromAscii(ECMA_FORMCHECKBOX_CHECKED),
245 ::rtl::OUString::createFromAscii(aFormula.nChecked!=0?"on":"off"));
246 // set field data here...
249 return FLD_OK;
253 eF_ResT SwWW8ImplReader::Read_F_FormListBox( WW8FieldDesc* pF, String& rStr)
255 WW8FormulaListBox aFormula(*this);
257 if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
258 ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_DROPDOWN);
260 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
261 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
263 if (!bUseEnhFields) {
264 SwDropDownField aFld(
265 (SwDropDownFieldType*)rDoc.GetSysFldType(RES_DROPDOWN));
267 aFld.SetName(aFormula.sTitle);
268 aFld.SetHelp(aFormula.sHelp);
269 aFld.SetToolTip(aFormula.sToolTip);
271 if (!aFormula.maListEntries.empty())
273 aFld.SetItems(aFormula.maListEntries);
274 int nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size()
275 ? aFormula.fDropdownIndex : 0;
276 aFld.SetSelectedItem(aFormula.maListEntries[nIndex]);
279 rDoc.Insert(*pPaM, SwFmtFld(aFld), 0);
280 return FLD_OK;
281 } else {
282 //@TODO fix: copy pasting here!!!!!!!!!!!!!!
283 //REVIEW: don't let this throught.... sometime I forget to get rid of my proof of concept stuff. Please kindly remind me!!!!!
285 String aBookmarkName;
286 WW8PLCFx_Book* pB = pPlcxMan->GetBook();
287 if (pB!=NULL) {
288 WW8_CP currentCP=pF->nSCode;
289 WW8_CP currentLen=pF->nLen;
291 USHORT bkmFindIdx;
292 String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
294 if (aBookmarkFind.Len()>0) {
295 pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
296 if (aBookmarkFind.Len()>0) {
297 aBookmarkName=aBookmarkFind;
302 if (pB!=NULL && aBookmarkName.Len()==0) {
303 aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
306 if (aBookmarkName.Len()>0)
308 IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
309 IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeNoTextFieldBookmark(
310 *pPaM, aBookmarkName, ::rtl::OUString::createFromAscii( ECMA_FORMDROPDOWN ) ) );
311 ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
312 if ( pFieldmark != NULL ) {
313 rtl::OUString sListEntry=rtl::OUString::createFromAscii( ECMA_FORMDROPDOWN_LISTENTRY );
314 std::vector<String>::iterator it = aFormula.maListEntries.begin();
315 for( ; it != aFormula.maListEntries.end(); it++ )
316 pFieldmark->addParam(sListEntry, *it, false);
318 int nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0;
319 pFieldmark->addParam(ECMA_FORMDROPDOWN_RESULT, nIndex);
320 // set field data here...
324 return FLD_OK;
329 eF_ResT SwWW8ImplReader::Read_F_HTMLControl( WW8FieldDesc* pF, String& rStr)
331 if( bObj && nPicLocFc )
332 nObjLocFc = nPicLocFc;
333 bEmbeddObj = true;
334 return FLD_TEXT;
337 void SwWW8ImplReader::DeleteFormImpl()
339 delete pFormImpl, pFormImpl = 0;
342 //----------------------------------------------------------------------------
343 // WW8ListManager oeffentliche Methoden stehen ganz am Ende
344 //------------------------- ============ --------------- ============ --------
348 // Hilfs-Deklarationen ///////////////////////////////////////////////////////
350 // Style Id's for each level
351 typedef sal_uInt16 WW8aIdSty[WW8ListManager::nMaxLevel];
352 // Zeichenattribute aus GrpprlChpx
353 typedef SfxItemSet* WW8aISet[WW8ListManager::nMaxLevel];
354 // Zeichen Style Pointer
355 typedef SwCharFmt* WW8aCFmt[WW8ListManager::nMaxLevel];
357 struct WW8LST // nur DIE Eintraege, die WIR benoetigen!
359 WW8aIdSty aIdSty; // Style Id's for each level,
360 // nIStDNil if no style linked
361 sal_uInt32 nIdLst; // Unique List ID
362 sal_uInt32 nTplC; // Unique template code - Was ist das bloss?
363 BYTE bSimpleList:1; // Flag: Liste hat nur EINEN Level
364 BYTE bRestartHdn:1; // WW6-Kompatibilitaets-Flag:
365 // true if the list should start numbering over
366 }; // at the beginning of each section
368 struct WW8LFO // nur DIE Eintraege, die WIR benoetigen!
370 SwNumRule* pNumRule; // Parent NumRule
371 sal_uInt32 nIdLst; // Unique List ID
372 sal_uInt8 nLfoLvl; // count of levels whose format is overridden
373 bool bSimpleList;
376 struct WW8LVL // nur DIE Eintraege, die WIR benoetigen!
378 long nStartAt; // start at value for this value
379 long nV6DxaSpace;// Ver6-Compatible: min Space between Num anf text::Paragraph
380 long nV6Indent; // Ver6-Compatible: Breite des Prefix Textes; ggfs. zur
381 // Definition d. Erstzl.einzug nutzen!
382 // Absatzattribute aus GrpprlPapx
383 sal_uInt16 nDxaLeft; // linker Einzug
384 short nDxaLeft1; // Erstzeilen-Einzug
386 sal_uInt8 nNFC; // number format code
387 // Offset der Feldkodes im Num-X-String
388 sal_uInt8 aOfsNumsXCH[WW8ListManager::nMaxLevel];
389 sal_uInt8 nLenGrpprlChpx; // length, in bytes, of the LVL's grpprlChpx
390 sal_uInt8 nLenGrpprlPapx; // length, in bytes, of the LVL's grpprlPapx
391 sal_uInt8 nAlign: 2; // alignment (left, right, centered) of the number
392 BYTE bLegal: 1; // egal
393 BYTE bNoRest:1; // egal
394 BYTE bV6Prev:1; // Ver6-Compatible: number will include previous levels
395 BYTE bV6PrSp:1; // Ver6-Compatible: egal
396 BYTE bV6: 1; // falls true , beachte die V6-Compatible Eintraege!
397 sal_uInt8 bDummy: 1; // (macht das Byte voll)
401 struct WW8LFOLVL
403 long nStartAt; // start-at value if bFormat==false and bStartAt == true
404 // (if bFormat==true, the start-at is stored in the LVL)
405 sal_uInt8 nLevel; // the level to be overridden
406 // dieses Byte ist _absichtlich_ nicht in das folgende Byte hineingepackt !!
407 // (siehe Kommentar unten bei struct WW8LFOInfo)
409 BYTE bStartAt :1; // true if the start-at value is overridden
410 BYTE bFormat :1; // true if the formatting is overriden
412 WW8LFOLVL() :
413 nStartAt(1), nLevel(0), bStartAt(1), bFormat(0) {}
416 // in den ListenInfos zu speichernde Daten ///////////////////////////////////
418 struct WW8LSTInfo // sortiert nach nIdLst (in WW8 verwendete Listen-Id)
420 std::vector<ww::bytes> maParaSprms;
421 WW8aIdSty aIdSty; // Style Id's for each level
422 WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
423 WW8aCFmt aCharFmt; // Zeichen Style Pointer
425 SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
426 sal_uInt32 nIdLst; // WW8Id dieser Liste
427 BYTE bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
428 BYTE bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
429 // oder beim Reader-Ende geloescht werden sollte
431 WW8LSTInfo(SwNumRule* pNumRule_, WW8LST& aLST)
432 : pNumRule(pNumRule_), nIdLst(aLST.nIdLst),
433 bSimpleList(aLST.bSimpleList), bUsedInDoc(0)
435 memcpy( aIdSty, aLST.aIdSty, sizeof( aIdSty ));
436 memset(&aItemSet, 0, sizeof( aItemSet ));
437 memset(&aCharFmt, 0, sizeof( aCharFmt ));
442 // in den ListenFormatOverrideInfos zu speichernde Daten /////////////////////
444 struct WW8LFOInfo // unsortiert, d.h. Reihenfolge genau wie im WW8 Stream
446 std::vector<ww::bytes> maParaSprms;
447 std::vector<WW8LFOLVL> maOverrides;
448 SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
449 // entweder: Liste in LSTInfos oder eigene Liste
450 // (im Ctor erstmal die aus den LSTInfos merken)
452 sal_uInt32 nIdLst; // WW8-Id der betreffenden Liste
453 sal_uInt8 nLfoLvl; // count of levels whose format is overridden
454 // Ja, ich natuerlich koennten wir nLfoLvl (mittels :4) noch in das folgende
455 // Byte mit hineinpacken, doch waere das eine ziemliche Fehlerquelle,
456 // an dem Tag, wo MS ihr Listenformat auf mehr als 15 Level aufbohren.
458 BYTE bOverride :1;// Flag, ob die NumRule nicht in maLSTInfos steht,
459 // sondern fuer pLFOInfos NEU angelegt wurde
460 BYTE bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
461 BYTE bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
462 // oder beim Reader-Ende geloescht werden sollte
463 BYTE bLSTbUIDSet :1;// Flag, ob bUsedInDoc in maLSTInfos gesetzt wurde,
464 // und nicht nochmals gesetzt zu werden braucht
465 WW8LFOInfo(const WW8LFO& rLFO);
468 WW8LFOInfo::WW8LFOInfo(const WW8LFO& rLFO)
469 : maParaSprms(WW8ListManager::nMaxLevel),
470 maOverrides(WW8ListManager::nMaxLevel), pNumRule(rLFO.pNumRule),
471 nIdLst(rLFO.nIdLst), nLfoLvl(rLFO.nLfoLvl),
472 bOverride(rLFO.nLfoLvl ? true : false), bSimpleList(rLFO.bSimpleList),
473 bUsedInDoc(0), bLSTbUIDSet(0)
477 SV_IMPL_PTRARR( WW8LFOInfos, WW8LFOInfo_Ptr );
480 // Hilfs-Methoden ////////////////////////////////////////////////////////////
483 // finden der Sprm-Parameter-Daten, falls Sprm im Grpprl enthalten
484 sal_uInt8* WW8ListManager::GrpprlHasSprm(sal_uInt16 nId, sal_uInt8& rSprms,
485 sal_uInt8 nLen)
487 sal_uInt8* pSprms = &rSprms;
488 USHORT i=0;
489 while (i < nLen)
491 sal_uInt16 nAktId = maSprmParser.GetSprmId(pSprms);
492 if( nAktId == nId ) // Sprm found
493 return pSprms + maSprmParser.DistanceToData(nId);
495 // gib Zeiger auf Daten
496 USHORT x = maSprmParser.GetSprmSize(nAktId, pSprms);
497 i = i + x;
498 pSprms += x;
500 return 0; // Sprm not found
503 class ListWithId : public std::unary_function<const WW8LSTInfo *, bool>
505 private:
506 sal_uInt32 mnIdLst;
507 public:
508 explicit ListWithId(sal_uInt32 nIdLst) : mnIdLst(nIdLst) {}
509 bool operator() (const WW8LSTInfo *pEntry) const
510 { return (pEntry->nIdLst == mnIdLst); }
513 // Zugriff ueber die List-Id des LST Eintrags
514 WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const
516 std::vector<WW8LSTInfo *>::const_iterator aResult =
517 std::find_if(maLSTInfos.begin(),maLSTInfos.end(),ListWithId(nIdLst));
518 if (aResult == maLSTInfos.end())
519 return 0;
520 return *aResult;
523 void lcl_CopyGreaterEight(String &rDest, String &rSrc,
524 xub_StrLen nStart, xub_StrLen nLen = STRING_LEN)
526 if (nLen == STRING_LEN)
527 nLen = rSrc.Len();
528 for (xub_StrLen nI = nStart; nI < nLen; ++nI)
530 sal_Unicode nChar = rSrc.GetChar(nI);
531 if (nChar > WW8ListManager::nMaxLevel)
532 rDest.Append(nChar);
536 bool WW8ListManager::ReadLVL(SwNumFmt& rNumFmt, SfxItemSet*& rpItemSet,
537 sal_uInt16 nLevelStyle, bool bSetStartNo,
538 std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
539 ww::bytes &rParaSprms)
541 sal_uInt8 aBits1;
542 sal_uInt16 nStartNo = 0; // Start-Nr. fuer den Writer
543 SvxExtNumType eType; // Writer-Num-Typ
544 SvxAdjust eAdj; // Ausrichtung (Links/rechts/zent.)
545 sal_Unicode cBullet(0x2190); // default safe bullet
546 String sPrefix;
547 String sPostfix;
548 WW8LVL aLVL;
550 // 1. LVLF einlesen
552 memset(&aLVL, 0, sizeof( aLVL ));
553 rSt >> aLVL.nStartAt;
554 rSt >> aLVL.nNFC;
555 rSt >> aBits1;
556 if( 0 != rSt.GetError() ) return false;
557 aLVL.nAlign = (aBits1 & 0x03);
558 if( aBits1 & 0x10 ) aLVL.bV6Prev = true;
559 if( aBits1 & 0x20 ) aLVL.bV6PrSp = true;
560 if( aBits1 & 0x40 ) aLVL.bV6 = true;
561 bool bLVLOkB = true;
562 sal_uInt8 nLevelB = 0;
563 for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
565 rSt >> aLVL.aOfsNumsXCH[ nLevelB ];
566 if( 0 != rSt.GetError() )
568 bLVLOkB = false;
569 break;
573 if( !bLVLOkB )
574 return false;
576 sal_uInt8 ixchFollow;
577 rSt >> ixchFollow;
578 if (ixchFollow == 0)
579 rReader.maTracer.Log(sw::log::eTabInNumbering);
580 rSt >> aLVL.nV6DxaSpace;
581 rSt >> aLVL.nV6Indent;
582 rSt >> aLVL.nLenGrpprlChpx;
583 rSt >> aLVL.nLenGrpprlPapx;
584 rSt.SeekRel( 2 );
585 if( 0 != rSt.GetError()) return false;
588 // 2. ggfs. PAPx einlesen und nach Einzug-Werten suchen
590 // --> OD 2008-06-04 #i86652# - read tab setting
591 short nTabPos = 0;
592 // <--
593 if( aLVL.nLenGrpprlPapx )
595 sal_uInt8 aGrpprlPapx[ 255 ];
596 if(aLVL.nLenGrpprlPapx != rSt.Read(&aGrpprlPapx,aLVL.nLenGrpprlPapx))
597 return false;
598 // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
599 sal_uInt8* pSprm;
600 if (
601 (0 != (pSprm = GrpprlHasSprm(0x840F,aGrpprlPapx[0],aLVL.nLenGrpprlPapx))) ||
602 (0 != (pSprm = GrpprlHasSprm(0x845E,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)))
605 sal_uInt8 *pBegin = pSprm-2;
606 for(int i=0;i<4;++i)
607 rParaSprms.push_back(*pBegin++);
608 short nDxaLeft = SVBT16ToShort( pSprm );
609 aLVL.nDxaLeft = (0 < nDxaLeft) ? (sal_uInt16)nDxaLeft
610 : (sal_uInt16)(-nDxaLeft);
613 // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
614 if (
615 (0 != (pSprm = GrpprlHasSprm(0x8411,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) ||
616 (0 != (pSprm = GrpprlHasSprm(0x8460,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
619 sal_uInt8 *pBegin = pSprm-2;
620 for(int i=0;i<4;++i)
621 rParaSprms.push_back(*pBegin++);
622 aLVL.nDxaLeft1 = SVBT16ToShort( pSprm );
625 // --> OD 2008-06-04 #i86652# - read tab setting
626 if(0 != (pSprm = GrpprlHasSprm(0xC615,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
628 bool bDone = false;
629 if (*(pSprm-1) == 5)
631 if (*pSprm++ == 0) //nDel
633 if (*pSprm++ == 1) //nIns
635 nTabPos = SVBT16ToShort(pSprm);
636 pSprm+=2;
637 if (*pSprm == 6) //type
639 bDone = true;
644 ASSERT(bDone, "tab setting in numbering is "
645 "of unexpected configuration");
647 if ( rNumFmt.GetPositionAndSpaceMode() ==
648 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
650 // If there is a tab setting with a larger value, then use that.
651 // Ideally we would allow tabs to be used in numbering fields and set
652 // this on the containing paragraph which would make it actually work
653 // most of the time.
654 if ( nTabPos != 0 )
656 const USHORT nDesired = aLVL.nDxaLeft + aLVL.nDxaLeft1;
658 bool bDoAdjust = false;
659 if ( nDesired < aLVL.nDxaLeft )
661 if ( nDesired < nTabPos && nTabPos < aLVL.nDxaLeft )
663 bDoAdjust = true;
666 else
668 if ( aLVL.nDxaLeft < nTabPos && nTabPos < nDesired )
670 bDoAdjust = true;
674 if (bDoAdjust)
676 aLVL.nDxaLeft = (0 < nTabPos)
677 ? (sal_uInt16)nTabPos
678 : (sal_uInt16)(-nTabPos);
680 aLVL.nDxaLeft1 = nDesired - aLVL.nDxaLeft;
684 // <--
687 // 3. ggfs. CHPx einlesen und
689 if( aLVL.nLenGrpprlChpx )
691 sal_uInt8 aGrpprlChpx[ 255 ];
692 memset(&aGrpprlChpx, 0, sizeof( aGrpprlChpx ));
693 if(aLVL.nLenGrpprlChpx != rSt.Read(&aGrpprlChpx, aLVL.nLenGrpprlChpx))
694 return false;
695 // neues ItemSet fuer die Zeichenattribute anlegen
696 rpItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN,
697 RES_CHRATR_END - 1 );
699 // Reader-ItemSet-Pointer darauf zeigen lassen
700 rReader.SetAktItemSet( rpItemSet );
701 // Reader-Style auf den Style dieses Levels setzen
702 sal_uInt16 nOldColl = rReader.GetNAktColl();
703 sal_uInt16 nNewColl = nLevelStyle;
704 if (ww::stiNil == nNewColl)
705 nNewColl = 0;
706 rReader.SetNAktColl( nNewColl );
708 // Nun den GrpprlChpx einfach durchnudeln: die Read_xy() Methoden
709 // in WW8PAR6.CXX rufen ganz normal ihr NewAttr() oder GetFmtAttr()
710 // und diese merken am besetzten Reader-ItemSet-Pointer, dass dieser
711 // spezielle ItemSet relevant ist - und nicht ein Stack oder Style!
712 USHORT nOldFlags1 = rReader.GetToggleAttrFlags();
713 USHORT nOldFlags2 = rReader.GetToggleBiDiAttrFlags();
714 short nLen = aLVL.nLenGrpprlChpx;
715 sal_uInt8* pSprms1 = &aGrpprlChpx[0];
716 while (0 < nLen)
718 sal_uInt16 nL1 = rReader.ImportSprm( pSprms1 );
719 nLen = nLen - nL1;
720 pSprms1 += nL1;
722 // Reader-ItemSet-Pointer und Reader-Style zuruecksetzen
723 rReader.SetAktItemSet( 0 );
724 rReader.SetNAktColl( nOldColl );
725 rReader.SetToggleAttrFlags(nOldFlags1);
726 rReader.SetToggleBiDiAttrFlags(nOldFlags2);
729 // 4. den Nummerierungsstring einlesen: ergibt Prefix und Postfix
731 String sNumString(WW8Read_xstz(rSt, 0, false));
734 // 5. gelesene Werte in Writer Syntax umwandeln
736 if( 0 <= aLVL.nStartAt )
737 nStartNo = (sal_uInt16)aLVL.nStartAt;
739 switch( aLVL.nNFC )
741 case 0:
742 eType = SVX_NUM_ARABIC;
743 break;
744 case 1:
745 eType = SVX_NUM_ROMAN_UPPER;
746 break;
747 case 2:
748 eType = SVX_NUM_ROMAN_LOWER;
749 break;
750 case 3:
751 eType = SVX_NUM_CHARS_UPPER_LETTER_N;
752 break;
753 case 4:
754 eType = SVX_NUM_CHARS_LOWER_LETTER_N;
755 break;
756 case 5:
757 // eigentlich: ORDINAL
758 eType = SVX_NUM_ARABIC;
759 break;
760 case 23:
761 case 25: //#114412#
762 eType = SVX_NUM_CHAR_SPECIAL;
763 break;
764 case 255:
765 eType = SVX_NUM_NUMBER_NONE;
766 break;
767 default:
768 // take default
769 eType = SVX_NUM_ARABIC;
770 break;
773 //If a number level is not going to be used, then record this fact
774 if (SVX_NUM_NUMBER_NONE == eType)
775 rNotReallyThere[nLevel] = true;
778 If a number level was not used (i.e. is in NotReallyThere), and that
779 number level appears at one of the positions in the display string of the
780 list, then it effectively is not there at all. So remove that level entry
781 from a copy of the aOfsNumsXCH.
783 std::vector<sal_uInt8> aOfsNumsXCH;
784 typedef std::vector<sal_uInt8>::iterator myIter;
785 aOfsNumsXCH.reserve(nMaxLevel);
787 for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
788 aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]);
790 for(nLevelB = 0; nLevelB <= nLevel; ++nLevelB)
792 sal_uInt8 nPos = aOfsNumsXCH[nLevelB];
793 if (nPos && sNumString.GetChar(nPos-1) < nMaxLevel)
795 if (rNotReallyThere[nLevelB])
796 aOfsNumsXCH[nLevelB] = 0;
799 myIter aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0);
800 myIter aEnd = aOfsNumsXCH.end();
801 // --> OD 2006-01-16 #i60633# - suppress access on <aOfsNumsXCH.end()>
802 if ( aIter != aEnd )
804 // Somehow the first removed vector element, at which <aIter>
805 // points to, isn't reset to zero.
806 // Investigation is needed to clarify why. It seems that only
807 // special arrays are handled correctly by this code.
808 ++aIter;
809 while (aIter != aEnd)
811 (*aIter) = 0;
812 ++aIter;
815 // <--
817 sal_uInt8 nUpperLevel = 0; // akt. Anzeigetiefe fuer den Writer
818 for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
820 if (!nUpperLevel && !aOfsNumsXCH[nLevelB])
821 nUpperLevel = nLevelB;
824 // falls kein NULL als Terminierungs-Char kam,
825 // ist die Liste voller Indices, d.h. alle Plaetze sind besetzt,
826 // also sind alle Level anzuzeigen
827 if (!nUpperLevel)
828 nUpperLevel = nMaxLevel;
830 if (SVX_NUM_CHAR_SPECIAL == eType)
832 cBullet = sNumString.Len() ? sNumString.GetChar(0) : 0x2190;
834 if (!cBullet) // unsave control code?
835 cBullet = 0x2190;
837 else
840 #83154#, #82192#, #i173#, #109158#
841 Our aOfsNumsXCH seems generally to be an array that contains the
842 offset into sNumString of locations where the numbers should be
843 filled in, so if the first "fill in a number" slot is greater than
844 1 there is a "prefix" before the number
846 //First number appears at
847 sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0];
848 xub_StrLen nFirstNoIndex =
849 nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : STRING_LEN;
850 lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex);
852 //Next number appears at
853 if (nUpperLevel)
855 sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1];
856 xub_StrLen nNextNoIndex =
857 nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex -1 : STRING_LEN;
858 if (nNextNoIndex != STRING_LEN)
859 ++nNextNoIndex;
860 if (sNumString.Len() > nNextNoIndex)
861 lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex);
865 We use lcl_CopyGreaterEight because once if we have removed unused
866 number indexes from the aOfsNumsXCH then placeholders remain in
867 sNumString which must not be copied into the final numbering strings
871 switch( aLVL.nAlign )
873 case 0:
874 eAdj = SVX_ADJUST_LEFT;
875 break;
876 case 1:
877 eAdj = SVX_ADJUST_CENTER;
878 break;
879 case 2:
880 eAdj = SVX_ADJUST_RIGHT;
881 break;
882 case 3:
883 // Writer here cannot do block justification
884 eAdj = SVX_ADJUST_LEFT;
885 break;
886 default:
887 // undefied value
888 ASSERT( !this, "Value of aLVL.nAlign is not supported" );
889 // take default
890 eAdj = SVX_ADJUST_LEFT;
891 break;
894 // 6. entsprechendes NumFmt konfigurieren
895 if( bSetStartNo )
896 rNumFmt.SetStart( nStartNo );
897 rNumFmt.SetNumberingType( static_cast< sal_Int16 >(eType) );
898 rNumFmt.SetNumAdjust( eAdj );
900 if( SVX_NUM_CHAR_SPECIAL == eType )
902 // first character of the Prefix-Text is the Bullet
903 rNumFmt.SetBulletChar(cBullet);
904 // Don't forget: unten, nach dem Bauen eventueller Styles auch noch
905 // SetBulletFont() rufen !!!
907 else
909 // reminder: Garnix ist default Prefix
910 if( sPrefix.Len() )
911 rNumFmt.SetPrefix( sPrefix );
912 // reminder: Point is default Postfix
913 rNumFmt.SetSuffix( sPostfix );
914 rNumFmt.SetIncludeUpperLevels( nUpperLevel );
917 // --> OD 2008-06-04 #i89181#
918 if ( rNumFmt.GetPositionAndSpaceMode() ==
919 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
921 if (eAdj == SVX_ADJUST_RIGHT)
923 rNumFmt.SetAbsLSpace(aLVL.nDxaLeft);
924 rNumFmt.SetFirstLineOffset(-aLVL.nDxaLeft);
925 rNumFmt.SetCharTextDistance(-aLVL.nDxaLeft1);
927 else
929 rNumFmt.SetAbsLSpace( aLVL.nDxaLeft );
930 rNumFmt.SetFirstLineOffset(aLVL.nDxaLeft1);
933 else
935 rNumFmt.SetIndentAt( aLVL.nDxaLeft );
936 rNumFmt.SetFirstLineIndent(aLVL.nDxaLeft1);
937 rNumFmt.SetListtabPos( nTabPos );
938 SvxNumberFormat::SvxNumLabelFollowedBy eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
939 switch ( ixchFollow )
941 case 0:
943 eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
945 break;
946 case 1:
948 eNumLabelFollowedBy = SvxNumberFormat::SPACE;
950 break;
951 case 2:
953 eNumLabelFollowedBy = SvxNumberFormat::NOTHING;
955 break;
957 rNumFmt.SetLabelFollowedBy( eNumLabelFollowedBy );
960 return true;
963 void WW8ListManager::AdjustLVL( sal_uInt8 nLevel, SwNumRule& rNumRule,
964 WW8aISet& rListItemSet, WW8aCFmt& rCharFmt, bool& bNewCharFmtCreated,
965 String sPrefix )
967 bNewCharFmtCreated = false;
968 SfxItemSet* pThisLevelItemSet;
969 SfxItemSet* pLowerLevelItemSet;
970 sal_uInt8 nIdenticalItemSetLevel;
971 const SfxPoolItem* pItem;
973 SwNumFmt aNumFmt = rNumRule.Get( nLevel );
975 pThisLevelItemSet = rListItemSet[ nLevel ];
977 if( pThisLevelItemSet && pThisLevelItemSet->Count())
979 nIdenticalItemSetLevel = nMaxLevel;
980 SfxItemIter aIter( *pThisLevelItemSet );
981 for (sal_uInt8 nLowerLevel = 0; nLowerLevel < nLevel; ++nLowerLevel)
983 pLowerLevelItemSet = rListItemSet[ nLowerLevel ];
984 if( pLowerLevelItemSet
985 && (pLowerLevelItemSet->Count() == pThisLevelItemSet->Count()) )
987 nIdenticalItemSetLevel = nLowerLevel;
988 sal_uInt16 nWhich = aIter.GetCurItem()->Which();
989 while (true)
991 if( // ggfs. passenden pItem im pLowerLevelItemSet finden
992 (SFX_ITEM_SET != pLowerLevelItemSet->GetItemState(
993 nWhich, false, &pItem ) )
994 || // virtuellen "!=" Operator anwenden
995 (*pItem != *aIter.GetCurItem() ) )
996 // falls kein Item mit gleicher nWhich gefunden oder Werte
997 // der Items ungleich, Ungleichheit merken und abbrechen!
999 nIdenticalItemSetLevel = nMaxLevel;
1000 break;
1002 if( aIter.IsAtEnd() )
1003 break;
1004 nWhich = aIter.NextItem()->Which();
1007 if( nIdenticalItemSetLevel != nMaxLevel )
1008 break;
1012 SwCharFmt* pFmt;
1013 if (nMaxLevel == nIdenticalItemSetLevel)
1015 // Style definieren
1016 String aName( sPrefix.Len() ? sPrefix : rNumRule.GetName() );
1017 (aName += 'z') += String::CreateFromInt32( nLevel );
1019 // const Wegcasten
1020 pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt());
1021 bNewCharFmtCreated = true;
1022 // Attribute reinsetzen
1023 pFmt->SetFmtAttr( *pThisLevelItemSet );
1025 else
1027 // passenden Style hier anhaengen
1028 pFmt = rCharFmt[ nIdenticalItemSetLevel ];
1031 // merken
1032 rCharFmt[ nLevel ] = pFmt;
1035 // Style an das NumFormat haengen
1037 aNumFmt.SetCharFmt( pFmt );
1040 // ggfs. Bullet Font an das NumFormat haengen
1042 if( SVX_NUM_CHAR_SPECIAL == aNumFmt.GetNumberingType() )
1044 SwCharFmt* pFmt = aNumFmt.GetCharFmt();
1045 Font aFont;
1046 if( !pFmt )
1048 // --> OD 2006-06-27 #b6440955#
1049 // aFont = SwNumRule::GetDefBulletFont();
1050 aFont = numfunc::GetDefBulletFont();
1051 // <--
1053 else
1055 const SvxFontItem& rFontItem = pFmt->GetFont();
1056 aFont.SetFamily( rFontItem.GetFamily() );
1057 aFont.SetName( rFontItem.GetFamilyName() );
1058 aFont.SetStyleName( rFontItem.GetStyleName() );
1059 aFont.SetPitch( rFontItem.GetPitch() );
1060 aFont.SetCharSet( rFontItem.GetCharSet() );
1062 aNumFmt.SetBulletFont( &aFont );
1065 // und wieder rein in die NumRule
1067 rNumRule.Set(nLevel, aNumFmt);
1070 SwNumRule* WW8ListManager::CreateNextRule(bool bSimple)
1072 // wird erstmal zur Bildung des Style Namens genommen
1073 String sPrefix(CREATE_CONST_ASC("WW8Num"));
1074 sPrefix += String::CreateFromInt32(nUniqueList++);
1075 // --> OD 2008-06-04 #i86652#
1076 // sal_uInt16 nRul = rDoc.MakeNumRule(rDoc.GetUniqueNumRuleName(&sPrefix));
1077 sal_uInt16 nRul =
1078 rDoc.MakeNumRule( rDoc.GetUniqueNumRuleName(&sPrefix), 0, FALSE,
1079 SvxNumberFormat::LABEL_ALIGNMENT );
1080 // <--
1081 SwNumRule* pMyNumRule = rDoc.GetNumRuleTbl()[nRul];
1082 pMyNumRule->SetAutoRule(false);
1083 pMyNumRule->SetContinusNum(bSimple);
1084 return pMyNumRule;
1087 // oeffentliche Methoden /////////////////////////////////////////////////////
1089 WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
1090 : maSprmParser(rReader_.GetFib().GetFIBVersion()), rReader(rReader_),
1091 rDoc(rReader.GetDoc()), rFib(rReader.GetFib()), rSt(rSt_), pLFOInfos(0),
1092 nUniqueList(1)
1094 // LST und LFO gibts erst ab WW8
1095 if( ( 8 > rFib.nVersion )
1096 || ( rFib.fcPlcfLst == rFib.fcPlfLfo )
1097 || ( !rFib.lcbPlcfLst )
1098 || ( !rFib.lcbPlfLfo ) ) return; // offensichtlich keine Listen da
1100 // Arrays anlegen
1101 pLFOInfos = new WW8LFOInfos;
1102 bool bLVLOk = true;
1103 sal_uInt8 aBits1;
1105 nLastLFOPosition = USHRT_MAX;
1106 long nOriginalPos = rSt.Tell();
1108 // 1. PLCF LST auslesen und die Listen Vorlagen im Writer anlegen
1110 rSt.Seek( rFib.fcPlcfLst );
1111 sal_uInt16 nListCount;
1112 rSt >> nListCount;
1113 bool bOk = 0 < nListCount;
1114 if( bOk )
1116 WW8LST aLST;
1118 // 1.1 alle LST einlesen
1120 for (sal_uInt16 nList=0; nList < nListCount; ++nList)
1122 bOk = false;
1123 memset(&aLST, 0, sizeof( aLST ));
1124 sal_uInt16 nLevel;
1126 // 1.1.1 Daten einlesen
1128 rSt >> aLST.nIdLst;
1129 rSt >> aLST.nTplC;
1130 for (nLevel = 0; nLevel < nMaxLevel; ++nLevel)
1131 rSt >> aLST.aIdSty[ nLevel ];
1134 rSt >> aBits1;
1136 rSt.SeekRel( 1 );
1138 if (rSt.GetError())
1139 break;
1141 if( aBits1 & 0x01 )
1142 aLST.bSimpleList = true;
1143 if( aBits1 & 0x02 )
1144 aLST.bRestartHdn = true;
1146 // 1.1.2 new NumRule inserted in Doc and WW8LSTInfo marked
1149 #i1869#
1150 In word 2000 microsoft got rid of creating new "simple lists" with
1151 only 1 level, all new lists are created with 9 levels. To hack it
1152 so that the list types formerly known as simple lists still have
1153 their own tab page to themselves one of the reserved bits is used
1154 to show that a given list is to be in the simple list tabpage.
1155 This has now nothing to do with the actual number of list level a
1156 list has, only how many will be shown in the user interface.
1158 i.e. create a simple list in 2000 and open it in 97 and 97 will
1159 claim (correctly) that it is an outline list. We can set our
1160 continous flag in these lists to store this information.
1162 SwNumRule* pMyNumRule = CreateNextRule(
1163 aLST.bSimpleList || (aBits1 & 0x10));
1165 WW8LSTInfo* pLSTInfo = new WW8LSTInfo(pMyNumRule, aLST);
1166 maLSTInfos.push_back(pLSTInfo);
1167 bOk = true;
1171 if( bOk )
1174 // 1.2 alle LVL aller aLST einlesen
1176 sal_uInt8 nLevel;
1177 sal_uInt16 nLSTInfos = static_cast< sal_uInt16 >(maLSTInfos.size());
1178 for (sal_uInt16 nList = 0; nList < nLSTInfos; ++nList)
1180 bOk = false;
1181 WW8LSTInfo* pListInfo = maLSTInfos[nList];
1182 if( !pListInfo || !pListInfo->pNumRule ) break;
1183 SwNumRule& rMyNumRule = *pListInfo->pNumRule;
1185 // 1.2.1 betreffende(n) LVL(s) fuer diese aLST einlesen
1187 sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel);
1188 std::deque<bool> aNotReallyThere;
1189 aNotReallyThere.resize(nMaxLevel);
1190 pListInfo->maParaSprms.resize(nMaxLevel);
1191 for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
1193 SwNumFmt aNumFmt( rMyNumRule.Get( nLevel ) );
1194 // LVLF einlesen
1195 bLVLOk = ReadLVL( aNumFmt, pListInfo->aItemSet[nLevel],
1196 pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel,
1197 pListInfo->maParaSprms[nLevel]);
1198 if( !bLVLOk )
1199 break;
1200 // und in die rMyNumRule aufnehmen
1201 rMyNumRule.Set( nLevel, aNumFmt );
1203 if( !bLVLOk )
1204 break;
1206 // 1.2.2 die ItemPools mit den CHPx Einstellungen der verschiedenen
1207 // Level miteinander vergleichen und ggfs. Style(s) erzeugen
1209 bool bDummy;
1210 for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
1212 AdjustLVL( nLevel, rMyNumRule, pListInfo->aItemSet,
1213 pListInfo->aCharFmt, bDummy );
1216 // 1.2.3 ItemPools leeren und loeschen
1218 for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
1219 delete pListInfo->aItemSet[ nLevel ];
1220 bOk = true;
1223 if( !bOk )
1225 // Fehler aufgetreten - LSTInfos abraeumen !!!
1231 // 2. PLF LFO auslesen und speichern
1233 long nLfoCount(0);
1234 if (bOk)
1236 rSt.Seek(rFib.fcPlfLfo);
1237 rSt >> nLfoCount;
1238 if (0 >= nLfoCount)
1239 bOk = false;
1242 if(bOk)
1244 WW8LFO aLFO;
1246 // 2.1 alle LFO einlesen
1248 for (sal_uInt16 nLfo = 0; nLfo < nLfoCount; ++nLfo)
1250 bOk = false;
1251 memset(&aLFO, 0, sizeof( aLFO ));
1252 rSt >> aLFO.nIdLst;
1253 rSt.SeekRel( 8 );
1254 rSt >> aLFO.nLfoLvl;
1255 rSt.SeekRel( 3 );
1256 // soviele Overrides existieren
1257 if ((nMaxLevel < aLFO.nLfoLvl) || rSt.GetError())
1258 break;
1260 // die Parent NumRule der entsprechenden Liste ermitteln
1261 WW8LSTInfo* pParentListInfo = GetLSTByListId(aLFO.nIdLst);
1262 if (pParentListInfo)
1264 // hier, im ersten Schritt, erst mal diese NumRule festhalten
1265 aLFO.pNumRule = pParentListInfo->pNumRule;
1267 // hat die Liste mehrere Level ?
1268 aLFO.bSimpleList = pParentListInfo->bSimpleList;
1270 // und rein ins Merk-Array mit dem Teil
1271 WW8LFOInfo* pLFOInfo = new WW8LFOInfo(aLFO);
1272 if (pParentListInfo)
1274 //Copy the basic paragraph properties for each level from the
1275 //original list into the list format override levels.
1276 int nMaxSize = pParentListInfo->maParaSprms.size();
1277 pLFOInfo->maParaSprms.resize(nMaxSize);
1278 for (int i = 0; i < nMaxSize; ++i)
1279 pLFOInfo->maParaSprms[i] = pParentListInfo->maParaSprms[i];
1281 pLFOInfos->Insert(pLFOInfo, pLFOInfos->Count());
1282 bOk = true;
1285 if( bOk )
1288 // 2.2 fuer alle LFO die zugehoerigen LFOLVL einlesen
1290 sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0;
1291 for (sal_uInt16 nLfo = 0; nLfo < nLFOInfos; ++nLfo)
1293 bOk = false;
1294 WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLfo );
1295 if (!pLFOInfo)
1296 break;
1297 // stehen hierfuer ueberhaupt LFOLVL an ?
1298 if( pLFOInfo->bOverride )
1300 WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst);
1301 if (!pParentListInfo) //e.g. #112324#
1302 break;
1304 // 2.2.1 eine neue NumRule fuer diese Liste anlegen
1306 SwNumRule* pParentNumRule = pLFOInfo->pNumRule;
1307 ASSERT(pParentNumRule, "ww: Impossible lists, please report");
1308 if( !pParentNumRule )
1309 break;
1310 // Nauemsprefix aufbauen: fuer NumRule-Name (eventuell)
1311 // und (falls vorhanden) fuer Style-Name (dann auf jeden Fall)
1312 String sPrefix(CREATE_CONST_ASC( "WW8NumSt" ));
1313 sPrefix += String::CreateFromInt32( nLfo + 1 );
1314 // jetzt dem pNumRule seinen RICHTIGEN Wert zuweisen !!!
1315 // (bis dahin war hier die Parent NumRule vermerkt )
1317 // Dazu erst mal nachsehen, ob ein Style diesen LFO
1318 // referenziert:
1319 if( USHRT_MAX > rReader.StyleUsingLFO( nLfo ) )
1321 sal_uInt16 nRul = rDoc.MakeNumRule(
1322 rDoc.GetUniqueNumRuleName( &sPrefix ), pParentNumRule);
1323 pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
1324 pLFOInfo->pNumRule->SetAutoRule(false);
1326 else
1328 sal_uInt16 nRul = rDoc.MakeNumRule(
1329 rDoc.GetUniqueNumRuleName(), pParentNumRule);
1330 pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
1331 pLFOInfo->pNumRule->SetAutoRule(true); // = default
1334 // 2.2.2 alle LFOLVL (und ggfs. LVL) fuer die neue NumRule
1335 // einlesen
1337 WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
1338 WW8aCFmt aCharFmt; // Zeichen Style Pointer
1339 memset(&aItemSet, 0, sizeof( aItemSet ));
1340 memset(&aCharFmt, 0, sizeof( aCharFmt ));
1342 //2.2.2.0 skip inter-group of override header ?
1343 //See #i25438# for why I moved this here, compare
1344 //that original bugdoc's binary to what it looks like
1345 //when resaved with word, i.e. there is always a
1346 //4 byte header, there might be more than one if
1347 //that header was 0xFFFFFFFF, e.g. #114412# ?
1348 sal_uInt32 nTest;
1349 rSt >> nTest;
1351 rSt >> nTest;
1352 while (nTest == 0xFFFFFFFF);
1353 rSt.SeekRel(-4);
1355 std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel);
1356 sal_uInt8 nLevel = 0;
1357 for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
1359 WW8LFOLVL aLFOLVL;
1360 bLVLOk = false;
1363 // 2.2.2.1 den LFOLVL einlesen
1365 rSt >> aLFOLVL.nStartAt;
1366 rSt >> aBits1;
1367 rSt.SeekRel( 3 );
1368 if (rSt.GetError())
1369 break;
1371 // beachte: Die Witzbolde bei MS quetschen die
1372 // Override-Level-Nummer in vier Bits hinein, damit sie
1373 // wieder einen Grund haben, ihr Dateiformat zu aendern,
1374 // falls ihnen einfaellt, dass sie eigentlich doch gerne
1375 // bis zu 16 Listen-Level haetten. Wir tun das *nicht*
1376 // (siehe Kommentar oben bei "struct
1377 // WW8LFOInfo")
1378 aLFOLVL.nLevel = aBits1 & 0x0F;
1379 if( (0xFF > aBits1) &&
1380 (nMaxLevel > aLFOLVL.nLevel) )
1382 if (aBits1 & 0x10)
1383 aLFOLVL.bStartAt = true;
1384 else
1385 aLFOLVL.bStartAt = false;
1387 // 2.2.2.2 eventuell auch den zugehoerigen LVL einlesen
1389 SwNumFmt aNumFmt(
1390 pLFOInfo->pNumRule->Get(aLFOLVL.nLevel));
1391 if (aBits1 & 0x20)
1393 aLFOLVL.bFormat = true;
1394 // falls bStartup true, hier den Startup-Level
1395 // durch den im LVL vermerkten ersetzen LVLF
1396 // einlesen
1397 bLVLOk = ReadLVL(aNumFmt, aItemSet[nLevel],
1398 pParentListInfo->aIdSty[nLevel],
1399 aLFOLVL.bStartAt, aNotReallyThere, nLevel,
1400 pLFOInfo->maParaSprms[nLevel]);
1402 if (!bLVLOk)
1403 break;
1405 else if (aLFOLVL.bStartAt)
1407 aNumFmt.SetStart(
1408 writer_cast<USHORT>(aLFOLVL.nStartAt));
1411 // 2.2.2.3 das NumFmt in die NumRule aufnehmen
1413 pLFOInfo->pNumRule->Set(aLFOLVL.nLevel, aNumFmt);
1415 bLVLOk = true;
1416 pLFOInfo->maOverrides[aLFOLVL.nLevel] = aLFOLVL;
1418 if( !bLVLOk )
1419 break;
1421 // 2.2.3 die LVL der neuen NumRule anpassen
1423 sal_uInt16 aFlagsNewCharFmt = 0;
1424 bool bNewCharFmtCreated = false;
1425 for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
1427 AdjustLVL( nLevel, *pLFOInfo->pNumRule, aItemSet, aCharFmt,
1428 bNewCharFmtCreated, sPrefix );
1429 if( bNewCharFmtCreated )
1430 aFlagsNewCharFmt += (1 << nLevel);
1433 // 2.2.4 ItemPools leeren und loeschen
1435 for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
1436 delete aItemSet[ nLevel ];
1437 bOk = true;
1441 if( !bOk )
1443 // Fehler aufgetreten - LSTInfos und LFOInfos abraeumen !!!
1446 // und schon sind wir fertig!
1447 rSt.Seek( nOriginalPos );
1450 WW8ListManager::~WW8ListManager()
1453 named lists remain in doc!!!
1454 unnamed lists are deleted when unused
1455 pLFOInfos are in any case destructed
1457 for(std::vector<WW8LSTInfo *>::iterator aIter = maLSTInfos.begin();
1458 aIter != maLSTInfos.end(); ++aIter)
1460 if ((*aIter)->pNumRule && !(*aIter)->bUsedInDoc &&
1461 (*aIter)->pNumRule->IsAutoRule())
1463 rDoc.DelNumRule((*aIter)->pNumRule->GetName());
1465 delete *aIter;
1468 if (pLFOInfos)
1470 for(sal_uInt16 nInfo = pLFOInfos->Count(); nInfo; )
1472 WW8LFOInfo *pActInfo = pLFOInfos->GetObject(--nInfo);
1473 if (pActInfo->bOverride && pActInfo->pNumRule
1474 && !pActInfo->bUsedInDoc && pActInfo->pNumRule->IsAutoRule())
1476 rDoc.DelNumRule( pActInfo->pNumRule->GetName() );
1479 delete pLFOInfos;
1483 bool IsEqualFormatting(const SwNumRule &rOne, const SwNumRule &rTwo)
1485 bool bRet =
1487 rOne.GetRuleType() == rTwo.GetRuleType() &&
1488 rOne.IsContinusNum() == rTwo.IsContinusNum() &&
1489 rOne.IsAbsSpaces() == rTwo.IsAbsSpaces() &&
1490 rOne.GetPoolFmtId() == rTwo.GetPoolFmtId() &&
1491 rOne.GetPoolHelpId() == rTwo.GetPoolHelpId() &&
1492 rTwo.GetPoolHlpFileId() == rTwo.GetPoolHlpFileId()
1495 if (bRet)
1497 for (BYTE n = 0; n < MAXLEVEL; ++n )
1499 //The SvxNumberFormat compare, not the SwNumFmt compare
1500 const SvxNumberFormat &rO = rOne.Get(n);
1501 const SvxNumberFormat &rT = rTwo.Get(n);
1502 if (!(rO == rT))
1504 bRet = false;
1505 break;
1509 return bRet;
1512 SwNumRule* WW8ListManager::GetNumRuleForActivation(sal_uInt16 nLFOPosition,
1513 const BYTE nLevel, std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode)
1515 sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0;
1516 if( nLFOInfos <= nLFOPosition )
1517 return 0;
1519 WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLFOPosition );
1521 if( !pLFOInfo )
1522 return 0;
1524 bool bFirstUse = !pLFOInfo->bUsedInDoc;
1525 pLFOInfo->bUsedInDoc = true;
1527 if( !pLFOInfo->pNumRule )
1528 return 0;
1530 // #i25545#
1531 // --> OD 2009-03-12 #i100132# - a number format does not have to exist on given list level
1532 // SwNumFmt pFmt(*(pLFOInfo->pNumRule->GetNumFmt(nLevel)));
1533 SwNumFmt pFmt(pLFOInfo->pNumRule->Get(nLevel));
1534 // <--
1535 if (rReader.IsRightToLeft() && nLastLFOPosition != nLFOPosition) {
1536 if ( pFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
1537 pFmt.SetNumAdjust(SVX_ADJUST_LEFT);
1538 else if ( pFmt.GetNumAdjust() == SVX_ADJUST_LEFT)
1539 pFmt.SetNumAdjust(SVX_ADJUST_RIGHT);
1540 pLFOInfo->pNumRule->Set(nLevel, pFmt);
1542 nLastLFOPosition = nLFOPosition;
1544 #i1869#
1545 If this list has had its bits set in word 2000 to pretend that it is a
1546 simple list from the point of view of the user, then it is almost
1547 certainly a simple continous list, and we will try to keep it like that.
1548 Otherwise when we save again it will be shown as the true outline list
1549 that it is, confusing the user that just wanted what they thought was a
1550 simple list. On the otherhand it is possible that some of the other levels
1551 were used by the user, in which case we will not pretend anymore that it
1552 is a simple list. Something that word 2000 does anyway, that 97 didn't, to
1553 my bewilderment.
1555 if (nLevel && pLFOInfo->pNumRule->IsContinusNum())
1556 pLFOInfo->pNumRule->SetContinusNum(false);
1558 if( (!pLFOInfo->bOverride) && (!pLFOInfo->bLSTbUIDSet) )
1560 WW8LSTInfo* pParentListInfo = GetLSTByListId( pLFOInfo->nIdLst );
1561 if( pParentListInfo )
1562 pParentListInfo->bUsedInDoc = true;
1563 pLFOInfo->bLSTbUIDSet = true;
1566 if (pLFOInfo->maParaSprms.size() > nLevel)
1567 rParaSprms = pLFOInfo->maParaSprms[nLevel];
1569 SwNumRule *pRet = pLFOInfo->pNumRule;
1571 bool bRestart(false);
1572 USHORT nStart(0);
1573 bool bNewstart(false);
1575 Note: If you fiddle with this then you have to make sure that #i18322#
1576 #i13833#, #i20095# and #112466# continue to work
1578 Check if there were overrides for this level
1580 if (pLFOInfo->bOverride && nLevel < pLFOInfo->nLfoLvl)
1582 WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst);
1583 ASSERT(pParentListInfo, "ww: Impossible lists, please report");
1584 if (pParentListInfo && pParentListInfo->pNumRule)
1586 const WW8LFOLVL &rOverride = pLFOInfo->maOverrides[nLevel];
1587 bool bNoChangeFromParent =
1588 IsEqualFormatting(*pRet, *(pParentListInfo->pNumRule));
1590 //If so then I think word still uses the parent (maybe)
1591 if (bNoChangeFromParent)
1593 pRet = pParentListInfo->pNumRule;
1595 //did it not affect start at value ?
1596 if (bFirstUse)
1598 if (rOverride.bStartAt)
1600 const SwNumFmt &rFmt =
1601 pParentListInfo->pNumRule->Get(nLevel);
1602 if (
1603 rFmt.GetStart() ==
1604 pLFOInfo->maOverrides[nLevel].nStartAt
1607 bRestart = true;
1609 else
1611 bNewstart = true;
1612 nStart = writer_cast<USHORT>
1613 (pLFOInfo->maOverrides[nLevel].nStartAt);
1618 pParentListInfo->bUsedInDoc = true;
1623 if (pNode)
1625 pNode->SetAttrListLevel(nLevel);
1627 if (bRestart || bNewstart) //#112466# (I think)
1628 pNode->SetListRestart(true);
1629 if (bNewstart)
1630 pNode->SetAttrListRestartValue(nStart);
1632 return pRet;
1635 //----------------------------------------------------------------------------
1636 // SwWW8ImplReader: anhaengen einer Liste an einen Style oder Absatz
1637 //----------------------------------------------------------------------------
1638 bool SwWW8ImplReader::SetTxtFmtCollAndListLevel(const SwPaM& rRg,
1639 SwWW8StyInf& rStyleInfo)
1641 bool bRes = true;
1642 if( rStyleInfo.pFmt && rStyleInfo.bColl )
1644 bRes = rDoc.SetTxtFmtColl(rRg, (SwTxtFmtColl*)rStyleInfo.pFmt)
1645 ? true : false;
1646 SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode();
1647 ASSERT( pTxtNode, "No Text-Node at PaM-Position" );
1648 // --> OD 2006-10-19 #134160# - make code robust
1649 if ( !pTxtNode )
1651 return bRes;
1653 // <--
1655 SwNumRule * pNumRule = pTxtNode->GetNumRule(); // #i27610#
1657 if( !IsInvalidOrToBeMergedTabCell() &&
1658 ! (pNumRule && pNumRule->IsOutlineRule()) ) // #i27610#
1659 pTxtNode->ResetAttr( RES_PARATR_NUMRULE );
1661 if( !rStyleInfo.pOutlineNumrule )
1663 if (
1664 (USHRT_MAX > rStyleInfo.nLFOIndex) &&
1665 (WW8ListManager::nMaxLevel > rStyleInfo.nListLevel)
1668 RegisterNumFmtOnTxtNode(rStyleInfo.nLFOIndex,
1669 rStyleInfo.nListLevel, false);
1672 else
1674 // --> OD 2005-11-07 #127520#
1675 // Use outline level set at the style info <rStyleInfo> instead of
1676 // the outline level at the text format, because the WW8 document
1677 // could contain more than one outline numbering rule and the one
1678 // of the text format isn't the one, which a chosen as the Writer
1679 // outline rule.
1680 // pTxtNode->
1681 // SetLevel(((SwTxtFmtColl*) rStyleInfo.pFmt)->GetOutlineLevel());
1682 pTxtNode->SetAttrListLevel( rStyleInfo.nOutlineLevel );
1683 // <--
1686 return bRes;
1689 void UseListIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
1691 // --> OD 2008-06-03 #i86652#
1692 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1694 const long nAbsLSpace = rFmt.GetAbsLSpace();
1695 const long nListFirstLineIndent = GetListFirstLineIndent(rFmt);
1696 SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
1697 aLR.SetTxtLeft(nAbsLSpace);
1698 aLR.SetTxtFirstLineOfst(writer_cast<short>(nListFirstLineIndent));
1699 rStyle.pFmt->SetFmtAttr(aLR);
1700 rStyle.bListReleventIndentSet = true;
1702 // <--
1705 void SetStyleIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
1707 // --> OD 2008-06-03 #i86652#
1708 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1709 // <--
1711 SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
1712 if (rStyle.bListReleventIndentSet)
1713 SyncIndentWithList(aLR, rFmt);
1714 else
1716 aLR.SetTxtLeft(0);
1717 aLR.SetTxtFirstLineOfst(0);
1719 rStyle.pFmt->SetFmtAttr(aLR);
1723 void SwWW8ImplReader::SetStylesList(sal_uInt16 nStyle, sal_uInt16 nActLFO,
1724 sal_uInt8 nActLevel)
1726 SwWW8StyInf &rStyleInf = pCollA[nStyle];
1727 if (rStyleInf.bValid)
1729 ASSERT(pAktColl, "Cannot be called outside of style import");
1730 // Phase 1: Nummerierungsattribute beim Einlesen einer StyleDef
1731 if( pAktColl )
1733 // jetzt nur die Parameter vermerken: die tatsaechliche Liste wird
1734 // spaeter drangehaengt, wenn die Listendefinitionen gelesen sind...
1735 if (
1736 (USHRT_MAX > nActLFO) &&
1737 (WW8ListManager::nMaxLevel > nActLevel)
1740 rStyleInf.nLFOIndex = nActLFO;
1741 rStyleInf.nListLevel = nActLevel;
1743 if (
1744 (USHRT_MAX > nActLFO) &&
1745 (WW8ListManager::nMaxLevel > nActLevel)
1748 std::vector<sal_uInt8> aParaSprms;
1749 SwNumRule *pNmRule =
1750 pLstManager->GetNumRuleForActivation(nActLFO,
1751 nActLevel, aParaSprms);
1752 if (pNmRule)
1753 UseListIndent(rStyleInf, pNmRule->Get(nActLevel));
1760 void SwWW8ImplReader::RegisterNumFmtOnStyle(sal_uInt16 nStyle)
1762 SwWW8StyInf &rStyleInf = pCollA[nStyle];
1763 if (rStyleInf.bValid && rStyleInf.pFmt)
1765 //Save old pre-list modified indent, which are the word indent values
1766 rStyleInf.maWordLR =
1767 ItemGet<SvxLRSpaceItem>(*rStyleInf.pFmt, RES_LR_SPACE);
1769 // Phase 2: aktualisieren der StyleDef nach einlesen aller Listen
1770 SwNumRule* pNmRule = 0;
1771 sal_uInt16 nLFO = rStyleInf.nLFOIndex;
1772 sal_uInt8 nLevel = rStyleInf.nListLevel;
1773 if (
1774 (USHRT_MAX > nLFO) &&
1775 (WW8ListManager::nMaxLevel > nLevel)
1778 std::vector<sal_uInt8> aParaSprms;
1779 pNmRule = pLstManager->GetNumRuleForActivation(nLFO, nLevel,
1780 aParaSprms);
1782 if (pNmRule)
1784 if( MAXLEVEL > rStyleInf.nOutlineLevel )
1785 rStyleInf.pOutlineNumrule = pNmRule;
1786 else
1788 rStyleInf.pFmt->SetFmtAttr(
1789 SwNumRuleItem( pNmRule->GetName() ) );
1790 rStyleInf.bHasStyNumRule = true;
1795 if (pNmRule)
1796 SetStyleIndent(rStyleInf, pNmRule->Get(nLevel));
1800 void SwWW8ImplReader::RegisterNumFmtOnTxtNode(sal_uInt16 nActLFO,
1801 sal_uInt8 nActLevel, bool bSetAttr)
1803 // beachte: die Methode haengt die NumRule an den Text Node, falls
1804 // bSetAttr (dann muessen natuerlich vorher die Listen gelesen sein)
1805 // stellt sie NUR den Level ein, im Vertrauen darauf, dass am STYLE eine
1806 // NumRule haengt - dies wird NICHT ueberprueft !!!
1808 if (pLstManager) // sind die Listendeklarationen gelesen?
1810 std::vector<sal_uInt8> aParaSprms;
1811 SwTxtNode* pTxtNd = pPaM->GetNode()->GetTxtNode();
1812 ASSERT(pTxtNd, "Kein Text-Node an PaM-Position");
1814 const SwNumRule* pRule = bSetAttr ?
1815 pLstManager->GetNumRuleForActivation( nActLFO, nActLevel,
1816 aParaSprms, pTxtNd) : 0;
1818 if (pRule || !bSetAttr)
1820 //#i24136# old is the same as new, and its the outline numbering,
1821 //then we don't set the numrule again, and we just take the num node
1822 //(the actual outline numbering gets set in SetOutlineNum)
1823 using namespace sw::util;
1824 bool bUnchangedOutlineNumbering = false;
1826 If the node is outline numbered, and the new numbering to apply
1827 is the one that was chosen to be the outline numbering then all
1828 is unchanged
1830 // --> OD 2005-11-04 #???# - correct condition according to the
1831 // above given comment.
1832 if ( pTxtNd->GetNumRule() == rDoc.GetOutlineNumRule() &&
1833 pRule == mpChosenOutlineNumRule )
1834 // <--
1836 bUnchangedOutlineNumbering = true;
1838 if (!bUnchangedOutlineNumbering)
1840 //If its normal numbering, see if its the same as it already
1841 //was, if its not, and we have been asked to set it, then set
1842 //it to the new one
1843 if (bSetAttr)
1845 const SwNumRule *pNormal = pTxtNd->GetNumRule();
1846 if (pNormal != pRule)
1848 pTxtNd->SetAttr
1849 (SwNumRuleItem(pRule->GetName()));
1853 // --> OD 2005-10-17 #126238#
1854 // - re-introduce fix for issue #i49037#, which got lost by
1855 // accident on a re-synchronisation on the master.
1856 // if (pTxtNd->IsOutline() && pTxtNd->Len() == 0)
1857 // pTxtNd->SetCounted(false);
1858 // <--
1860 pTxtNd->SetAttrListLevel(nActLevel);
1861 // --> OD 2005-11-01 #126924#
1862 // - <IsCounted()> state of text node has to be adjusted accordingly.
1863 if ( /*nActLevel >= 0 &&*/ nActLevel < MAXLEVEL )
1865 pTxtNd->SetCountedInList( true );
1867 // <--
1869 // --> OD 2009-03-04 #i99822#
1870 // Direct application of the list level formatting no longer
1871 // needed for list levels of mode LABEL_ALIGNMENT
1872 bool bApplyListLevelIndentDirectlyAtPara( true );
1873 if ( pTxtNd->GetNumRule() && nActLevel < MAXLEVEL )
1875 const SwNumFmt& rFmt = pTxtNd->GetNumRule()->Get( nActLevel );
1876 if ( rFmt.GetPositionAndSpaceMode() ==
1877 SvxNumberFormat::LABEL_ALIGNMENT )
1879 bApplyListLevelIndentDirectlyAtPara = false;
1883 if ( bApplyListLevelIndentDirectlyAtPara )
1885 SfxItemSet aListIndent(rDoc.GetAttrPool(), RES_LR_SPACE,
1886 RES_LR_SPACE);
1887 const SvxLRSpaceItem *pItem = (const SvxLRSpaceItem*)(
1888 GetFmtAttr(RES_LR_SPACE));
1889 ASSERT(pItem, "impossible");
1890 if (pItem)
1891 aListIndent.Put(*pItem);
1894 Take the original paragraph sprms attached to this list level
1895 formatting and apply them to the paragraph. I'm convinced that
1896 this is exactly what word does.
1898 if (short nLen = static_cast< short >(aParaSprms.size()))
1900 SfxItemSet* pOldAktItemSet = pAktItemSet;
1901 SetAktItemSet(&aListIndent);
1903 sal_uInt8* pSprms1 = &aParaSprms[0];
1904 while (0 < nLen)
1906 sal_uInt16 nL1 = ImportSprm(pSprms1);
1907 nLen = nLen - nL1;
1908 pSprms1 += nL1;
1911 SetAktItemSet(pOldAktItemSet);
1914 const SvxLRSpaceItem *pLR =
1915 HasItem<SvxLRSpaceItem>(aListIndent, RES_LR_SPACE);
1916 ASSERT(pLR, "Impossible");
1917 if (pLR)
1919 pCtrlStck->NewAttr(*pPaM->GetPoint(), *pLR);
1920 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
1923 // <--
1928 void SwWW8ImplReader::RegisterNumFmt(sal_uInt16 nActLFO, sal_uInt8 nActLevel)
1930 // sind wir erst beim Einlesen der StyleDef ?
1931 if (pAktColl)
1932 SetStylesList( nAktColl , nActLFO, nActLevel);
1933 else
1934 RegisterNumFmtOnTxtNode(nActLFO, nActLevel);
1937 void SwWW8ImplReader::Read_ListLevel(sal_uInt16, const sal_uInt8* pData,
1938 short nLen)
1940 if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
1941 return;
1943 if( nLen < 0 )
1945 // aktuelle Liste ist hier zu Ende, was ist zu tun ???
1946 nListLevel = WW8ListManager::nMaxLevel;
1947 if (pStyles && !bVer67)
1948 pStyles->nWwNumLevel = 0;
1950 else
1952 // Sicherheitspruefung auf NIL Pointer
1953 if( !pData ) return;
1954 // die Streamdaten sind hier Null basiert, so wie wir es brauchen
1955 nListLevel = *pData;
1957 if (pStyles && !bVer67)
1960 #94672#
1961 if this is the case, then if the numbering is actually stored in
1962 winword 6 format, and its likely that sprmPIlvl has been abused
1963 to set the ww6 list level information which we will need when we
1964 reach the true ww6 list def. So set it now
1966 pStyles->nWwNumLevel = nListLevel;
1969 if (WW8ListManager::nMaxLevel <= nListLevel )
1970 nListLevel = WW8ListManager::nMaxLevel;
1971 else if
1973 (USHRT_MAX > nLFOPosition) &&
1974 (WW8ListManager::nMaxLevel > nListLevel)
1977 RegisterNumFmt(nLFOPosition, nListLevel);
1978 nLFOPosition = USHRT_MAX;
1979 nListLevel = WW8ListManager::nMaxLevel;
1984 void SwWW8ImplReader::Read_LFOPosition(sal_uInt16, const sal_uInt8* pData,
1985 short nLen)
1987 if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
1988 return;
1990 if( nLen < 0 )
1992 // aktueller Level ist hier zu Ende, was ist zu tun ???
1993 nLFOPosition = USHRT_MAX;
1994 nListLevel = WW8ListManager::nMaxLevel;
1996 else
1998 // Sicherheitspruefung auf NIL Pointer
1999 if( !pData )
2000 return;
2001 short nData = SVBT16ToShort( pData );
2002 if( 0 >= nData )
2005 #94672# discussion
2006 If you have a paragraph in word with left and/or hanging indent
2007 and remove its numbering, then the indentation appears to get
2008 reset, but not back to the base style, instead its goes to a blank
2009 setting.
2010 Unless its a broken ww6 list in 97 in which case more hackery is
2011 required, some more details about that in
2012 ww8par6.cxx#SwWW8ImplReader::Read_LR
2015 if (pAktColl)
2017 pAktColl->SetFmtAttr(*GetDfltAttr( RES_PARATR_NUMRULE));
2018 pAktColl->SetFmtAttr(SvxLRSpaceItem(RES_LR_SPACE)); //#94672#
2020 else if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
2022 // --> OD 2005-10-21 #i54393#
2023 // - Reset hard set numbering rule at paragraph instead of
2024 // setting hard no numbering.
2025 // pTxtNode->SwCntntNode::SetAttr
2026 // (*GetDfltAttr(RES_PARATR_NUMRULE));
2027 pTxtNode->ResetAttr( RES_PARATR_NUMRULE );
2028 // <--
2029 pTxtNode->SetCountedInList(false);
2032 #i24553#
2033 Hmm, I can't remove outline numbering on a per txtnode basis,
2034 but I can set some normal numbering, and that overrides outline
2035 numbering, and then I can say when I come to say that I want no
2036 number on the normal numbering rule, that should all work out
2038 #115901#
2039 No special outline number in textnode any more
2041 if (pTxtNode->IsOutline())
2043 // OD 2005-10-21 #i54393#
2044 // It's not needed to call <SetCounted( false )> again - see above.
2045 // --> OD 2005-10-21 #i54393#
2046 // Assure that the numbering rule, which is retrieved at
2047 // the paragraph is the outline numbering rule, instead of
2048 // incorrectly setting the chosen outline rule.
2049 // Note: The chosen outline rule doesn't have to correspond
2050 // to the outline rule
2051 if ( pTxtNode->GetNumRule() != rDoc.GetOutlineNumRule() )
2053 pTxtNode->SetAttr(
2054 SwNumRuleItem( rDoc.GetOutlineNumRule()->GetName() ) );
2056 // <--
2059 //#94672#
2060 pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxLRSpaceItem(RES_LR_SPACE));
2061 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
2063 nLFOPosition = USHRT_MAX;
2065 else
2067 nLFOPosition = (sal_uInt16)nData-1;
2069 #94672#
2070 If we are a ww8+ style with ww7- style lists then there is a
2071 bizarre broken word bug where when the list is removed from a para
2072 the ww6 list first line indent still affects the first line
2073 indentation. Setting this flag will allow us to recover from this
2074 braindeadness
2076 if (pAktColl && (nLFOPosition == 2047-1))
2077 pCollA[nAktColl].bHasBrokenWW6List = true;
2079 // die Streamdaten sind hier 1 basiert, wir ziehen EINS ab
2080 if (USHRT_MAX > nLFOPosition)
2082 if (nLFOPosition != 2047-1) //Normal ww8+ list behaviour
2084 if (WW8ListManager::nMaxLevel == nListLevel)
2085 nListLevel = 0;
2086 else if (WW8ListManager::nMaxLevel > nListLevel)
2088 RegisterNumFmt(nLFOPosition, nListLevel);
2089 nLFOPosition = USHRT_MAX;
2090 nListLevel = WW8ListManager::nMaxLevel;
2093 else if (pPlcxMan && pPlcxMan->HasParaSprm(0xC63E))
2096 #i8114# Horrific backwards compatible ww7- lists in ww8+
2097 docs
2099 Read_ANLevelNo(13 /*equiv ww7- sprm no*/, &nListLevel, 1);
2106 // -------------------------------------------------------------------
2107 // ------------------------- Reading Controls ------------------------
2108 // -------------------------------------------------------------------
2110 bool SwWW8ImplReader::ImportFormulaControl(WW8FormulaControl &aFormula,
2111 WW8_CP nStart, SwWw8ControlType nWhich )
2113 bool bRet=false;
2115 * Save the reader state and process the sprms for this anchor cp.
2116 * Doing so will set the nPicLocFc to the offset to find the hypertext
2117 * data in the data stream.
2119 WW8_CP nEndCp = nStart+1; //Only interested in the single 0x01 character
2121 WW8ReaderSave aSave(this,nStart);
2123 WW8PLCFManResult aRes;
2124 nStart = pPlcxMan->Where();
2125 while(nStart <= nEndCp)
2127 if ( pPlcxMan->Get(&aRes)
2128 && aRes.pMemPos && aRes.nSprmId )
2130 //only interested in sprms which would set nPicLocFc
2131 if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
2133 Read_PicLoc( aRes.nSprmId, aRes.pMemPos +
2134 mpSprmParser->DistanceToData(aRes.nSprmId), 4);
2135 break;
2138 (*pPlcxMan)++;
2139 nStart = pPlcxMan->Where();
2141 ULONG nOffset = nPicLocFc;
2142 aSave.Restore(this);
2144 ULONG nOldPos = pDataStream->Tell();
2145 WW8_PIC aPic;
2146 pDataStream->Seek( nOffset);
2147 PicRead( pDataStream, &aPic, bVer67);
2149 if((aPic.lcb > 0x3A) && !pDataStream->GetError() )
2151 #if 0 // some debug fun; remove this later...
2152 int len=aPic.lcb-aPic.cbHeader;
2153 char *pBuf=(char*)malloc(len);
2154 pDataStream->Read( pBuf, len);
2155 static int _h=0;
2156 char fname[255];
2157 sprintf(fname, "data%03i.data", _h++);
2158 FILE *out=fopen(fname, "wb");
2159 fwrite(pBuf, len, 1, out);
2160 fclose(out);
2161 pDataStream->Seek( nPicLocFc + aPic.cbHeader );
2162 #endif
2163 aFormula.FormulaRead(nWhich,pDataStream);
2164 bRet = true;
2168 There is a problem with aPic, the WW8_PIC is always used even though it
2169 is too big for the WW95 files, it needs to be modified to check the
2170 version C.
2172 pDataStream->Seek( nOldPos );
2173 return(bRet);
2176 sal_Bool SwMSConvertControls::InsertFormula(WW8FormulaControl &rFormula)
2178 sal_Bool bRet = sal_False;
2180 const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory =
2181 GetServiceFactory();
2183 if(!rServiceFactory.is())
2184 return sal_False;
2186 awt::Size aSz;
2187 uno::Reference< form::XFormComponent> xFComp;
2189 if (sal_True == (bRet = rFormula.Import(rServiceFactory, xFComp, aSz)))
2191 uno::Reference <drawing::XShape> xShapeRef;
2192 if (sal_True == (bRet = InsertControl(xFComp, aSz, &xShapeRef, false)))
2193 GetShapes()->add(xShapeRef);
2195 return bRet;
2198 void WW8FormulaControl::FormulaRead(SwWw8ControlType nWhich,
2199 SvStream *pDataStream)
2201 UINT8 nField;
2202 UINT8 nHeaderByte;
2204 int nType=0;
2205 *pDataStream >> nHeaderByte;
2206 if (nHeaderByte == 0xFF) //Guesswork time, difference between 97 and 95 ?
2208 pDataStream->SeekRel(3);
2209 *pDataStream >> nHeaderByte;
2210 nType=1;
2212 fUnknown = nHeaderByte & 0x3;
2213 fDropdownIndex = (nHeaderByte & 0xFC) >> 2;
2214 *pDataStream >> nField;
2215 fToolTip = nField & 0x01;
2216 fNoMark = (nField & 0x02)>>1;
2217 fUseSize = (nField & 0x04)>>2;
2218 fNumbersOnly= (nField & 0x08)>>3;
2219 fDateOnly = (nField & 0x10)>>4;
2220 fUnused = (nField & 0xE0)>>5;
2221 *pDataStream >> nSize;
2223 *pDataStream >> hpsCheckBox;
2224 if (nType == 0)
2225 pDataStream->SeekRel(2); //Guess
2227 rtl_TextEncoding eEnc = rRdr.eStructCharSet;
2228 sTitle = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
2229 : WW8Read_xstz(*pDataStream, 0, true);
2231 if (nWhich == WW8_CT_CHECKBOX)
2233 *pDataStream >> nDefaultChecked;
2234 nChecked = nDefaultChecked;
2235 //Don't know the details yet
2236 switch (nHeaderByte)
2238 case 0x65: //01100101
2239 //use defaults ?
2240 break;
2241 case 0x1: //00000001
2242 //swap to unchecked from checked (#114841)?
2243 nChecked = false;
2244 break;
2245 case 0x5: //00000101
2246 //change to checked
2247 nChecked = true;
2248 break;
2249 default:
2250 ASSERT(!this, "unknown option, please report to cmc");
2251 break;
2254 else if (nWhich == WW8_CT_DROPDOWN)
2255 *pDataStream >> nChecked;
2256 else
2258 sDefault = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
2259 : WW8Read_xstz(*pDataStream, 0, true);
2262 sFormatting = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
2263 : WW8Read_xstz(*pDataStream, 0, true);
2265 sHelp = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
2266 : WW8Read_xstz(*pDataStream, 0, true);
2268 if (nWhich == WW8_CT_DROPDOWN) //is this the case ?
2269 fToolTip = true;
2271 if( fToolTip )
2273 sToolTip = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
2274 : WW8Read_xstz(*pDataStream, 0, true);
2277 if (nWhich == WW8_CT_DROPDOWN)
2279 bool bAllOk = true;
2280 pDataStream->SeekRel(4 * (nType ? 2 : 1));
2281 sal_uInt16 nDummy;
2282 *pDataStream >> nDummy;
2283 sal_uInt32 nNoStrings;
2284 if (!nType)
2286 sal_uInt16 nWord95NoStrings;
2287 *pDataStream >> nWord95NoStrings;
2288 nNoStrings = nWord95NoStrings;
2289 *pDataStream >> nWord95NoStrings;
2290 if (nNoStrings != nWord95NoStrings)
2291 bAllOk = false;
2292 nNoStrings = nWord95NoStrings;
2293 sal_uInt16 nDummy2;
2294 *pDataStream >> nDummy2;
2295 if (nDummy2 != 0)
2296 bAllOk = false;
2297 *pDataStream >> nDummy2;
2298 if (nDummy2 != 0xA)
2299 bAllOk = false;
2300 if (!bAllOk) //Not as expected, don't risk it at all.
2301 nNoStrings = 0;
2302 for (sal_uInt16 nI = 0; nI < nNoStrings; ++nI)
2303 pDataStream->SeekRel(2);
2305 else
2307 if (nDummy != 0xFFFF)
2308 bAllOk = false;
2309 *pDataStream >> nNoStrings;
2311 ASSERT(bAllOk,
2312 "Unknown formfield dropdown list structure. Report to cmc");
2313 if (!bAllOk) //Not as expected, don't risk it at all.
2314 nNoStrings = 0;
2315 maListEntries.reserve(nNoStrings);
2316 for (sal_uInt32 nI = 0; nI < nNoStrings; ++nI)
2318 String sEntry = !nType ? WW8ReadPString(*pDataStream, eEnc, false)
2319 : WW8Read_xstz(*pDataStream, 0, false);
2320 maListEntries.push_back(sEntry);
2325 WW8FormulaListBox::WW8FormulaListBox(SwWW8ImplReader &rR)
2326 : WW8FormulaControl( CREATE_CONST_ASC(SL::aListBox), rR)
2330 //Miserable hack to get a hardcoded guesstimate of the size of a list dropdown
2331 //box's first entry to set as the lists default size
2332 awt::Size SwWW8ImplReader::MiserableDropDownFormHack(const String &rString,
2333 uno::Reference<beans::XPropertySet>& rPropSet)
2335 awt::Size aRet;
2336 struct CtrlFontMapEntry
2338 USHORT nWhichId;
2339 const sal_Char* pPropNm;
2341 const CtrlFontMapEntry aMapTable[] =
2343 { RES_CHRATR_COLOR, "TextColor" },
2344 { RES_CHRATR_FONT, "FontName" },
2345 { RES_CHRATR_FONTSIZE, "FontHeight" },
2346 { RES_CHRATR_WEIGHT, "FontWeight" },
2347 { RES_CHRATR_UNDERLINE, "FontUnderline" },
2348 { RES_CHRATR_CROSSEDOUT, "FontStrikeout" },
2349 { RES_CHRATR_POSTURE, "FontSlant" },
2350 { 0, 0 }
2353 Font aFont;
2354 uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
2355 rPropSet->getPropertySetInfo();
2357 uno::Any aTmp;
2358 for (const CtrlFontMapEntry* pMap = aMapTable; pMap->nWhichId; ++pMap)
2360 bool bSet = true;
2361 const SfxPoolItem* pItem = GetFmtAttr( pMap->nWhichId );
2362 ASSERT(pItem, "Impossible");
2363 if (!pItem)
2364 continue;
2366 switch ( pMap->nWhichId )
2368 case RES_CHRATR_COLOR:
2370 String pNm;
2371 if (xPropSetInfo->hasPropertyByName(pNm = C2U("TextColor")))
2373 aTmp <<= (sal_Int32)((SvxColorItem*)pItem)->GetValue().GetColor();
2374 rPropSet->setPropertyValue(pNm, aTmp);
2377 aFont.SetColor(((SvxColorItem*)pItem)->GetValue());
2378 break;
2379 case RES_CHRATR_FONT:
2381 const SvxFontItem *pFontItem = (SvxFontItem *)pItem;
2382 String pNm;
2383 if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontStyleName")))
2385 aTmp <<= rtl::OUString( pFontItem->GetStyleName());
2386 rPropSet->setPropertyValue( pNm, aTmp );
2388 if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontFamily")))
2390 aTmp <<= (sal_Int16)pFontItem->GetFamily();
2391 rPropSet->setPropertyValue( pNm, aTmp );
2393 if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontCharset")))
2395 aTmp <<= (sal_Int16)pFontItem->GetCharSet();
2396 rPropSet->setPropertyValue( pNm, aTmp );
2398 if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontPitch")))
2400 aTmp <<= (sal_Int16)pFontItem->GetPitch();
2401 rPropSet->setPropertyValue( pNm, aTmp );
2404 aTmp <<= rtl::OUString( pFontItem->GetFamilyName());
2405 aFont.SetName( pFontItem->GetFamilyName() );
2406 aFont.SetStyleName( pFontItem->GetStyleName() );
2407 aFont.SetFamily( pFontItem->GetFamily() );
2408 aFont.SetCharSet( pFontItem->GetCharSet() );
2409 aFont.SetPitch( pFontItem->GetPitch() );
2411 break;
2413 case RES_CHRATR_FONTSIZE:
2415 Size aSize( aFont.GetSize().Width(),
2416 ((SvxFontHeightItem*)pItem)->GetHeight() );
2417 aTmp <<= ((float)aSize.Height()) / 20.0;
2419 aFont.SetSize(OutputDevice::LogicToLogic(aSize, MAP_TWIP,
2420 MAP_100TH_MM));
2422 break;
2424 case RES_CHRATR_WEIGHT:
2425 aTmp <<= (float)VCLUnoHelper::ConvertFontWeight(
2426 ((SvxWeightItem*)pItem)->GetWeight() );
2427 aFont.SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
2428 break;
2430 case RES_CHRATR_UNDERLINE:
2431 aTmp <<= (sal_Int16)(((SvxUnderlineItem*)pItem)->GetLineStyle());
2432 aFont.SetUnderline(((SvxUnderlineItem*)pItem)->GetLineStyle());
2433 break;
2435 case RES_CHRATR_CROSSEDOUT:
2436 aTmp <<= (sal_Int16)( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
2437 aFont.SetStrikeout( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
2438 break;
2440 case RES_CHRATR_POSTURE:
2441 aTmp <<= (sal_Int16)( ((SvxPostureItem*)pItem)->GetPosture() );
2442 aFont.SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
2443 break;
2445 default:
2446 bSet = false;
2447 break;
2450 if (bSet && xPropSetInfo->hasPropertyByName(C2U(pMap->pPropNm)))
2451 rPropSet->setPropertyValue(C2U(pMap->pPropNm), aTmp);
2453 // now calculate the size of the control
2454 OutputDevice* pOut = Application::GetDefaultDevice();
2455 ASSERT(pOut, "Impossible");
2456 if (pOut)
2458 pOut->Push( PUSH_FONT | PUSH_MAPMODE );
2459 pOut->SetMapMode( MapMode( MAP_100TH_MM ));
2460 pOut->SetFont( aFont );
2461 aRet.Width = pOut->GetTextWidth(rString);
2462 aRet.Width += 500; //plus size of button, total hack territory
2463 aRet.Height = pOut->GetTextHeight();
2464 pOut->Pop();
2466 return aRet;
2469 sal_Bool WW8FormulaListBox::Import(const uno::Reference <
2470 lang::XMultiServiceFactory> &rServiceFactory,
2471 uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
2473 uno::Reference<uno::XInterface> xCreate = rServiceFactory->createInstance(
2474 C2U("com.sun.star.form.component.ComboBox"));
2475 if( !xCreate.is() )
2476 return sal_False;
2478 rFComp = uno::Reference<form::XFormComponent>(xCreate, uno::UNO_QUERY);
2479 if( !rFComp.is() )
2480 return sal_False;
2482 uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY);
2484 uno::Any aTmp;
2485 if (sTitle.Len())
2486 aTmp <<= rtl::OUString(sTitle);
2487 else
2488 aTmp <<= rtl::OUString(sName);
2489 xPropSet->setPropertyValue(C2U("Name"), aTmp );
2491 if (sToolTip.Len())
2493 aTmp <<= rtl::OUString(sToolTip);
2494 xPropSet->setPropertyValue(C2U("HelpText"), aTmp );
2497 sal_Bool bDropDown(sal_True);
2498 xPropSet->setPropertyValue(C2U("Dropdown"), cppu::bool2any(bDropDown));
2500 if (!maListEntries.empty())
2502 sal_uInt32 nLen = maListEntries.size();
2503 uno::Sequence< ::rtl::OUString > aListSource(nLen);
2504 for (sal_uInt32 nI = 0; nI < nLen; ++nI)
2505 aListSource[nI] = rtl::OUString(maListEntries[nI]);
2506 aTmp <<= aListSource;
2507 xPropSet->setPropertyValue(C2U("StringItemList"), aTmp );
2509 aTmp <<= aListSource[0];
2510 xPropSet->setPropertyValue(C2U("DefaultText"), aTmp );
2512 rSz = rRdr.MiserableDropDownFormHack(maListEntries[0], xPropSet);
2514 else
2516 static const sal_Unicode aBlank[] =
2518 0x2002,0x2002,0x2002,0x2002,0x2002
2520 rSz = rRdr.MiserableDropDownFormHack(String(aBlank), xPropSet);
2523 return sal_True;
2526 WW8FormulaCheckBox::WW8FormulaCheckBox(SwWW8ImplReader &rR)
2527 : WW8FormulaControl( CREATE_CONST_ASC(SL::aCheckBox), rR)
2531 static void lcl_AddToPropertyContainer
2532 (uno::Reference<beans::XPropertySet> xPropSet,
2533 const rtl::OUString & rPropertyName, const rtl::OUString & rValue)
2535 uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
2536 xPropSet->getPropertySetInfo();
2537 if (xPropSetInfo.is() &&
2538 ! xPropSetInfo->hasPropertyByName(rPropertyName))
2540 uno::Reference<beans::XPropertyContainer>
2541 xPropContainer(xPropSet, uno::UNO_QUERY);
2542 uno::Any aAny(C2U(""));
2543 xPropContainer->addProperty
2544 (rPropertyName,
2545 static_cast<sal_Int16>(beans::PropertyAttribute::BOUND ||
2546 beans::PropertyAttribute::REMOVABLE),
2547 aAny);
2550 uno::Any aAnyValue(rValue);
2551 xPropSet->setPropertyValue(rPropertyName, aAnyValue );
2554 sal_Bool WW8FormulaCheckBox::Import(const uno::Reference <
2555 lang::XMultiServiceFactory> &rServiceFactory,
2556 uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
2558 uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance(
2559 C2U("com.sun.star.form.component.CheckBox"));
2560 if( !xCreate.is() )
2561 return sal_False;
2563 rFComp = uno::Reference< form::XFormComponent >( xCreate, uno::UNO_QUERY );
2564 if( !rFComp.is() )
2565 return sal_False;
2567 uno::Reference< beans::XPropertySet > xPropSet( xCreate, uno::UNO_QUERY );
2569 rSz.Width = 16 * hpsCheckBox;
2570 rSz.Height = 16 * hpsCheckBox;
2572 uno::Any aTmp;
2573 if (sTitle.Len())
2574 aTmp <<= rtl::OUString(sTitle);
2575 else
2576 aTmp <<= rtl::OUString(sName);
2577 xPropSet->setPropertyValue(C2U("Name"), aTmp );
2579 aTmp <<= (sal_Int16)nChecked;
2580 xPropSet->setPropertyValue(C2U("DefaultState"), aTmp);
2582 if( sToolTip.Len() )
2583 lcl_AddToPropertyContainer(xPropSet, C2U("HelpText"), sToolTip);
2585 if( sHelp.Len() )
2586 lcl_AddToPropertyContainer(xPropSet, C2U("HelpF1Text"), sHelp);
2588 return sal_True;
2592 WW8FormulaEditBox::WW8FormulaEditBox(SwWW8ImplReader &rR)
2593 : WW8FormulaControl( CREATE_CONST_ASC(SL::aTextField) ,rR)
2597 sal_Bool SwMSConvertControls::InsertControl(
2598 const uno::Reference< form::XFormComponent > & rFComp,
2599 const awt::Size& rSize, uno::Reference< drawing::XShape > *pShape,
2600 BOOL bFloatingCtrl)
2602 const uno::Reference< container::XIndexContainer > &rComps = GetFormComps();
2603 uno::Any aTmp( &rFComp, ::getCppuType((const uno::Reference<
2604 form::XFormComponent >*)0) );
2605 rComps->insertByIndex( rComps->getCount(), aTmp );
2607 const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory =
2608 GetServiceFactory();
2609 if( !rServiceFactory.is() )
2610 return sal_False;
2612 uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance(
2613 C2U("com.sun.star.drawing.ControlShape"));
2614 if( !xCreate.is() )
2615 return sal_False;
2617 uno::Reference< drawing::XShape > xShape =
2618 uno::Reference< drawing::XShape >(xCreate, uno::UNO_QUERY);
2620 DBG_ASSERT(xShape.is(), "XShape nicht erhalten");
2621 xShape->setSize(rSize);
2623 uno::Reference< beans::XPropertySet > xShapePropSet(
2624 xCreate, uno::UNO_QUERY );
2626 //I lay a small bet that this will change to
2627 //INT16 nTemp=TextContentAnchorType::AS_CHARACTER;
2628 INT16 nTemp;
2629 if (bFloatingCtrl)
2630 nTemp= text::TextContentAnchorType_AT_PARAGRAPH;
2631 else
2632 nTemp= text::TextContentAnchorType_AS_CHARACTER;
2634 aTmp <<= nTemp;
2635 xShapePropSet->setPropertyValue(C2U("AnchorType"), aTmp );
2637 nTemp= text::VertOrientation::TOP;
2638 aTmp <<= nTemp;
2639 xShapePropSet->setPropertyValue(C2U("VertOrient"), aTmp );
2641 uno::Reference< text::XText > xDummyTxtRef;
2642 uno::Reference< text::XTextRange > xTxtRg =
2643 new SwXTextRange( *pPaM, xDummyTxtRef );
2645 aTmp.setValue(&xTxtRg,::getCppuType((
2646 uno::Reference< text::XTextRange >*)0));
2647 xShapePropSet->setPropertyValue(C2U("TextRange"), aTmp );
2649 // Das Control-Model am Control-Shape setzen
2650 uno::Reference< drawing::XControlShape > xControlShape( xShape,
2651 uno::UNO_QUERY );
2652 uno::Reference< awt::XControlModel > xControlModel( rFComp,
2653 uno::UNO_QUERY );
2654 xControlShape->setControl( xControlModel );
2656 if (pShape)
2657 *pShape = xShape;
2659 return sal_True;
2662 /* vi:set tabstop=4 shiftwidth=4 expandtab: */