Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <svl/itemiter.hxx>
22 : #include <vcl/svapp.hxx>
23 : #include <vcl/outdev.hxx>
24 :
25 : #include <toolkit/helper/vclunohelper.hxx>
26 : #include <com/sun/star/form/XFormsSupplier.hpp>
27 : #include <com/sun/star/form/XForm.hpp>
28 : #include <com/sun/star/form/XImageProducerSupplier.hpp>
29 : #include <com/sun/star/form/XFormController.hpp>
30 : #include <com/sun/star/frame/XStorable.hpp>
31 : #include <com/sun/star/frame/XModel.hpp>
32 : #include <com/sun/star/drawing/XConnectableShape.hpp>
33 : #include <com/sun/star/drawing/XConnectorShape.hpp>
34 : #include <com/sun/star/drawing/XShape.hpp>
35 : #include <com/sun/star/drawing/XControlShape.hpp>
36 : #include <com/sun/star/drawing/XShapeAligner.hpp>
37 : #include <com/sun/star/drawing/XShapeGroup.hpp>
38 : #include <com/sun/star/drawing/XUniversalShapeDescriptor.hpp>
39 : #include <com/sun/star/drawing/XShapeMirror.hpp>
40 : #include <com/sun/star/drawing/XShapeArranger.hpp>
41 : #include <com/sun/star/drawing/XDrawPage.hpp>
42 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
43 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
45 : #include <com/sun/star/container/XIndexContainer.hpp>
46 : #include <com/sun/star/text/VertOrientation.hpp>
47 : #include <com/sun/star/text/TextContentAnchorType.hpp>
48 : #include <comphelper/extract.hxx>
49 : #include <comphelper/stlunosequence.hxx>
50 : #include <com/sun/star/beans/XPropertyContainer.hpp>
51 : #include <com/sun/star/beans/PropertyAttribute.hpp>
52 :
53 : #include <algorithm>
54 : #include <functional>
55 : #include <hintids.hxx>
56 : #include <editeng/fontitem.hxx>
57 : #include <editeng/lrspitem.hxx>
58 : #include <editeng/fhgtitem.hxx>
59 : #include <editeng/colritem.hxx>
60 : #include <editeng/wghtitem.hxx>
61 : #include <editeng/crossedoutitem.hxx>
62 : #include <editeng/udlnitem.hxx>
63 : #include <editeng/postitem.hxx>
64 : #include <unotextrange.hxx>
65 : #include <doc.hxx>
66 : #include <docary.hxx>
67 : #include <docsh.hxx>
68 : #include <numrule.hxx>
69 : #include <paratr.hxx>
70 : #include <charatr.hxx>
71 : #include <charfmt.hxx>
72 : #include <ndtxt.hxx>
73 : #include <expfld.hxx>
74 : #include <fmtfld.hxx>
75 : #include <flddropdown.hxx>
76 : #include "writerhelper.hxx"
77 : #include "writerwordglue.hxx"
78 : #include "ww8par.hxx"
79 : #include "ww8par2.hxx" // wg. Listen-Attributen in Styles
80 :
81 : #include <IMark.hxx>
82 : #include <unotools/fltrcfg.hxx>
83 : #include <xmloff/odffields.hxx>
84 :
85 : #include <stdio.h>
86 :
87 : using namespace com::sun::star;
88 : using namespace sw::util;
89 : using namespace sw::types;
90 : using namespace sw::mark;
91 :
92 : //-----------------------------------------
93 : // UNO-Controls
94 : //-----------------------------------------
95 :
96 : //cmc, OCX i.e. word 97 form controls
97 0 : eF_ResT SwWW8ImplReader::Read_F_OCX( WW8FieldDesc*, String& )
98 : {
99 0 : if( bObj && nPicLocFc )
100 0 : nObjLocFc = nPicLocFc;
101 0 : bEmbeddObj = true;
102 0 : return FLD_TEXT;
103 : }
104 :
105 0 : eF_ResT SwWW8ImplReader::Read_F_FormTextBox( WW8FieldDesc* pF, String& rStr )
106 : {
107 0 : WW8FormulaEditBox aFormula(*this);
108 :
109 0 : if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) {
110 0 : ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_EDIT);
111 : }
112 :
113 : /*
114 : Here we have a small complication. This formula control contains
115 : the default text that is displayed if you edit the form field in
116 : the "default text" area. But MSOffice does not display that
117 : information, instead it display the result of the field,
118 : MSOffice just uses the default text of the control as its
119 : initial value for the displayed default text. So we will swap in
120 : the field result into the formula here in place of the default
121 : text.
122 : */
123 :
124 0 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
125 0 : sal_Bool bUseEnhFields = rOpt.IsUseEnhancedFields();
126 :
127 0 : if (!bUseEnhFields) {
128 0 : aFormula.sDefault = GetFieldResult(pF);
129 :
130 0 : SwInputField aFld((SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
131 0 : aFormula.sDefault , aFormula.sTitle , INP_TXT, 0 );
132 0 : aFld.SetHelp(aFormula.sHelp);
133 0 : aFld.SetToolTip(aFormula.sToolTip);
134 :
135 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
136 0 : return FLD_OK;
137 : } else {
138 0 : WW8PLCFx_Book* pB = pPlcxMan->GetBook();
139 0 : String aBookmarkName;
140 0 : if (pB!=NULL) {
141 0 : WW8_CP currentCP=pF->nSCode;
142 0 : WW8_CP currentLen=pF->nLen;
143 :
144 : sal_uInt16 bkmFindIdx;
145 0 : String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
146 :
147 0 : if (aBookmarkFind.Len()>0) {
148 0 : pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark bookmark as consumed, such that tl'll not get inserted as a "normal" bookmark again
149 0 : if (aBookmarkFind.Len()>0) {
150 0 : aBookmarkName=aBookmarkFind;
151 : }
152 0 : }
153 : }
154 :
155 0 : if (pB!=NULL && aBookmarkName.Len()==0) {
156 0 : aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
157 : }
158 :
159 :
160 0 : if (aBookmarkName.Len()>0) {
161 0 : maFieldStack.back().SetBookmarkName(aBookmarkName);
162 0 : maFieldStack.back().SetBookmarkType(ODF_FORMTEXT);
163 0 : maFieldStack.back().getParameters()["Description"] = uno::makeAny(OUString(aFormula.sToolTip));
164 0 : maFieldStack.back().getParameters()["Name"] = uno::makeAny(OUString(aFormula.sTitle));
165 : }
166 0 : return FLD_TEXT;
167 0 : }
168 : }
169 :
170 0 : eF_ResT SwWW8ImplReader::Read_F_FormCheckBox( WW8FieldDesc* pF, String& rStr )
171 : {
172 0 : WW8FormulaCheckBox aFormula(*this);
173 :
174 0 : if (!pFormImpl)
175 0 : pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
176 :
177 0 : if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
178 0 : ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_CHECKBOX);
179 0 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
180 0 : sal_Bool bUseEnhFields = rOpt.IsUseEnhancedFields();
181 :
182 0 : if (!bUseEnhFields) {
183 0 : pFormImpl->InsertFormula(aFormula);
184 0 : return FLD_OK;
185 : } else {
186 0 : String aBookmarkName;
187 0 : WW8PLCFx_Book* pB = pPlcxMan->GetBook();
188 0 : if (pB!=NULL) {
189 0 : WW8_CP currentCP=pF->nSCode;
190 0 : WW8_CP currentLen=pF->nLen;
191 :
192 : sal_uInt16 bkmFindIdx;
193 0 : String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
194 :
195 0 : if (aBookmarkFind.Len()>0) {
196 0 : pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
197 0 : if (aBookmarkFind.Len()>0) {
198 0 : aBookmarkName=aBookmarkFind;
199 : }
200 0 : }
201 : }
202 :
203 0 : if (pB!=NULL && aBookmarkName.Len()==0) {
204 0 : aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
205 : }
206 :
207 0 : if (aBookmarkName.Len()>0)
208 : {
209 0 : IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
210 : IFieldmark* pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeNoTextFieldBookmark(
211 0 : *pPaM, aBookmarkName, ODF_FORMCHECKBOX ) );
212 : OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
213 0 : if (pFieldmark!=NULL) {
214 0 : IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
215 0 : ICheckboxFieldmark* pCheckboxFm = dynamic_cast<ICheckboxFieldmark*>(pFieldmark);
216 0 : (*pParameters)[ODF_FORMCHECKBOX_NAME] = uno::makeAny(OUString(aFormula.sTitle));
217 0 : (*pParameters)[ODF_FORMCHECKBOX_HELPTEXT] = uno::makeAny(OUString(aFormula.sToolTip));
218 :
219 0 : if(pCheckboxFm)
220 0 : pCheckboxFm->SetChecked(aFormula.nChecked);
221 : // set field data here...
222 : }
223 : }
224 0 : return FLD_OK;
225 0 : }
226 : }
227 :
228 0 : eF_ResT SwWW8ImplReader::Read_F_FormListBox( WW8FieldDesc* pF, String& rStr)
229 : {
230 0 : WW8FormulaListBox aFormula(*this);
231 :
232 0 : if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
233 0 : ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_DROPDOWN);
234 :
235 0 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
236 0 : sal_Bool bUseEnhFields = rOpt.IsUseEnhancedFields();
237 :
238 0 : if (!bUseEnhFields)
239 : {
240 0 : SwDropDownField aFld((SwDropDownFieldType*)rDoc.GetSysFldType(RES_DROPDOWN));
241 :
242 0 : aFld.SetName(aFormula.sTitle);
243 0 : aFld.SetHelp(aFormula.sHelp);
244 0 : aFld.SetToolTip(aFormula.sToolTip);
245 :
246 0 : if (!aFormula.maListEntries.empty())
247 : {
248 0 : aFld.SetItems(aFormula.maListEntries);
249 0 : int nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0;
250 0 : aFld.SetSelectedItem(aFormula.maListEntries[nIndex]);
251 : }
252 :
253 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
254 0 : return FLD_OK;
255 : }
256 : else
257 : {
258 : // TODO: review me
259 0 : String aBookmarkName;
260 0 : WW8PLCFx_Book* pB = pPlcxMan->GetBook();
261 0 : if (pB!=NULL)
262 : {
263 0 : WW8_CP currentCP=pF->nSCode;
264 0 : WW8_CP currentLen=pF->nLen;
265 :
266 : sal_uInt16 bkmFindIdx;
267 0 : String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
268 :
269 0 : if (aBookmarkFind.Len()>0)
270 : {
271 0 : pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
272 0 : if (aBookmarkFind.Len()>0)
273 0 : aBookmarkName=aBookmarkFind;
274 0 : }
275 : }
276 :
277 0 : if (pB!=NULL && aBookmarkName.Len()==0)
278 0 : aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
279 :
280 0 : if (aBookmarkName.Len()>0)
281 : {
282 0 : IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
283 : IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>(
284 0 : pMarksAccess->makeNoTextFieldBookmark( *pPaM, aBookmarkName, ODF_FORMDROPDOWN ) );
285 : OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
286 0 : if ( pFieldmark != NULL )
287 : {
288 0 : uno::Sequence< OUString > vListEntries(aFormula.maListEntries.size());
289 0 : ::std::copy(aFormula.maListEntries.begin(), aFormula.maListEntries.end(), ::comphelper::stl_begin(vListEntries));
290 0 : (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY] = uno::makeAny(vListEntries);
291 0 : sal_Int32 nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0;
292 0 : (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] = uno::makeAny(nIndex);
293 : // set field data here...
294 : }
295 : }
296 :
297 0 : return FLD_OK;
298 0 : }
299 : }
300 :
301 0 : eF_ResT SwWW8ImplReader::Read_F_HTMLControl(WW8FieldDesc*, String&)
302 : {
303 0 : if( bObj && nPicLocFc )
304 0 : nObjLocFc = nPicLocFc;
305 0 : bEmbeddObj = true;
306 0 : return FLD_TEXT;
307 : }
308 :
309 27 : void SwWW8ImplReader::DeleteFormImpl()
310 : {
311 27 : delete pFormImpl, pFormImpl = 0;
312 27 : }
313 :
314 : //----------------------------------------------------------------------------
315 : // WW8ListManager oeffentliche Methoden stehen ganz am Ende
316 : //------------------------- ============ --------------- ============ --------
317 :
318 :
319 :
320 : // Hilfs-Deklarationen ///////////////////////////////////////////////////////
321 : //
322 : // Style Id's for each level
323 : typedef sal_uInt16 WW8aIdSty[WW8ListManager::nMaxLevel];
324 : // Zeichenattribute aus GrpprlChpx
325 : typedef SfxItemSet* WW8aISet[WW8ListManager::nMaxLevel];
326 : // Zeichen Style Pointer
327 : typedef SwCharFmt* WW8aCFmt[WW8ListManager::nMaxLevel];
328 :
329 : struct WW8LST // nur DIE Eintraege, die WIR benoetigen!
330 : {
331 : WW8aIdSty aIdSty; // Style Id's for each level,
332 : // nIStDNil if no style linked
333 : sal_uInt32 nIdLst; // Unique List ID
334 : sal_uInt32 nTplC; // Unique template code - Was ist das bloss?
335 : sal_uInt8 bSimpleList:1; // Flag: Liste hat nur EINEN Level
336 : sal_uInt8 bRestartHdn:1; // WW6-Kompatibilitaets-Flag:
337 : // true if the list should start numbering over
338 : }; // at the beginning of each section
339 :
340 : const sal_uInt32 cbLSTF=28;
341 :
342 : struct WW8LFO // nur DIE Eintraege, die WIR benoetigen!
343 : {
344 : SwNumRule* pNumRule; // Parent NumRule
345 : sal_uInt32 nIdLst; // Unique List ID
346 : sal_uInt8 nLfoLvl; // count of levels whose format is overridden
347 : bool bSimpleList;
348 : };
349 :
350 : struct WW8LVL // nur DIE Eintraege, die WIR benoetigen!
351 : {
352 : sal_Int32 nStartAt; // start at value for this value
353 : sal_Int32 nV6DxaSpace;// Ver6-Compatible: min Space between Num anf text::Paragraph
354 : sal_Int32 nV6Indent; // Ver6-Compatible: Breite des Prefix Textes; ggfs. zur
355 : // Definition d. Erstzl.einzug nutzen!
356 : // Absatzattribute aus GrpprlPapx
357 : sal_uInt16 nDxaLeft; // linker Einzug
358 : short nDxaLeft1; // Erstzeilen-Einzug
359 :
360 : sal_uInt8 nNFC; // number format code
361 : // Offset der Feldkodes im Num-X-String
362 : sal_uInt8 aOfsNumsXCH[WW8ListManager::nMaxLevel];
363 : sal_uInt8 nLenGrpprlChpx; // length, in bytes, of the LVL's grpprlChpx
364 : sal_uInt8 nLenGrpprlPapx; // length, in bytes, of the LVL's grpprlPapx
365 : sal_uInt8 nAlign: 2; // alignment (left, right, centered) of the number
366 : sal_uInt8 bLegal: 1; // egal
367 : sal_uInt8 bNoRest:1; // egal
368 : sal_uInt8 bV6Prev:1; // Ver6-Compatible: number will include previous levels
369 : sal_uInt8 bV6PrSp:1; // Ver6-Compatible: egal
370 : sal_uInt8 bV6: 1; // falls true , beachte die V6-Compatible Eintraege!
371 : sal_uInt8 bDummy: 1; // (macht das Byte voll)
372 :
373 : };
374 :
375 : struct WW8LFOLVL
376 : {
377 : sal_Int32 nStartAt; // start-at value if bFormat==false and bStartAt == true
378 : // (if bFormat==true, the start-at is stored in the LVL)
379 : sal_uInt8 nLevel; // the level to be overridden
380 : // dieses Byte ist _absichtlich_ nicht in das folgende Byte hineingepackt !!
381 : // (siehe Kommentar unten bei struct WW8LFOInfo)
382 :
383 : sal_uInt8 bStartAt :1; // true if the start-at value is overridden
384 : sal_uInt8 bFormat :1; // true if the formatting is overriden
385 :
386 2195 : WW8LFOLVL() :
387 2195 : nStartAt(1), nLevel(0), bStartAt(1), bFormat(0) {}
388 : };
389 :
390 : // in den ListenInfos zu speichernde Daten ///////////////////////////////////
391 : //
392 241 : struct WW8LSTInfo // sortiert nach nIdLst (in WW8 verwendete Listen-Id)
393 : {
394 : std::vector<ww::bytes> maParaSprms;
395 : WW8aIdSty aIdSty; // Style Id's for each level
396 : WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
397 : WW8aCFmt aCharFmt; // Zeichen Style Pointer
398 :
399 : SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
400 : sal_uInt32 nIdLst; // WW8Id dieser Liste
401 : sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
402 : sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
403 : // oder beim Reader-Ende geloescht werden sollte
404 :
405 241 : WW8LSTInfo(SwNumRule* pNumRule_, WW8LST& aLST)
406 : : pNumRule(pNumRule_), nIdLst(aLST.nIdLst),
407 241 : bSimpleList(aLST.bSimpleList), bUsedInDoc(0)
408 : {
409 241 : memcpy( aIdSty, aLST.aIdSty, sizeof( aIdSty ));
410 241 : memset(&aItemSet, 0, sizeof( aItemSet ));
411 241 : memset(&aCharFmt, 0, sizeof( aCharFmt ));
412 241 : }
413 :
414 : };
415 :
416 : // in den ListenFormatOverrideInfos zu speichernde Daten /////////////////////
417 : //
418 243 : struct WW8LFOInfo // unsortiert, d.h. Reihenfolge genau wie im WW8 Stream
419 : {
420 : std::vector<ww::bytes> maParaSprms;
421 : std::vector<WW8LFOLVL> maOverrides;
422 : SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
423 : // entweder: Liste in LSTInfos oder eigene Liste
424 : // (im Ctor erstmal die aus den LSTInfos merken)
425 :
426 : sal_uInt32 nIdLst; // WW8-Id der betreffenden Liste
427 : sal_uInt8 nLfoLvl; // count of levels whose format is overridden
428 : // Ja, ich natuerlich koennten wir nLfoLvl (mittels :4) noch in das folgende
429 : // Byte mit hineinpacken, doch waere das eine ziemliche Fehlerquelle,
430 : // an dem Tag, wo MS ihr Listenformat auf mehr als 15 Level aufbohren.
431 :
432 : sal_uInt8 bOverride :1;// Flag, ob die NumRule nicht in maLSTInfos steht,
433 : // sondern fuer pLFOInfos NEU angelegt wurde
434 : sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
435 : sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
436 : // oder beim Reader-Ende geloescht werden sollte
437 : sal_uInt8 bLSTbUIDSet :1;// Flag, ob bUsedInDoc in maLSTInfos gesetzt wurde,
438 : // und nicht nochmals gesetzt zu werden braucht
439 : WW8LFOInfo(const WW8LFO& rLFO);
440 : };
441 :
442 243 : WW8LFOInfo::WW8LFOInfo(const WW8LFO& rLFO)
443 : : maParaSprms(WW8ListManager::nMaxLevel)
444 : , maOverrides(WW8ListManager::nMaxLevel)
445 : , pNumRule(rLFO.pNumRule)
446 : , nIdLst(rLFO.nIdLst)
447 : , nLfoLvl(rLFO.nLfoLvl)
448 : , bOverride(rLFO.nLfoLvl ? true : false)
449 : , bSimpleList(rLFO.bSimpleList)
450 : , bUsedInDoc(0)
451 243 : , bLSTbUIDSet(0)
452 : {
453 243 : }
454 :
455 :
456 :
457 : // Hilfs-Methoden ////////////////////////////////////////////////////////////
458 : //
459 :
460 : // finden der Sprm-Parameter-Daten, falls Sprm im Grpprl enthalten
461 7896 : sal_uInt8* WW8ListManager::GrpprlHasSprm(sal_uInt16 nId, sal_uInt8& rSprms,
462 : sal_uInt8 nLen)
463 : {
464 7896 : return maSprmParser.findSprmData(nId, &rSprms, nLen);
465 : }
466 :
467 : class ListWithId : public std::unary_function<const WW8LSTInfo *, bool>
468 : {
469 : private:
470 : sal_uInt32 mnIdLst;
471 : public:
472 295 : explicit ListWithId(sal_uInt32 nIdLst) : mnIdLst(nIdLst) {}
473 7075 : bool operator() (const WW8LSTInfo *pEntry) const
474 7075 : { return (pEntry->nIdLst == mnIdLst); }
475 : };
476 :
477 : // Zugriff ueber die List-Id des LST Eintrags
478 295 : WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const
479 : {
480 : std::vector<WW8LSTInfo *>::const_iterator aResult =
481 295 : std::find_if(maLSTInfos.begin(),maLSTInfos.end(),ListWithId(nIdLst));
482 295 : if (aResult == maLSTInfos.end())
483 0 : return 0;
484 295 : return *aResult;
485 : }
486 :
487 1899 : static void lcl_CopyGreaterEight(String &rDest, String &rSrc,
488 : xub_StrLen nStart, xub_StrLen nLen = STRING_LEN)
489 : {
490 1899 : if (nLen > rSrc.Len() || nLen == STRING_LEN)
491 559 : nLen = rSrc.Len();
492 20874 : for (xub_StrLen nI = nStart; nI < nLen; ++nI)
493 : {
494 18975 : sal_Unicode nChar = rSrc.GetChar(nI);
495 18975 : if (nChar > WW8ListManager::nMaxLevel)
496 10992 : rDest.Append(nChar);
497 : }
498 1899 : }
499 :
500 2017 : bool WW8ListManager::ReadLVL(SwNumFmt& rNumFmt, SfxItemSet*& rpItemSet,
501 : sal_uInt16 nLevelStyle, bool bSetStartNo,
502 : std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
503 : ww::bytes &rParaSprms)
504 : {
505 2017 : sal_uInt8 aBits1(0);
506 2017 : sal_uInt16 nStartNo(0); // Start-Nr. fuer den Writer
507 : SvxExtNumType eType; // Writer-Num-Typ
508 : SvxAdjust eAdj; // Ausrichtung (Links/rechts/zent.)
509 2017 : sal_Unicode cBullet(0x2190); // default safe bullet
510 :
511 2017 : sal_Unicode cGrfBulletCP(USHRT_MAX);
512 :
513 2017 : String sPrefix;
514 4034 : String sPostfix;
515 : WW8LVL aLVL;
516 : //
517 : // 1. LVLF einlesen
518 : //
519 2017 : memset(&aLVL, 0, sizeof( aLVL ));
520 2017 : rSt >> aLVL.nStartAt;
521 2017 : rSt >> aLVL.nNFC;
522 2017 : rSt >> aBits1;
523 2017 : if( 0 != rSt.GetError() ) return false;
524 2017 : aLVL.nAlign = (aBits1 & 0x03);
525 2017 : if( aBits1 & 0x10 ) aLVL.bV6Prev = true;
526 2017 : if( aBits1 & 0x20 ) aLVL.bV6PrSp = true;
527 2017 : if( aBits1 & 0x40 ) aLVL.bV6 = true;
528 2017 : bool bLVLOkB = true;
529 2017 : sal_uInt8 nLevelB = 0;
530 20170 : for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
531 : {
532 18153 : rSt >> aLVL.aOfsNumsXCH[ nLevelB ];
533 18153 : if( 0 != rSt.GetError() )
534 : {
535 0 : bLVLOkB = false;
536 0 : break;
537 : }
538 : }
539 :
540 2017 : if( !bLVLOkB )
541 0 : return false;
542 :
543 2017 : sal_uInt8 ixchFollow(0);
544 2017 : rSt >> ixchFollow;
545 2017 : rSt >> aLVL.nV6DxaSpace;
546 2017 : rSt >> aLVL.nV6Indent;
547 2017 : rSt >> aLVL.nLenGrpprlChpx;
548 2017 : rSt >> aLVL.nLenGrpprlPapx;
549 2017 : rSt.SeekRel( 2 );
550 2017 : if( 0 != rSt.GetError()) return false;
551 :
552 : //
553 : // 2. ggfs. PAPx einlesen und nach Einzug-Werten suchen
554 : //
555 2017 : short nTabPos = 0; // #i86652# - read tab setting
556 2017 : if( aLVL.nLenGrpprlPapx )
557 : {
558 : sal_uInt8 aGrpprlPapx[ 255 ];
559 1586 : if(aLVL.nLenGrpprlPapx != rSt.Read(&aGrpprlPapx,aLVL.nLenGrpprlPapx))
560 0 : return false;
561 : // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
562 : sal_uInt8* pSprm;
563 1586 : if (
564 1621 : (0 != (pSprm = GrpprlHasSprm(0x840F,aGrpprlPapx[0],aLVL.nLenGrpprlPapx))) ||
565 35 : (0 != (pSprm = GrpprlHasSprm(0x845E,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)))
566 : )
567 : {
568 1582 : sal_uInt8 *pBegin = pSprm-2;
569 7910 : for(int i=0;i<4;++i)
570 6328 : rParaSprms.push_back(*pBegin++);
571 1582 : short nDxaLeft = SVBT16ToShort( pSprm );
572 : aLVL.nDxaLeft = (0 < nDxaLeft) ? (sal_uInt16)nDxaLeft
573 1582 : : (sal_uInt16)(-nDxaLeft);
574 : }
575 :
576 : // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
577 1586 : if (
578 1621 : (0 != (pSprm = GrpprlHasSprm(0x8411,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) ||
579 35 : (0 != (pSprm = GrpprlHasSprm(0x8460,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
580 : )
581 : {
582 1582 : sal_uInt8 *pBegin = pSprm-2;
583 7910 : for(int i=0;i<4;++i)
584 6328 : rParaSprms.push_back(*pBegin++);
585 1582 : aLVL.nDxaLeft1 = SVBT16ToShort( pSprm );
586 : }
587 :
588 : // #i86652# - read tab setting
589 1586 : if(0 != (pSprm = GrpprlHasSprm(0xC615,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
590 : {
591 1582 : bool bDone = false;
592 1582 : if (*(pSprm-1) == 5)
593 : {
594 1582 : if (*pSprm++ == 0) //nDel
595 : {
596 1582 : if (*pSprm++ == 1) //nIns
597 : {
598 1582 : nTabPos = SVBT16ToShort(pSprm);
599 1582 : pSprm+=2;
600 1582 : if (*pSprm == 6) //type
601 : {
602 1582 : bDone = true;
603 : }
604 : }
605 : }
606 : }
607 : OSL_ENSURE(bDone, "tab setting in numbering is "
608 : "of unexpected configuration");
609 : (void)bDone;
610 : }
611 1586 : if ( rNumFmt.GetPositionAndSpaceMode() ==
612 : SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
613 : {
614 : // If there is a tab setting with a larger value, then use that.
615 : // Ideally we would allow tabs to be used in numbering fields and set
616 : // this on the containing paragraph which would make it actually work
617 : // most of the time.
618 0 : if ( nTabPos != 0 )
619 : {
620 0 : const sal_uInt16 nDesired = aLVL.nDxaLeft + aLVL.nDxaLeft1;
621 :
622 0 : bool bDoAdjust = false;
623 0 : if ( nDesired < aLVL.nDxaLeft )
624 : {
625 0 : if ( nDesired < nTabPos && nTabPos < aLVL.nDxaLeft )
626 : {
627 0 : bDoAdjust = true;
628 : }
629 : }
630 : else
631 : {
632 0 : if ( aLVL.nDxaLeft < nTabPos && nTabPos < nDesired )
633 : {
634 0 : bDoAdjust = true;
635 : }
636 : }
637 :
638 0 : if (bDoAdjust)
639 : {
640 : aLVL.nDxaLeft = (0 < nTabPos)
641 : ? (sal_uInt16)nTabPos
642 0 : : (sal_uInt16)(-nTabPos);
643 :
644 0 : aLVL.nDxaLeft1 = nDesired - aLVL.nDxaLeft;
645 : }
646 : }
647 : }
648 : }
649 : //
650 : // 3. ggfs. CHPx einlesen und
651 : //
652 2017 : sal_uInt16 nWitchPicIsBullet = USHRT_MAX;
653 2017 : bool bIsPicBullet = false;
654 :
655 2017 : if( aLVL.nLenGrpprlChpx )
656 : {
657 : sal_uInt8 aGrpprlChpx[ 255 ];
658 1534 : memset(&aGrpprlChpx, 0, sizeof( aGrpprlChpx ));
659 1534 : if(aLVL.nLenGrpprlChpx != rSt.Read(&aGrpprlChpx, aLVL.nLenGrpprlChpx))
660 0 : return false;
661 :
662 : //For i120928,parse the graphic info of bullets
663 1534 : sal_uInt8 *pSprmWhichPis = GrpprlHasSprm(0x6887,aGrpprlChpx[0],aLVL.nLenGrpprlChpx);
664 1534 : sal_uInt8 *pSprmIsPicBullet = GrpprlHasSprm(0x4888,aGrpprlChpx[0],aLVL.nLenGrpprlChpx);
665 1534 : if (pSprmWhichPis)
666 : {
667 92 : nWitchPicIsBullet = *pSprmWhichPis;
668 : }
669 1534 : if (pSprmIsPicBullet)
670 : {
671 92 : bIsPicBullet = (*pSprmIsPicBullet) & 0x0001;
672 : }
673 :
674 : // neues ItemSet fuer die Zeichenattribute anlegen
675 1534 : rpItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN,
676 1534 : RES_CHRATR_END - 1 );
677 :
678 : // Reader-ItemSet-Pointer darauf zeigen lassen
679 1534 : rReader.SetAktItemSet( rpItemSet );
680 : // Reader-Style auf den Style dieses Levels setzen
681 1534 : sal_uInt16 nOldColl = rReader.GetNAktColl();
682 1534 : sal_uInt16 nNewColl = nLevelStyle;
683 1534 : if (ww::stiNil == nNewColl)
684 1496 : nNewColl = 0;
685 1534 : rReader.SetNAktColl( nNewColl );
686 :
687 : // Nun den GrpprlChpx einfach durchnudeln: die Read_xy() Methoden
688 : // in WW8PAR6.CXX rufen ganz normal ihr NewAttr() oder GetFmtAttr()
689 : // und diese merken am besetzten Reader-ItemSet-Pointer, dass dieser
690 : // spezielle ItemSet relevant ist - und nicht ein Stack oder Style!
691 1534 : sal_uInt16 nOldFlags1 = rReader.GetToggleAttrFlags();
692 1534 : sal_uInt16 nOldFlags2 = rReader.GetToggleBiDiAttrFlags();
693 :
694 : WW8SprmIter aSprmIter(&aGrpprlChpx[0], aLVL.nLenGrpprlChpx,
695 1534 : maSprmParser);
696 3742 : while (const sal_uInt8* pSprm = aSprmIter.GetSprms())
697 : {
698 2208 : rReader.ImportSprm(pSprm);
699 2208 : aSprmIter.advance();
700 : }
701 :
702 : // Reader-ItemSet-Pointer und Reader-Style zuruecksetzen
703 1534 : rReader.SetAktItemSet( 0 );
704 1534 : rReader.SetNAktColl( nOldColl );
705 1534 : rReader.SetToggleAttrFlags(nOldFlags1);
706 3742 : rReader.SetToggleBiDiAttrFlags(nOldFlags2);
707 : }
708 : //
709 : // 4. den Nummerierungsstring einlesen: ergibt Prefix und Postfix
710 : //
711 4034 : String sNumString(read_uInt16_PascalString(rSt));
712 :
713 : //
714 : // 5. gelesene Werte in Writer Syntax umwandeln
715 : //
716 2017 : if( 0 <= aLVL.nStartAt )
717 2017 : nStartNo = (sal_uInt16)aLVL.nStartAt;
718 :
719 2017 : switch( aLVL.nNFC )
720 : {
721 : case 0:
722 1715 : eType = SVX_NUM_ARABIC;
723 1715 : break;
724 : case 1:
725 0 : eType = SVX_NUM_ROMAN_UPPER;
726 0 : break;
727 : case 2:
728 28 : eType = SVX_NUM_ROMAN_LOWER;
729 28 : break;
730 : case 3:
731 0 : eType = SVX_NUM_CHARS_UPPER_LETTER_N;
732 0 : break;
733 : case 4:
734 27 : eType = SVX_NUM_CHARS_LOWER_LETTER_N;
735 27 : break;
736 : case 5:
737 : // eigentlich: ORDINAL
738 0 : eType = SVX_NUM_ARABIC;
739 0 : break;
740 : case 23:
741 : case 25:
742 219 : eType = SVX_NUM_CHAR_SPECIAL;
743 : //For i120928,type info
744 219 : if (bIsPicBullet)
745 : {
746 0 : eType = SVX_NUM_BITMAP;
747 : }
748 :
749 219 : break;
750 : case 255:
751 27 : eType = SVX_NUM_NUMBER_NONE;
752 27 : break;
753 : default:
754 : // take default
755 1 : eType = SVX_NUM_ARABIC;
756 1 : break;
757 : }
758 :
759 : //If a number level is not going to be used, then record this fact
760 2017 : if (SVX_NUM_NUMBER_NONE == eType)
761 27 : rNotReallyThere[nLevel] = true;
762 :
763 : /*
764 : If a number level was not used (i.e. is in NotReallyThere), and that
765 : number level appears at one of the positions in the display string of the
766 : list, then it effectively is not there at all. So remove that level entry
767 : from a copy of the aOfsNumsXCH.
768 : */
769 2017 : std::vector<sal_uInt8> aOfsNumsXCH;
770 : typedef std::vector<sal_uInt8>::iterator myIter;
771 2017 : aOfsNumsXCH.reserve(nMaxLevel);
772 :
773 20170 : for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
774 18153 : aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]);
775 :
776 12026 : for(nLevelB = 0; nLevelB <= nLevel; ++nLevelB)
777 : {
778 10009 : sal_uInt8 nPos = aOfsNumsXCH[nLevelB];
779 10009 : if (nPos && nPos < sNumString.Len() && sNumString.GetChar(nPos-1) < nMaxLevel)
780 : {
781 5101 : if (rNotReallyThere[nLevelB])
782 0 : aOfsNumsXCH[nLevelB] = 0;
783 : }
784 : }
785 2017 : myIter aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0);
786 2017 : myIter aEnd = aOfsNumsXCH.end();
787 : // #i60633# - suppress access on <aOfsNumsXCH.end()>
788 2017 : if ( aIter != aEnd )
789 : {
790 : // Somehow the first removed vector element, at which <aIter>
791 : // points to, isn't reset to zero.
792 : // Investigation is needed to clarify why. It seems that only
793 : // special arrays are handled correctly by this code.
794 1878 : ++aIter;
795 13678 : while (aIter != aEnd)
796 : {
797 9922 : (*aIter) = 0;
798 9922 : ++aIter;
799 : }
800 : }
801 :
802 2017 : sal_uInt8 nUpperLevel = 0; // akt. Anzeigetiefe fuer den Writer
803 20170 : for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
804 : {
805 18153 : if (!nUpperLevel && !aOfsNumsXCH[nLevelB])
806 2554 : nUpperLevel = nLevelB;
807 : }
808 :
809 : // falls kein NULL als Terminierungs-Char kam,
810 : // ist die Liste voller Indices, d.h. alle Plaetze sind besetzt,
811 : // also sind alle Level anzuzeigen
812 2017 : if (!nUpperLevel)
813 139 : nUpperLevel = nMaxLevel;
814 :
815 2017 : if (SVX_NUM_CHAR_SPECIAL == eType)
816 : {
817 219 : cBullet = sNumString.Len() ? sNumString.GetChar(0) : 0x2190;
818 :
819 219 : if (!cBullet) // unsave control code?
820 0 : cBullet = 0x2190;
821 : }
822 1798 : else if (SVX_NUM_BITMAP == eType) //For i120928,position index info of graphic
823 : {
824 0 : cGrfBulletCP = nWitchPicIsBullet; // This is a bullet picture ID
825 : }
826 : else
827 : {
828 : /*
829 : #i173#
830 : Our aOfsNumsXCH seems generally to be an array that contains the
831 : offset into sNumString of locations where the numbers should be
832 : filled in, so if the first "fill in a number" slot is greater than
833 : 1 there is a "prefix" before the number
834 : */
835 : //First number appears at
836 1798 : sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0];
837 : xub_StrLen nFirstNoIndex =
838 1798 : nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : STRING_LEN;
839 1798 : lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex);
840 :
841 : //Next number appears at
842 1798 : if (nUpperLevel)
843 : {
844 1798 : sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1];
845 : xub_StrLen nNextNoIndex =
846 1798 : nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex -1 : STRING_LEN;
847 1798 : if (nNextNoIndex != STRING_LEN)
848 1341 : ++nNextNoIndex;
849 1798 : if (sNumString.Len() > nNextNoIndex)
850 101 : lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex);
851 : }
852 :
853 : /*
854 : We use lcl_CopyGreaterEight because once if we have removed unused
855 : number indexes from the aOfsNumsXCH then placeholders remain in
856 : sNumString which must not be copied into the final numbering strings
857 : */
858 : }
859 :
860 2017 : switch( aLVL.nAlign )
861 : {
862 : case 0:
863 1990 : eAdj = SVX_ADJUST_LEFT;
864 1990 : break;
865 : case 1:
866 0 : eAdj = SVX_ADJUST_CENTER;
867 0 : break;
868 : case 2:
869 27 : eAdj = SVX_ADJUST_RIGHT;
870 27 : break;
871 : case 3:
872 : // Writer here cannot do block justification
873 0 : eAdj = SVX_ADJUST_LEFT;
874 0 : break;
875 : default:
876 : // undefied value
877 : OSL_ENSURE( !this, "Value of aLVL.nAlign is not supported" );
878 : // take default
879 0 : eAdj = SVX_ADJUST_LEFT;
880 0 : break;
881 : }
882 :
883 : // 6. entsprechendes NumFmt konfigurieren
884 2017 : if( bSetStartNo )
885 2017 : rNumFmt.SetStart( nStartNo );
886 2017 : rNumFmt.SetNumberingType( static_cast< sal_Int16 >(eType) );
887 2017 : rNumFmt.SetNumAdjust( eAdj );
888 :
889 2017 : if( SVX_NUM_CHAR_SPECIAL == eType )
890 : {
891 : // first character of the Prefix-Text is the Bullet
892 219 : rNumFmt.SetBulletChar(cBullet);
893 : // Don't forget: unten, nach dem Bauen eventueller Styles auch noch
894 : // SetBulletFont() rufen !!!
895 : }
896 : //For i120928,position index info
897 1798 : else if (SVX_NUM_BITMAP == eType)
898 : {
899 0 : rNumFmt.SetGrfBulletCP(cGrfBulletCP);
900 : }
901 : else
902 : {
903 : // reminder: Garnix ist default Prefix
904 1798 : if( sPrefix.Len() )
905 1 : rNumFmt.SetPrefix( sPrefix );
906 : // reminder: Point is default Postfix
907 1798 : rNumFmt.SetSuffix( sPostfix );
908 1798 : rNumFmt.SetIncludeUpperLevels( nUpperLevel );
909 : }
910 :
911 : // #i89181#
912 2017 : if ( rNumFmt.GetPositionAndSpaceMode() ==
913 : SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
914 : {
915 0 : if (eAdj == SVX_ADJUST_RIGHT)
916 : {
917 0 : rNumFmt.SetAbsLSpace(aLVL.nDxaLeft);
918 0 : rNumFmt.SetFirstLineOffset(-aLVL.nDxaLeft);
919 0 : rNumFmt.SetCharTextDistance(-aLVL.nDxaLeft1);
920 : }
921 : else
922 : {
923 0 : rNumFmt.SetAbsLSpace( aLVL.nDxaLeft );
924 0 : rNumFmt.SetFirstLineOffset(aLVL.nDxaLeft1);
925 : }
926 : }
927 : else
928 : {
929 2017 : rNumFmt.SetIndentAt( aLVL.nDxaLeft );
930 2017 : rNumFmt.SetFirstLineIndent(aLVL.nDxaLeft1);
931 2017 : if ( !aLVL.bV6 )
932 2017 : rNumFmt.SetListtabPos( nTabPos );
933 : else
934 0 : rNumFmt.SetListtabPos( aLVL.nV6Indent );
935 2017 : SvxNumberFormat::LabelFollowedBy eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
936 2017 : switch ( ixchFollow )
937 : {
938 : case 0:
939 : {
940 1989 : eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
941 : }
942 1989 : break;
943 : case 1:
944 : {
945 0 : eNumLabelFollowedBy = SvxNumberFormat::SPACE;
946 : }
947 0 : break;
948 : case 2:
949 : {
950 27 : eNumLabelFollowedBy = SvxNumberFormat::NOTHING;
951 : }
952 27 : break;
953 : }
954 2017 : rNumFmt.SetLabelFollowedBy( eNumLabelFollowedBy );
955 : }
956 :
957 4034 : return true;
958 : }
959 :
960 2025 : void WW8ListManager::AdjustLVL( sal_uInt8 nLevel, SwNumRule& rNumRule,
961 : WW8aISet& rListItemSet, WW8aCFmt& rCharFmt, bool& bNewCharFmtCreated,
962 : String sPrefix )
963 : {
964 2025 : bNewCharFmtCreated = false;
965 : SfxItemSet* pThisLevelItemSet;
966 : sal_uInt8 nIdenticalItemSetLevel;
967 : const SfxPoolItem* pItem;
968 :
969 2025 : SwNumFmt aNumFmt = rNumRule.Get( nLevel );
970 :
971 2025 : pThisLevelItemSet = rListItemSet[ nLevel ];
972 :
973 2025 : if( pThisLevelItemSet && pThisLevelItemSet->Count())
974 : {
975 233 : nIdenticalItemSetLevel = nMaxLevel;
976 233 : SfxItemIter aIter( *pThisLevelItemSet );
977 : SfxItemSet* pLowerLevelItemSet;
978 411 : for (sal_uInt8 nLowerLevel = 0; nLowerLevel < nLevel; ++nLowerLevel)
979 : {
980 325 : pLowerLevelItemSet = rListItemSet[ nLowerLevel ];
981 325 : if( pLowerLevelItemSet
982 325 : && (pLowerLevelItemSet->Count() == pThisLevelItemSet->Count()) )
983 : {
984 301 : nIdenticalItemSetLevel = nLowerLevel;
985 301 : sal_uInt16 nWhich = aIter.GetCurItem()->Which();
986 : while (true)
987 : {
988 448 : if( // ggfs. passenden pItem im pLowerLevelItemSet finden
989 : (SFX_ITEM_SET != pLowerLevelItemSet->GetItemState(
990 448 : nWhich, false, &pItem ) )
991 896 : || // virtuellen "!=" Operator anwenden
992 448 : (*pItem != *aIter.GetCurItem() ) )
993 : // falls kein Item mit gleicher nWhich gefunden oder Werte
994 : // der Items ungleich, Ungleichheit merken und abbrechen!
995 : {
996 154 : nIdenticalItemSetLevel = nMaxLevel;
997 154 : break;
998 : }
999 294 : if( aIter.IsAtEnd() )
1000 147 : break;
1001 147 : nWhich = aIter.NextItem()->Which();
1002 : }
1003 :
1004 301 : if( nIdenticalItemSetLevel != nMaxLevel )
1005 294 : break;
1006 : }
1007 : }
1008 :
1009 : SwCharFmt* pFmt;
1010 233 : if (nMaxLevel == nIdenticalItemSetLevel)
1011 : {
1012 : // Style definieren
1013 86 : String aName( sPrefix.Len() ? sPrefix : rNumRule.GetName() );
1014 86 : (aName += 'z') += OUString::number( nLevel );
1015 :
1016 : // const Wegcasten
1017 86 : pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt());
1018 86 : bNewCharFmtCreated = true;
1019 : // Attribute reinsetzen
1020 86 : pFmt->SetFmtAttr( *pThisLevelItemSet );
1021 : }
1022 : else
1023 : {
1024 : // passenden Style hier anhaengen
1025 147 : pFmt = rCharFmt[ nIdenticalItemSetLevel ];
1026 : }
1027 :
1028 : // merken
1029 233 : rCharFmt[ nLevel ] = pFmt;
1030 :
1031 : //
1032 : // Style an das NumFormat haengen
1033 : //
1034 233 : aNumFmt.SetCharFmt( pFmt );
1035 : }
1036 : //Ensure the default char fmt is initialized for any level of num ruler if no customized attr
1037 : else
1038 : {
1039 1792 : SwCharFmt* pFmt = aNumFmt.GetCharFmt();
1040 1792 : if ( !pFmt)
1041 : {
1042 1784 : OUString aName = ( sPrefix.Len() ? sPrefix : rNumRule.GetName() );
1043 1784 : aName += "z" + OUString::number( nLevel );
1044 :
1045 1784 : pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt());
1046 1784 : bNewCharFmtCreated = true;
1047 1784 : rCharFmt[ nLevel ] = pFmt;
1048 1784 : aNumFmt.SetCharFmt( pFmt );
1049 : }
1050 : }
1051 : //
1052 : // ggfs. Bullet Font an das NumFormat haengen
1053 : //
1054 2025 : if( SVX_NUM_CHAR_SPECIAL == aNumFmt.GetNumberingType() )
1055 : {
1056 227 : SwCharFmt* pFmt = aNumFmt.GetCharFmt();
1057 227 : Font aFont;
1058 227 : if( !pFmt )
1059 : {
1060 0 : aFont = numfunc::GetDefBulletFont();
1061 : }
1062 : else
1063 : {
1064 227 : const SvxFontItem& rFontItem = pFmt->GetFont();
1065 227 : aFont.SetFamily( rFontItem.GetFamily() );
1066 227 : aFont.SetName( rFontItem.GetFamilyName() );
1067 227 : aFont.SetStyleName( rFontItem.GetStyleName() );
1068 227 : aFont.SetPitch( rFontItem.GetPitch() );
1069 227 : aFont.SetCharSet( rFontItem.GetCharSet() );
1070 : }
1071 227 : aNumFmt.SetBulletFont( &aFont );
1072 : }
1073 : //
1074 : // und wieder rein in die NumRule
1075 : //
1076 2025 : rNumRule.Set(nLevel, aNumFmt);
1077 2025 : }
1078 :
1079 241 : SwNumRule* WW8ListManager::CreateNextRule(bool bSimple)
1080 : {
1081 : // wird erstmal zur Bildung des Style Namens genommen
1082 241 : String sPrefix(OUString("WW8Num"));
1083 241 : sPrefix += OUString::number(nUniqueList++);
1084 : // #i86652#
1085 : sal_uInt16 nRul =
1086 : rDoc.MakeNumRule( rDoc.GetUniqueNumRuleName(&sPrefix), 0, false,
1087 241 : SvxNumberFormat::LABEL_ALIGNMENT );
1088 241 : SwNumRule* pMyNumRule = rDoc.GetNumRuleTbl()[nRul];
1089 241 : pMyNumRule->SetAutoRule(false);
1090 241 : pMyNumRule->SetContinusNum(bSimple);
1091 241 : return pMyNumRule;
1092 : }
1093 :
1094 0 : SwNumRule* WW8ListManager::GetNumRule(size_t i)
1095 : {
1096 0 : if (i < maLSTInfos.size())
1097 0 : return maLSTInfos[i]->pNumRule;
1098 : else
1099 0 : return 0;
1100 : }
1101 :
1102 : // oeffentliche Methoden /////////////////////////////////////////////////////
1103 : //
1104 50 : WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
1105 50 : : maSprmParser(rReader_.GetFib().GetFIBVersion()), rReader(rReader_),
1106 100 : rDoc(rReader.GetDoc()), rFib(rReader.GetFib()), rSt(rSt_),
1107 150 : nUniqueList(1)
1108 : {
1109 : // LST und LFO gibts erst ab WW8
1110 50 : if( ( 8 > rFib.nVersion )
1111 50 : || ( rFib.fcPlcfLst == rFib.fcPlfLfo )
1112 38 : || ( rFib.lcbPlcfLst < 2 )
1113 50 : || ( rFib.lcbPlfLfo < 2) ) return; // offensichtlich keine Listen da
1114 :
1115 : // Arrays anlegen
1116 16 : bool bLVLOk = true;
1117 :
1118 16 : nLastLFOPosition = USHRT_MAX;
1119 16 : long nOriginalPos = rSt.Tell();
1120 : //
1121 : // 1. PLCF LST auslesen und die Listen Vorlagen im Writer anlegen
1122 : //
1123 16 : bool bOk = checkSeek(rSt, rFib.fcPlcfLst);
1124 :
1125 16 : if (!bOk)
1126 0 : return;
1127 :
1128 16 : sal_uInt32 nRemainingPlcfLst = rFib.lcbPlcfLst;
1129 :
1130 16 : sal_uInt16 nListCount(0);
1131 16 : rSt >> nListCount;
1132 16 : nRemainingPlcfLst -= 2;
1133 16 : bOk = nListCount > 0;
1134 :
1135 16 : if (!bOk)
1136 0 : return;
1137 :
1138 : //
1139 : // 1.1 alle LST einlesen
1140 : //
1141 257 : for (sal_uInt16 nList=0; nList < nListCount; ++nList)
1142 : {
1143 241 : if (nRemainingPlcfLst < cbLSTF)
1144 0 : break;
1145 :
1146 : WW8LST aLST;
1147 241 : memset(&aLST, 0, sizeof( aLST ));
1148 :
1149 : //
1150 : // 1.1.1 Daten einlesen
1151 : //
1152 241 : rSt >> aLST.nIdLst;
1153 241 : rSt >> aLST.nTplC;
1154 2410 : for (sal_uInt16 nLevel = 0; nLevel < nMaxLevel; ++nLevel)
1155 2169 : rSt >> aLST.aIdSty[ nLevel ];
1156 :
1157 241 : sal_uInt8 aBits1(0);
1158 241 : rSt >> aBits1;
1159 :
1160 241 : rSt.SeekRel( 1 );
1161 :
1162 241 : if( aBits1 & 0x01 )
1163 19 : aLST.bSimpleList = true;
1164 241 : if( aBits1 & 0x02 )
1165 1 : aLST.bRestartHdn = true;
1166 :
1167 : // 1.1.2 new NumRule inserted in Doc and WW8LSTInfo marked
1168 :
1169 : /*
1170 : #i1869#
1171 : In word 2000 microsoft got rid of creating new "simple lists" with
1172 : only 1 level, all new lists are created with 9 levels. To hack it
1173 : so that the list types formerly known as simple lists still have
1174 : their own tab page to themselves one of the reserved bits is used
1175 : to show that a given list is to be in the simple list tabpage.
1176 : This has now nothing to do with the actual number of list level a
1177 : list has, only how many will be shown in the user interface.
1178 :
1179 : i.e. create a simple list in 2000 and open it in 97 and 97 will
1180 : claim (correctly) that it is an outline list. We can set our
1181 : continous flag in these lists to store this information.
1182 : */
1183 : SwNumRule* pMyNumRule = CreateNextRule(
1184 241 : aLST.bSimpleList || (aBits1 & 0x10));
1185 :
1186 241 : WW8LSTInfo* pLSTInfo = new WW8LSTInfo(pMyNumRule, aLST);
1187 241 : maLSTInfos.push_back(pLSTInfo);
1188 :
1189 241 : nRemainingPlcfLst -= cbLSTF;
1190 : }
1191 :
1192 : //
1193 : // 1.2 alle LVL aller aLST einlesen
1194 : //
1195 16 : sal_uInt16 nLSTInfos = static_cast< sal_uInt16 >(maLSTInfos.size());
1196 257 : for (sal_uInt16 nList = 0; nList < nLSTInfos; ++nList)
1197 : {
1198 241 : WW8LSTInfo* pListInfo = maLSTInfos[nList];
1199 241 : if( !pListInfo || !pListInfo->pNumRule ) break;
1200 241 : SwNumRule& rMyNumRule = *pListInfo->pNumRule;
1201 : //
1202 : // 1.2.1 betreffende(n) LVL(s) fuer diese aLST einlesen
1203 : //
1204 241 : sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel);
1205 241 : std::deque<bool> aNotReallyThere;
1206 241 : aNotReallyThere.resize(nMaxLevel);
1207 241 : pListInfo->maParaSprms.resize(nMaxLevel);
1208 2258 : for (sal_uInt8 nLevel = 0; nLevel < nLvlCount; ++nLevel)
1209 : {
1210 2017 : SwNumFmt aNumFmt( rMyNumRule.Get( nLevel ) );
1211 : // LVLF einlesen
1212 2017 : bLVLOk = ReadLVL( aNumFmt, pListInfo->aItemSet[nLevel],
1213 2017 : pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel,
1214 6051 : pListInfo->maParaSprms[nLevel]);
1215 2017 : if( !bLVLOk )
1216 0 : break;
1217 : // und in die rMyNumRule aufnehmen
1218 2017 : rMyNumRule.Set( nLevel, aNumFmt );
1219 2017 : }
1220 241 : if( !bLVLOk )
1221 0 : break;
1222 : //
1223 : // 1.2.2 die ItemPools mit den CHPx Einstellungen der verschiedenen
1224 : // Level miteinander vergleichen und ggfs. Style(s) erzeugen
1225 : //
1226 2258 : for (sal_uInt8 nLevel = 0; nLevel < nLvlCount; ++nLevel)
1227 : {
1228 : bool bDummy;
1229 : AdjustLVL( nLevel, rMyNumRule, pListInfo->aItemSet,
1230 2017 : pListInfo->aCharFmt, bDummy );
1231 : }
1232 : //
1233 : // 1.2.3 ItemPools leeren und loeschen
1234 : //
1235 2258 : for (sal_uInt8 nLevel = 0; nLevel < nLvlCount; ++nLevel)
1236 2017 : delete pListInfo->aItemSet[ nLevel ];
1237 241 : }
1238 :
1239 : //
1240 : // 2. PLF LFO auslesen und speichern
1241 : //
1242 16 : bOk = checkSeek(rSt, rFib.fcPlfLfo);
1243 :
1244 16 : if (!bOk)
1245 0 : return;
1246 :
1247 16 : sal_Int32 nLfoCount(0);
1248 16 : rSt >> nLfoCount;
1249 16 : bOk = nLfoCount > 0;
1250 :
1251 16 : if (!bOk)
1252 0 : return;
1253 :
1254 : //
1255 : // 2.1 alle LFO einlesen
1256 : //
1257 518 : for (sal_uInt16 nLfo = 0; nLfo < nLfoCount; ++nLfo)
1258 : {
1259 244 : bOk = false;
1260 :
1261 244 : if (rSt.IsEof())
1262 1 : break;
1263 :
1264 : WW8LFO aLFO;
1265 244 : memset(&aLFO, 0, sizeof( aLFO ));
1266 :
1267 244 : rSt >> aLFO.nIdLst;
1268 244 : rSt.SeekRel( 8 );
1269 244 : rSt >> aLFO.nLfoLvl;
1270 244 : rSt.SeekRel( 3 );
1271 : // soviele Overrides existieren
1272 244 : if ((nMaxLevel < aLFO.nLfoLvl) || rSt.GetError())
1273 1 : break;
1274 :
1275 : // die Parent NumRule der entsprechenden Liste ermitteln
1276 243 : WW8LSTInfo* pParentListInfo = GetLSTByListId(aLFO.nIdLst);
1277 243 : if (pParentListInfo)
1278 : {
1279 : // hier, im ersten Schritt, erst mal diese NumRule festhalten
1280 243 : aLFO.pNumRule = pParentListInfo->pNumRule;
1281 :
1282 : // hat die Liste mehrere Level ?
1283 243 : aLFO.bSimpleList = pParentListInfo->bSimpleList;
1284 : }
1285 : // und rein ins Merk-Array mit dem Teil
1286 243 : WW8LFOInfo* pLFOInfo = new WW8LFOInfo(aLFO);
1287 243 : if (pParentListInfo)
1288 : {
1289 : //Copy the basic paragraph properties for each level from the
1290 : //original list into the list format override levels.
1291 243 : int nMaxSize = pParentListInfo->maParaSprms.size();
1292 243 : pLFOInfo->maParaSprms.resize(nMaxSize);
1293 2430 : for (int i = 0; i < nMaxSize; ++i)
1294 2187 : pLFOInfo->maParaSprms[i] = pParentListInfo->maParaSprms[i];
1295 : }
1296 243 : pLFOInfos.push_back(pLFOInfo);
1297 243 : bOk = true;
1298 : }
1299 :
1300 16 : if( bOk )
1301 : {
1302 : //
1303 : // 2.2 fuer alle LFO die zugehoerigen LFOLVL einlesen
1304 : //
1305 15 : size_t nLFOInfos = pLFOInfos.size();
1306 258 : for (size_t nLfo = 0; nLfo < nLFOInfos; ++nLfo)
1307 : {
1308 243 : bOk = false;
1309 243 : WW8LFOInfo& rLFOInfo = pLFOInfos[nLfo];
1310 : // stehen hierfuer ueberhaupt LFOLVL an ?
1311 243 : if( rLFOInfo.bOverride )
1312 : {
1313 1 : WW8LSTInfo* pParentListInfo = GetLSTByListId(rLFOInfo.nIdLst);
1314 1 : if (!pParentListInfo)
1315 0 : break;
1316 : //
1317 : // 2.2.1 eine neue NumRule fuer diese Liste anlegen
1318 : //
1319 1 : SwNumRule* pParentNumRule = rLFOInfo.pNumRule;
1320 : OSL_ENSURE(pParentNumRule, "ww: Impossible lists, please report");
1321 1 : if( !pParentNumRule )
1322 0 : break;
1323 : // Nauemsprefix aufbauen: fuer NumRule-Name (eventuell)
1324 : // und (falls vorhanden) fuer Style-Name (dann auf jeden Fall)
1325 1 : String sPrefix(OUString("WW8NumSt"));
1326 1 : sPrefix += OUString::number( nLfo + 1 );
1327 : // jetzt dem pNumRule seinen RICHTIGEN Wert zuweisen !!!
1328 : // (bis dahin war hier die Parent NumRule vermerkt )
1329 : //
1330 : // Dazu erst mal nachsehen, ob ein Style diesen LFO
1331 : // referenziert:
1332 1 : if( USHRT_MAX > rReader.StyleUsingLFO( nLfo ) )
1333 : {
1334 : sal_uInt16 nRul = rDoc.MakeNumRule(
1335 0 : rDoc.GetUniqueNumRuleName( &sPrefix ), pParentNumRule);
1336 0 : rLFOInfo.pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
1337 0 : rLFOInfo.pNumRule->SetAutoRule(false);
1338 : }
1339 : else
1340 : {
1341 : sal_uInt16 nRul = rDoc.MakeNumRule(
1342 1 : rDoc.GetUniqueNumRuleName(), pParentNumRule);
1343 1 : rLFOInfo.pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
1344 1 : rLFOInfo.pNumRule->SetAutoRule(true); // = default
1345 : }
1346 : //
1347 : // 2.2.2 alle LFOLVL (und ggfs. LVL) fuer die neue NumRule
1348 : // einlesen
1349 : //
1350 : WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
1351 : WW8aCFmt aCharFmt; // Zeichen Style Pointer
1352 1 : memset(&aItemSet, 0, sizeof( aItemSet ));
1353 1 : memset(&aCharFmt, 0, sizeof( aCharFmt ));
1354 :
1355 : //2.2.2.0 skip inter-group of override header ?
1356 : //See #i25438# for why I moved this here, compare
1357 : //that original bugdoc's binary to what it looks like
1358 : //when resaved with word, i.e. there is always a
1359 : //4 byte header, there might be more than one if
1360 : //that header was 0xFFFFFFFF, e.g. #114412# ?
1361 : sal_uInt32 nTest;
1362 1 : rSt >> nTest;
1363 12 : do
1364 : {
1365 12 : nTest = 0;
1366 12 : rSt >> nTest;
1367 : }
1368 12 : while (nTest == 0xFFFFFFFF);
1369 1 : rSt.SeekRel(-4);
1370 :
1371 2 : std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel);
1372 18 : for (sal_uInt8 nLevel = 0; nLevel < rLFOInfo.nLfoLvl; ++nLevel)
1373 : {
1374 8 : WW8LFOLVL aLFOLVL;
1375 8 : bLVLOk = false;
1376 :
1377 : //
1378 : // 2.2.2.1 den LFOLVL einlesen
1379 : //
1380 8 : rSt >> aLFOLVL.nStartAt;
1381 8 : sal_uInt8 aBits1(0);
1382 8 : rSt >> aBits1;
1383 8 : rSt.SeekRel( 3 );
1384 8 : if (rSt.GetError())
1385 0 : break;
1386 :
1387 : // beachte: Die Witzbolde bei MS quetschen die
1388 : // Override-Level-Nummer in vier Bits hinein, damit sie
1389 : // wieder einen Grund haben, ihr Dateiformat zu aendern,
1390 : // falls ihnen einfaellt, dass sie eigentlich doch gerne
1391 : // bis zu 16 Listen-Level haetten. Wir tun das *nicht*
1392 : // (siehe Kommentar oben bei "struct
1393 : // WW8LFOInfo")
1394 8 : aLFOLVL.nLevel = aBits1 & 0x0F;
1395 13 : if( (0xFF > aBits1) &&
1396 5 : (nMaxLevel > aLFOLVL.nLevel) )
1397 : {
1398 5 : if (aBits1 & 0x10)
1399 0 : aLFOLVL.bStartAt = true;
1400 : else
1401 5 : aLFOLVL.bStartAt = false;
1402 : //
1403 : // 2.2.2.2 eventuell auch den zugehoerigen LVL einlesen
1404 : //
1405 : SwNumFmt aNumFmt(
1406 5 : rLFOInfo.pNumRule->Get(aLFOLVL.nLevel));
1407 5 : if (aBits1 & 0x20)
1408 : {
1409 0 : aLFOLVL.bFormat = true;
1410 : // falls bStartup true, hier den Startup-Level
1411 : // durch den im LVL vermerkten ersetzen LVLF
1412 : // einlesen
1413 0 : bLVLOk = ReadLVL(aNumFmt, aItemSet[nLevel],
1414 0 : pParentListInfo->aIdSty[nLevel],
1415 : aLFOLVL.bStartAt, aNotReallyThere, nLevel,
1416 0 : rLFOInfo.maParaSprms[nLevel]);
1417 :
1418 0 : if (!bLVLOk)
1419 0 : break;
1420 : }
1421 5 : else if (aLFOLVL.bStartAt)
1422 : {
1423 : aNumFmt.SetStart(
1424 0 : writer_cast<sal_uInt16>(aLFOLVL.nStartAt));
1425 : }
1426 : //
1427 : // 2.2.2.3 das NumFmt in die NumRule aufnehmen
1428 : //
1429 5 : rLFOInfo.pNumRule->Set(aLFOLVL.nLevel, aNumFmt);
1430 : }
1431 8 : bLVLOk = true;
1432 :
1433 8 : if (nMaxLevel > aLFOLVL.nLevel)
1434 5 : rLFOInfo.maOverrides[aLFOLVL.nLevel] = aLFOLVL;
1435 : }
1436 1 : if( !bLVLOk )
1437 0 : break;
1438 : //
1439 : // 2.2.3 die LVL der neuen NumRule anpassen
1440 : //
1441 1 : sal_uInt16 aFlagsNewCharFmt = 0;
1442 1 : bool bNewCharFmtCreated = false;
1443 9 : for (sal_uInt8 nLevel = 0; nLevel < rLFOInfo.nLfoLvl; ++nLevel)
1444 : {
1445 : AdjustLVL( nLevel, *rLFOInfo.pNumRule, aItemSet, aCharFmt,
1446 8 : bNewCharFmtCreated, sPrefix );
1447 8 : if( bNewCharFmtCreated )
1448 0 : aFlagsNewCharFmt += (1 << nLevel);
1449 : }
1450 : //
1451 : // 2.2.4 ItemPools leeren und loeschen
1452 : //
1453 9 : for (sal_uInt8 nLevel = 0; nLevel < rLFOInfo.nLfoLvl; ++nLevel)
1454 8 : delete aItemSet[ nLevel ];
1455 2 : bOk = true;
1456 : }
1457 : }
1458 : }
1459 : // und schon sind wir fertig!
1460 16 : rSt.Seek( nOriginalPos );
1461 : }
1462 :
1463 100 : WW8ListManager::~WW8ListManager()
1464 : {
1465 : /*
1466 : named lists remain in document
1467 : unused automatic lists are removed from document (DelNumRule)
1468 : */
1469 873 : for(std::vector<WW8LSTInfo *>::iterator aIter = maLSTInfos.begin();
1470 582 : aIter != maLSTInfos.end(); ++aIter)
1471 : {
1472 431 : if ((*aIter)->pNumRule && !(*aIter)->bUsedInDoc &&
1473 190 : (*aIter)->pNumRule->IsAutoRule())
1474 : {
1475 0 : rDoc.DelNumRule((*aIter)->pNumRule->GetName());
1476 : }
1477 241 : delete *aIter;
1478 : }
1479 50 : boost::ptr_vector<WW8LFOInfo >::reverse_iterator aIter;
1480 879 : for (aIter = pLFOInfos.rbegin() ;
1481 586 : aIter < pLFOInfos.rend();
1482 : ++aIter )
1483 : {
1484 486 : if (aIter->bOverride
1485 1 : && aIter->pNumRule
1486 1 : && !aIter->bUsedInDoc
1487 244 : && aIter->pNumRule->IsAutoRule())
1488 : {
1489 1 : rDoc.DelNumRule( aIter->pNumRule->GetName() );
1490 : }
1491 : }
1492 50 : }
1493 :
1494 0 : bool IsEqualFormatting(const SwNumRule &rOne, const SwNumRule &rTwo)
1495 : {
1496 : bool bRet =
1497 : (
1498 0 : rOne.GetRuleType() == rTwo.GetRuleType() &&
1499 0 : rOne.IsContinusNum() == rTwo.IsContinusNum() &&
1500 0 : rOne.IsAbsSpaces() == rTwo.IsAbsSpaces() &&
1501 0 : rOne.GetPoolFmtId() == rTwo.GetPoolFmtId() &&
1502 0 : rOne.GetPoolHelpId() == rTwo.GetPoolHelpId() &&
1503 0 : rTwo.GetPoolHlpFileId() == rTwo.GetPoolHlpFileId()
1504 0 : );
1505 :
1506 0 : if (bRet)
1507 : {
1508 0 : for (sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1509 : {
1510 : //The SvxNumberFormat compare, not the SwNumFmt compare
1511 0 : const SvxNumberFormat &rO = rOne.Get(n);
1512 0 : const SvxNumberFormat &rT = rTwo.Get(n);
1513 0 : if (!(rO == rT))
1514 : {
1515 0 : bRet = false;
1516 0 : break;
1517 : }
1518 : }
1519 : }
1520 0 : return bRet;
1521 : }
1522 :
1523 274 : SwNumRule* WW8ListManager::GetNumRuleForActivation(sal_uInt16 nLFOPosition,
1524 : const sal_uInt8 nLevel, std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode)
1525 : {
1526 274 : if (pLFOInfos.size() <= nLFOPosition)
1527 8 : return 0;
1528 :
1529 266 : WW8LFOInfo& rLFOInfo = pLFOInfos[nLFOPosition];
1530 :
1531 266 : bool bFirstUse = !rLFOInfo.bUsedInDoc;
1532 266 : rLFOInfo.bUsedInDoc = true;
1533 :
1534 266 : if( !rLFOInfo.pNumRule )
1535 0 : return 0;
1536 :
1537 : // #i25545#
1538 : // #i100132# - a number format does not have to exist on given list level
1539 266 : SwNumFmt pFmt(rLFOInfo.pNumRule->Get(nLevel));
1540 :
1541 266 : if (rReader.IsRightToLeft() && nLastLFOPosition != nLFOPosition) {
1542 0 : if ( pFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
1543 0 : pFmt.SetNumAdjust(SVX_ADJUST_LEFT);
1544 0 : else if ( pFmt.GetNumAdjust() == SVX_ADJUST_LEFT)
1545 0 : pFmt.SetNumAdjust(SVX_ADJUST_RIGHT);
1546 0 : rLFOInfo.pNumRule->Set(nLevel, pFmt);
1547 : }
1548 266 : nLastLFOPosition = nLFOPosition;
1549 : /*
1550 : #i1869#
1551 : If this list has had its bits set in word 2000 to pretend that it is a
1552 : simple list from the point of view of the user, then it is almost
1553 : certainly a simple continous list, and we will try to keep it like that.
1554 : Otherwise when we save again it will be shown as the true outline list
1555 : that it is, confusing the user that just wanted what they thought was a
1556 : simple list. On the otherhand it is possible that some of the other levels
1557 : were used by the user, in which case we will not pretend anymore that it
1558 : is a simple list. Something that word 2000 does anyway, that 97 didn't, to
1559 : my bewilderment.
1560 : */
1561 266 : if (nLevel && rLFOInfo.pNumRule->IsContinusNum())
1562 0 : rLFOInfo.pNumRule->SetContinusNum(false);
1563 :
1564 266 : if( (!rLFOInfo.bOverride) && (!rLFOInfo.bLSTbUIDSet) )
1565 : {
1566 51 : WW8LSTInfo* pParentListInfo = GetLSTByListId( rLFOInfo.nIdLst );
1567 51 : if( pParentListInfo )
1568 51 : pParentListInfo->bUsedInDoc = true;
1569 51 : rLFOInfo.bLSTbUIDSet = true;
1570 : }
1571 :
1572 266 : if (rLFOInfo.maParaSprms.size() > nLevel)
1573 266 : rParaSprms = rLFOInfo.maParaSprms[nLevel];
1574 :
1575 266 : SwNumRule *pRet = rLFOInfo.pNumRule;
1576 :
1577 266 : bool bRestart(false);
1578 266 : sal_uInt16 nStart(0);
1579 266 : bool bNewstart(false);
1580 : /*
1581 : Note: If you fiddle with this then you have to make sure that #i18322#
1582 : #i13833#, #i20095# and #112466# continue to work
1583 :
1584 : Check if there were overrides for this level
1585 : */
1586 266 : if (rLFOInfo.bOverride && nLevel < rLFOInfo.nLfoLvl)
1587 : {
1588 0 : WW8LSTInfo* pParentListInfo = GetLSTByListId(rLFOInfo.nIdLst);
1589 : OSL_ENSURE(pParentListInfo, "ww: Impossible lists, please report");
1590 0 : if (pParentListInfo && pParentListInfo->pNumRule)
1591 : {
1592 0 : const WW8LFOLVL &rOverride = rLFOInfo.maOverrides[nLevel];
1593 : bool bNoChangeFromParent =
1594 0 : IsEqualFormatting(*pRet, *(pParentListInfo->pNumRule));
1595 :
1596 : //If so then I think word still uses the parent (maybe)
1597 0 : if (bNoChangeFromParent)
1598 : {
1599 0 : pRet = pParentListInfo->pNumRule;
1600 :
1601 : //did it not affect start at value ?
1602 0 : if (bFirstUse)
1603 : {
1604 0 : if (rOverride.bStartAt)
1605 : {
1606 : const SwNumFmt &rFmt =
1607 0 : pParentListInfo->pNumRule->Get(nLevel);
1608 0 : if (
1609 0 : rFmt.GetStart() ==
1610 0 : rLFOInfo.maOverrides[nLevel].nStartAt
1611 : )
1612 : {
1613 0 : bRestart = true;
1614 : }
1615 : else
1616 : {
1617 0 : bNewstart = true;
1618 : nStart = writer_cast<sal_uInt16>
1619 0 : (rLFOInfo.maOverrides[nLevel].nStartAt);
1620 : }
1621 : }
1622 : }
1623 :
1624 0 : pParentListInfo->bUsedInDoc = true;
1625 : }
1626 : }
1627 : }
1628 :
1629 266 : if (pNode)
1630 : {
1631 233 : pNode->SetAttrListLevel(nLevel);
1632 :
1633 233 : if (bRestart || bNewstart)
1634 0 : pNode->SetListRestart(true);
1635 233 : if (bNewstart)
1636 0 : pNode->SetAttrListRestartValue(nStart);
1637 : }
1638 266 : return pRet;
1639 : }
1640 :
1641 : //----------------------------------------------------------------------------
1642 : // SwWW8ImplReader: anhaengen einer Liste an einen Style oder Absatz
1643 : //----------------------------------------------------------------------------
1644 5204 : bool SwWW8ImplReader::SetTxtFmtCollAndListLevel(const SwPaM& rRg,
1645 : SwWW8StyInf& rStyleInfo)
1646 : {
1647 5204 : bool bRes = true;
1648 5204 : if( rStyleInfo.pFmt && rStyleInfo.bColl )
1649 : {
1650 5204 : bRes = rDoc.SetTxtFmtColl(rRg, (SwTxtFmtColl*)rStyleInfo.pFmt);
1651 5204 : SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode();
1652 : OSL_ENSURE( pTxtNode, "No Text-Node at PaM-Position" );
1653 : // make code robust
1654 5204 : if ( !pTxtNode )
1655 : {
1656 0 : return bRes;
1657 : }
1658 :
1659 5204 : SwNumRule * pNumRule = pTxtNode->GetNumRule(); // #i27610#
1660 :
1661 10334 : if( !IsInvalidOrToBeMergedTabCell() &&
1662 439 : ! (pNumRule && pNumRule->IsOutlineRule()) ) // #i27610#
1663 5130 : pTxtNode->ResetAttr( RES_PARATR_NUMRULE );
1664 :
1665 5204 : if( !rStyleInfo.pOutlineNumrule )
1666 : {
1667 5162 : if (
1668 5408 : (USHRT_MAX > rStyleInfo.nLFOIndex) &&
1669 246 : (WW8ListManager::nMaxLevel > rStyleInfo.nListLevel)
1670 : )
1671 : {
1672 : RegisterNumFmtOnTxtNode(rStyleInfo.nLFOIndex,
1673 246 : rStyleInfo.nListLevel, false);
1674 : }
1675 : }
1676 : else
1677 : {
1678 : // Use outline level set at the style info <rStyleInfo> instead of
1679 : // the outline level at the text format, because the WW8 document
1680 : // could contain more than one outline numbering rule and the one
1681 : // of the text format isn't the one, which a chosen as the Writer
1682 : // outline rule.
1683 42 : pTxtNode->SetAttrListLevel( rStyleInfo.nOutlineLevel );
1684 : }
1685 : }
1686 5204 : return bRes;
1687 : }
1688 :
1689 18 : void UseListIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
1690 : {
1691 : // #i86652#
1692 18 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1693 : {
1694 0 : const long nAbsLSpace = rFmt.GetAbsLSpace();
1695 0 : const long nListFirstLineIndent = GetListFirstLineIndent(rFmt);
1696 0 : SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
1697 0 : aLR.SetTxtLeft(nAbsLSpace);
1698 0 : aLR.SetTxtFirstLineOfst(writer_cast<short>(nListFirstLineIndent));
1699 0 : rStyle.pFmt->SetFmtAttr(aLR);
1700 0 : rStyle.bListReleventIndentSet = true;
1701 : }
1702 18 : }
1703 :
1704 15 : void SetStyleIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
1705 : {
1706 15 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) // #i86652#
1707 : {
1708 0 : SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
1709 0 : if (rStyle.bListReleventIndentSet)
1710 : {
1711 :
1712 0 : SyncIndentWithList( aLR, rFmt, false, false ); // #i103711#, #i105414#
1713 : }
1714 : else
1715 : {
1716 0 : aLR.SetTxtLeft(0);
1717 0 : aLR.SetTxtFirstLineOfst(0);
1718 : }
1719 0 : rStyle.pFmt->SetFmtAttr(aLR);
1720 : }
1721 15 : }
1722 :
1723 20 : void SwWW8ImplReader::SetStylesList(sal_uInt16 nStyle, sal_uInt16 nActLFO,
1724 : sal_uInt8 nActLevel)
1725 : {
1726 20 : if (nStyle >= vColl.size())
1727 20 : return;
1728 :
1729 20 : SwWW8StyInf &rStyleInf = vColl[nStyle];
1730 20 : if (rStyleInf.bValid)
1731 : {
1732 : OSL_ENSURE(pAktColl, "Cannot be called outside of style import");
1733 : // Phase 1: Nummerierungsattribute beim Einlesen einer StyleDef
1734 20 : if( pAktColl )
1735 : {
1736 : // jetzt nur die Parameter vermerken: die tatsaechliche Liste wird
1737 : // spaeter drangehaengt, wenn die Listendefinitionen gelesen sind...
1738 20 : if (
1739 20 : (USHRT_MAX > nActLFO) &&
1740 : (WW8ListManager::nMaxLevel > nActLevel)
1741 : )
1742 : {
1743 20 : rStyleInf.nLFOIndex = nActLFO;
1744 20 : rStyleInf.nListLevel = nActLevel;
1745 20 : if (nActLevel > 0) // it must be an outline list
1746 8 : rStyleInf.nOutlineLevel = nActLevel;
1747 :
1748 20 : if (
1749 20 : (USHRT_MAX > nActLFO) &&
1750 : (WW8ListManager::nMaxLevel > nActLevel)
1751 : )
1752 : {
1753 20 : std::vector<sal_uInt8> aParaSprms;
1754 : SwNumRule *pNmRule =
1755 : pLstManager->GetNumRuleForActivation(nActLFO,
1756 20 : nActLevel, aParaSprms);
1757 20 : if (pNmRule)
1758 18 : UseListIndent(rStyleInf, pNmRule->Get(nActLevel));
1759 : }
1760 : }
1761 : }
1762 : }
1763 : }
1764 :
1765 603 : void SwWW8ImplReader::RegisterNumFmtOnStyle(sal_uInt16 nStyle)
1766 : {
1767 :
1768 603 : if (nStyle >= vColl.size())
1769 603 : return;
1770 :
1771 603 : SwWW8StyInf &rStyleInf = vColl[nStyle];
1772 603 : if (rStyleInf.bValid && rStyleInf.pFmt)
1773 : {
1774 : //Save old pre-list modified indent, which are the word indent values
1775 546 : rStyleInf.maWordLR =
1776 1092 : ItemGet<SvxLRSpaceItem>(*rStyleInf.pFmt, RES_LR_SPACE);
1777 :
1778 : // Phase 2: aktualisieren der StyleDef nach einlesen aller Listen
1779 546 : SwNumRule* pNmRule = 0;
1780 546 : sal_uInt16 nLFO = rStyleInf.nLFOIndex;
1781 546 : sal_uInt8 nLevel = rStyleInf.nListLevel;
1782 546 : if (
1783 17 : (USHRT_MAX > nLFO) &&
1784 : (WW8ListManager::nMaxLevel > nLevel)
1785 : )
1786 : {
1787 17 : std::vector<sal_uInt8> aParaSprms;
1788 : pNmRule = pLstManager->GetNumRuleForActivation(nLFO, nLevel,
1789 17 : aParaSprms);
1790 :
1791 17 : if (pNmRule)
1792 : {
1793 15 : if( MAXLEVEL > rStyleInf.nOutlineLevel )
1794 11 : rStyleInf.pOutlineNumrule = pNmRule;
1795 : else
1796 : {
1797 : rStyleInf.pFmt->SetFmtAttr(
1798 4 : SwNumRuleItem( pNmRule->GetName() ) );
1799 4 : rStyleInf.bHasStyNumRule = true;
1800 : }
1801 17 : }
1802 : }
1803 :
1804 546 : if (pNmRule)
1805 15 : SetStyleIndent(rStyleInf, pNmRule->Get(nLevel));
1806 : }
1807 : }
1808 :
1809 483 : void SwWW8ImplReader::RegisterNumFmtOnTxtNode(sal_uInt16 nActLFO,
1810 : sal_uInt8 nActLevel, bool bSetAttr)
1811 : {
1812 : // beachte: die Methode haengt die NumRule an den Text Node, falls
1813 : // bSetAttr (dann muessen natuerlich vorher die Listen gelesen sein)
1814 : // stellt sie NUR den Level ein, im Vertrauen darauf, dass am STYLE eine
1815 : // NumRule haengt - dies wird NICHT ueberprueft !!!
1816 :
1817 483 : if (pLstManager) // sind die Listendeklarationen gelesen?
1818 : {
1819 483 : SwTxtNode* pTxtNd = pPaM->GetNode()->GetTxtNode();
1820 : OSL_ENSURE(pTxtNd, "No Text-Node at PaM-Position");
1821 483 : if (!pTxtNd)
1822 483 : return;
1823 :
1824 483 : std::vector<sal_uInt8> aParaSprms;
1825 : const SwNumRule* pRule = bSetAttr ?
1826 : pLstManager->GetNumRuleForActivation( nActLFO, nActLevel,
1827 483 : aParaSprms, pTxtNd) : 0;
1828 :
1829 483 : if (pRule || !bSetAttr)
1830 : {
1831 : //#i24136# old is the same as new, and its the outline numbering,
1832 : //then we don't set the numrule again, and we just take the num node
1833 : //(the actual outline numbering gets set in SetOutlineNum)
1834 : using namespace sw::util;
1835 479 : bool bUnchangedOutlineNumbering = false;
1836 : /*
1837 : If the node is outline numbered, and the new numbering to apply
1838 : is the one that was chosen to be the outline numbering then all
1839 : is unchanged
1840 : */
1841 : // correct condition according to the above given comment.
1842 479 : if ( pTxtNd->GetNumRule() == rDoc.GetOutlineNumRule() &&
1843 0 : pRule == mpChosenOutlineNumRule )
1844 : {
1845 0 : bUnchangedOutlineNumbering = true;
1846 : }
1847 479 : if (!bUnchangedOutlineNumbering)
1848 : {
1849 : //If its normal numbering, see if its the same as it already
1850 : //was, if its not, and we have been asked to set it, then set
1851 : //it to the new one
1852 479 : if (bSetAttr)
1853 : {
1854 233 : const SwNumRule *pNormal = pTxtNd->GetNumRule();
1855 233 : if (pNormal != pRule)
1856 : {
1857 : pTxtNd->SetAttr
1858 233 : (SwNumRuleItem(pRule->GetName()));
1859 : }
1860 : }
1861 : }
1862 479 : pTxtNd->SetAttrListLevel(nActLevel);
1863 :
1864 : // <IsCounted()> state of text node has to be adjusted accordingly.
1865 479 : if ( /*nActLevel >= 0 &&*/ nActLevel < MAXLEVEL )
1866 : {
1867 479 : pTxtNd->SetCountedInList( true );
1868 : }
1869 :
1870 : // #i99822#
1871 : // Direct application of the list level formatting no longer
1872 : // needed for list levels of mode LABEL_ALIGNMENT
1873 479 : bool bApplyListLevelIndentDirectlyAtPara( true );
1874 479 : if ( pTxtNd->GetNumRule() && nActLevel < MAXLEVEL )
1875 : {
1876 397 : const SwNumFmt& rFmt = pTxtNd->GetNumRule()->Get( nActLevel );
1877 397 : if ( rFmt.GetPositionAndSpaceMode() ==
1878 : SvxNumberFormat::LABEL_ALIGNMENT )
1879 : {
1880 397 : bApplyListLevelIndentDirectlyAtPara = false;
1881 : }
1882 : }
1883 :
1884 479 : if ( bApplyListLevelIndentDirectlyAtPara )
1885 : {
1886 82 : SfxItemSet aListIndent(rDoc.GetAttrPool(), RES_LR_SPACE,
1887 82 : RES_LR_SPACE);
1888 : const SvxLRSpaceItem *pItem = (const SvxLRSpaceItem*)(
1889 82 : GetFmtAttr(RES_LR_SPACE));
1890 : OSL_ENSURE(pItem, "impossible");
1891 82 : if (pItem)
1892 82 : aListIndent.Put(*pItem);
1893 :
1894 : /*
1895 : Take the original paragraph sprms attached to this list level
1896 : formatting and apply them to the paragraph. I'm convinced that
1897 : this is exactly what word does.
1898 : */
1899 82 : if (short nLen = static_cast< short >(aParaSprms.size()))
1900 : {
1901 0 : SfxItemSet* pOldAktItemSet = pAktItemSet;
1902 0 : SetAktItemSet(&aListIndent);
1903 :
1904 0 : sal_uInt8* pSprms1 = &aParaSprms[0];
1905 0 : while (0 < nLen)
1906 : {
1907 0 : sal_uInt16 nL1 = ImportSprm(pSprms1);
1908 0 : nLen = nLen - nL1;
1909 0 : pSprms1 += nL1;
1910 : }
1911 :
1912 0 : SetAktItemSet(pOldAktItemSet);
1913 : }
1914 :
1915 : const SvxLRSpaceItem *pLR =
1916 82 : HasItem<SvxLRSpaceItem>(aListIndent, RES_LR_SPACE);
1917 : OSL_ENSURE(pLR, "Impossible");
1918 82 : if (pLR)
1919 : {
1920 82 : pCtrlStck->NewAttr(*pPaM->GetPoint(), *pLR);
1921 82 : pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
1922 82 : }
1923 : }
1924 483 : }
1925 : }
1926 : }
1927 :
1928 257 : void SwWW8ImplReader::RegisterNumFmt(sal_uInt16 nActLFO, sal_uInt8 nActLevel)
1929 : {
1930 : // sind wir erst beim Einlesen der StyleDef ?
1931 257 : if (pAktColl)
1932 20 : SetStylesList( nAktColl , nActLFO, nActLevel);
1933 : else
1934 237 : RegisterNumFmtOnTxtNode(nActLFO, nActLevel);
1935 257 : }
1936 :
1937 572 : void SwWW8ImplReader::Read_ListLevel(sal_uInt16, const sal_uInt8* pData,
1938 : short nLen)
1939 : {
1940 572 : if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
1941 0 : return;
1942 :
1943 572 : if( nLen < 0 )
1944 : {
1945 : // the actual level is finished, what should we do ?
1946 276 : nListLevel = WW8ListManager::nMaxLevel;
1947 276 : if (pStyles && !bVer67)
1948 276 : pStyles->nWwNumLevel = 0;
1949 : }
1950 : else
1951 : {
1952 : // security check
1953 296 : if( !pData )
1954 0 : return;
1955 :
1956 : // die Streamdaten sind hier Null basiert, so wie wir es brauchen
1957 296 : nListLevel = *pData;
1958 :
1959 296 : if (pStyles && !bVer67)
1960 : {
1961 : /*
1962 : if this is the case, then if the numbering is actually stored in
1963 : winword 6 format, and its likely that sprmPIlvl has been abused
1964 : to set the ww6 list level information which we will need when we
1965 : reach the true ww6 list def. So set it now
1966 : */
1967 296 : pStyles->nWwNumLevel = nListLevel;
1968 : }
1969 :
1970 296 : if (WW8ListManager::nMaxLevel <= nListLevel )
1971 0 : nListLevel = WW8ListManager::nMaxLevel;
1972 296 : else if
1973 : (
1974 296 : (USHRT_MAX > nLFOPosition) &&
1975 0 : (WW8ListManager::nMaxLevel > nListLevel)
1976 : )
1977 : {
1978 0 : RegisterNumFmt(nLFOPosition, nListLevel);
1979 0 : nLFOPosition = USHRT_MAX;
1980 0 : nListLevel = WW8ListManager::nMaxLevel;
1981 : }
1982 : }
1983 : }
1984 :
1985 572 : void SwWW8ImplReader::Read_LFOPosition(sal_uInt16, const sal_uInt8* pData,
1986 : short nLen)
1987 : {
1988 572 : if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
1989 0 : return;
1990 :
1991 572 : if( nLen < 0 )
1992 : {
1993 : // the actual level is finished, what should we do ?
1994 276 : nLFOPosition = USHRT_MAX;
1995 276 : nListLevel = WW8ListManager::nMaxLevel;
1996 : }
1997 : else
1998 : {
1999 : // security check
2000 296 : if( !pData )
2001 0 : return;
2002 :
2003 296 : short nData = SVBT16ToShort( pData );
2004 296 : if( 0 >= nData )
2005 : {
2006 : // disable the numbering/list style apply to the paragraph or the style
2007 :
2008 : /*
2009 : If you have a paragraph in word with left and/or hanging indent
2010 : and remove its numbering, then the indentation appears to get
2011 : reset, but not back to the base style, instead its goes to a blank
2012 : setting.
2013 : Unless its a broken ww6 list in 97 in which case more hackery is
2014 : required, some more details about broken ww6 list in
2015 : ww8par6.cxx#SwWW8ImplReader::Read_LR
2016 : */
2017 :
2018 39 : if (pAktColl)
2019 : {
2020 : // here a "named" style is beeing configured
2021 :
2022 : // disable the numbering/list in the style currently configured
2023 0 : pAktColl->SetFmtAttr(*GetDfltAttr(RES_PARATR_NUMRULE));
2024 :
2025 : // reset/blank the indent
2026 0 : pAktColl->SetFmtAttr(SvxLRSpaceItem(RES_LR_SPACE));
2027 : }
2028 39 : else if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
2029 : {
2030 : // here a paragraph is being directly formated
2031 :
2032 : // empty the numbering/list style applied to the current paragraph
2033 39 : SwNumRuleItem aEmptyRule( aEmptyStr );
2034 39 : pTxtNode->SetAttr( aEmptyRule );
2035 :
2036 : // create an empty SvxLRSpaceItem
2037 78 : SvxLRSpaceItem aLR( RES_LR_SPACE );
2038 :
2039 : // replace it with the one of the current node if it exist
2040 39 : const SfxPoolItem* pLR = GetFmtAttr(RES_LR_SPACE);
2041 39 : if( pLR )
2042 39 : aLR = *static_cast<const SvxLRSpaceItem*>(pLR);
2043 :
2044 : // reset/blank the left indent (and only the left)
2045 39 : aLR.SetTxtLeft(0);
2046 39 : aLR.SetTxtFirstLineOfst(0);
2047 :
2048 : // apply the modified SvxLRSpaceItem to the current paragraph
2049 78 : pTxtNode->SetAttr( aLR );
2050 : }
2051 :
2052 39 : nLFOPosition = USHRT_MAX;
2053 : }
2054 : else
2055 : {
2056 257 : nLFOPosition = (sal_uInt16)nData-1;
2057 : /*
2058 : If we are a ww8+ style with ww7- style lists then there is a
2059 : bizarre broken word bug where when the list is removed from a para
2060 : the ww6 list first line indent still affects the first line
2061 : indentation. Setting this flag will allow us to recover from this
2062 : braindeadness
2063 : */
2064 257 : if (pAktColl && (nLFOPosition == 2047-1) && nAktColl < vColl.size())
2065 0 : vColl[nAktColl].bHasBrokenWW6List = true;
2066 :
2067 : // die Streamdaten sind hier 1 basiert, wir ziehen EINS ab
2068 257 : if (USHRT_MAX > nLFOPosition)
2069 : {
2070 257 : if (nLFOPosition != 2047-1) //Normal ww8+ list behaviour
2071 : {
2072 257 : if (WW8ListManager::nMaxLevel == nListLevel)
2073 0 : nListLevel = 0;
2074 257 : else if (WW8ListManager::nMaxLevel > nListLevel)
2075 : {
2076 257 : RegisterNumFmt(nLFOPosition, nListLevel);
2077 257 : nLFOPosition = USHRT_MAX;
2078 257 : nListLevel = WW8ListManager::nMaxLevel;
2079 : }
2080 : }
2081 0 : else if (pPlcxMan && pPlcxMan->HasParaSprm(0xC63E))
2082 : {
2083 : /*
2084 : #i8114# Horrific backwards compatible ww7- lists in ww8+
2085 : docs
2086 : */
2087 0 : Read_ANLevelNo(13 /*equiv ww7- sprm no*/, &nListLevel, 1);
2088 : }
2089 : }
2090 : }
2091 : }
2092 : }
2093 :
2094 : // -------------------------------------------------------------------
2095 : // ------------------------- Reading Controls ------------------------
2096 : // -------------------------------------------------------------------
2097 :
2098 0 : bool SwWW8ImplReader::ImportFormulaControl(WW8FormulaControl &aFormula,
2099 : WW8_CP nStart, SwWw8ControlType nWhich )
2100 : {
2101 0 : bool bRet=false;
2102 : /*
2103 : * Save the reader state and process the sprms for this anchor cp.
2104 : * Doing so will set the nPicLocFc to the offset to find the hypertext
2105 : * data in the data stream.
2106 : */
2107 0 : WW8_CP nEndCp = nStart+1; //Only interested in the single 0x01 character
2108 :
2109 0 : WW8ReaderSave aSave(this,nStart);
2110 :
2111 : WW8PLCFManResult aRes;
2112 0 : nStart = pPlcxMan->Where();
2113 0 : while(nStart <= nEndCp)
2114 : {
2115 0 : if ( pPlcxMan->Get(&aRes)
2116 0 : && aRes.pMemPos && aRes.nSprmId )
2117 : {
2118 : //only interested in sprms which would set nPicLocFc
2119 0 : if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
2120 : {
2121 : Read_PicLoc( aRes.nSprmId, aRes.pMemPos +
2122 0 : mpSprmParser->DistanceToData(aRes.nSprmId), 4);
2123 0 : break;
2124 : }
2125 : }
2126 0 : pPlcxMan->advance();
2127 0 : nStart = pPlcxMan->Where();
2128 : }
2129 0 : sal_uLong nOffset = nPicLocFc;
2130 0 : aSave.Restore(this);
2131 :
2132 0 : sal_uLong nOldPos = pDataStream->Tell();
2133 0 : WW8_PIC aPic;
2134 0 : pDataStream->Seek( nOffset);
2135 0 : PicRead( pDataStream, &aPic, bVer67);
2136 :
2137 0 : if((aPic.lcb > 0x3A) && !pDataStream->GetError() )
2138 : {
2139 0 : aFormula.FormulaRead(nWhich,pDataStream);
2140 0 : bRet = true;
2141 : }
2142 :
2143 : /*
2144 : There is a problem with aPic, the WW8_PIC is always used even though it
2145 : is too big for the WW95 files, it needs to be modified to check the
2146 : version C.
2147 : */
2148 0 : pDataStream->Seek( nOldPos );
2149 0 : return(bRet);
2150 : }
2151 :
2152 0 : sal_Bool SwMSConvertControls::InsertFormula(WW8FormulaControl &rFormula)
2153 : {
2154 0 : sal_Bool bRet = sal_False;
2155 :
2156 : const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory =
2157 0 : GetServiceFactory();
2158 :
2159 0 : if(!rServiceFactory.is())
2160 0 : return sal_False;
2161 :
2162 0 : awt::Size aSz;
2163 0 : uno::Reference< form::XFormComponent> xFComp;
2164 :
2165 0 : if (sal_True == (bRet = rFormula.Import(rServiceFactory, xFComp, aSz)))
2166 : {
2167 0 : uno::Reference <drawing::XShape> xShapeRef;
2168 0 : if (sal_True == (bRet = InsertControl(xFComp, aSz, &xShapeRef, false)))
2169 0 : GetShapes()->add(xShapeRef);
2170 : }
2171 0 : return bRet;
2172 : }
2173 :
2174 0 : void WW8FormulaControl::FormulaRead(SwWw8ControlType nWhich,
2175 : SvStream *pDataStream)
2176 : {
2177 : sal_uInt8 nField;
2178 : // nHeaderBype == version
2179 0 : sal_uInt32 nHeaderByte = 0;
2180 :
2181 : // The following is a FFData structure as described in
2182 : // Microsoft's DOC specification (chapter 2.9.78)
2183 :
2184 0 : *pDataStream >> nHeaderByte;
2185 :
2186 : // might be better to read the bits as a 16 bit word
2187 : // ( like it is in the spec. )
2188 0 : sal_uInt8 bits1 = 0;
2189 0 : *pDataStream >> bits1;
2190 0 : sal_uInt8 bits2 = 0;
2191 0 : *pDataStream >> bits2;
2192 :
2193 0 : sal_uInt8 iType = ( bits1 & 0x3 );
2194 :
2195 : // we should verify that bits.iType & nWhich concur
2196 : OSL_ENSURE( iType == nWhich, "something wrong, expect control type read from stream doesn't match nWhich passed in");
2197 0 : if ( !( iType == nWhich ) )
2198 0 : return; // bail out
2199 :
2200 0 : sal_uInt8 iRes = (bits1 & 0x7C) >> 2;
2201 :
2202 0 : sal_uInt16 cch = 0;
2203 0 : *pDataStream >> cch;
2204 :
2205 0 : sal_uInt16 hps = 0;
2206 0 : *pDataStream >> hps;
2207 :
2208 : // xstzName
2209 0 : sTitle = read_uInt16_BeltAndBracesString(*pDataStream);
2210 :
2211 0 : if (nWhich == WW8_CT_EDIT)
2212 : { // Field is a textbox
2213 : // Default text
2214 : // xstzTextDef
2215 0 : sDefault = read_uInt16_BeltAndBracesString(*pDataStream);
2216 : }
2217 : else
2218 : {
2219 : // CheckBox or ComboBox
2220 0 : sal_uInt16 wDef = 0;
2221 0 : *pDataStream >> wDef;
2222 0 : nChecked = wDef; // default
2223 0 : if (nWhich == WW8_CT_CHECKBOX)
2224 : {
2225 0 : if ( iRes != 25 )
2226 0 : nChecked = iRes;
2227 0 : sDefault = ( wDef == 0 ) ? OUString( "0" ) : OUString( "1" );
2228 : }
2229 : }
2230 : // xstzTextFormat
2231 0 : sFormatting = read_uInt16_BeltAndBracesString(*pDataStream);
2232 : // xstzHelpText
2233 0 : sHelp = read_uInt16_BeltAndBracesString(*pDataStream);
2234 : // xstzStatText
2235 0 : sToolTip = read_uInt16_BeltAndBracesString(*pDataStream);
2236 :
2237 0 : /*String sEntryMacro =*/ read_uInt16_BeltAndBracesString(*pDataStream);
2238 0 : /*String sExitMcr =*/ read_uInt16_BeltAndBracesString(*pDataStream);
2239 :
2240 0 : if (nWhich == WW8_CT_DROPDOWN)
2241 : {
2242 0 : bool bAllOk = true;
2243 : // SSTB (see Spec. 2.2.4)
2244 0 : sal_uInt16 fExtend = 0;
2245 0 : *pDataStream >> fExtend;
2246 0 : sal_uInt16 nNoStrings = 0;
2247 :
2248 : // Isn't it that if fExtend isn't 0xFFFF then fExtend actually
2249 : // doesn't exist and we really have just read nNoStrings ( or cData )?
2250 0 : if (fExtend != 0xFFFF)
2251 0 : bAllOk = false;
2252 0 : *pDataStream >> nNoStrings;
2253 :
2254 : // I guess this should be zero ( and we should ensure that )
2255 0 : sal_uInt16 cbExtra = 0;
2256 0 : *pDataStream >> cbExtra;
2257 :
2258 : OSL_ENSURE(bAllOk,
2259 : "Unknown formfield dropdown list structure. Report to cmc");
2260 0 : if (!bAllOk) //Not as expected, don't risk it at all.
2261 0 : nNoStrings = 0;
2262 0 : maListEntries.reserve(nNoStrings);
2263 0 : for (sal_uInt32 nI = 0; nI < nNoStrings; ++nI)
2264 : {
2265 0 : String sEntry = read_uInt16_PascalString(*pDataStream);
2266 0 : maListEntries.push_back(sEntry);
2267 0 : }
2268 : }
2269 0 : fDropdownIndex = iRes;
2270 :
2271 0 : nField = bits2;
2272 0 : fToolTip = nField & 0x01;
2273 0 : fNoMark = (nField & 0x02)>>1;
2274 0 : fUseSize = (nField & 0x04)>>2;
2275 0 : fNumbersOnly= (nField & 0x08)>>3;
2276 0 : fDateOnly = (nField & 0x10)>>4;
2277 0 : fUnused = (nField & 0xE0)>>5;
2278 : }
2279 :
2280 0 : WW8FormulaListBox::WW8FormulaListBox(SwWW8ImplReader &rR)
2281 0 : : WW8FormulaControl(OUString(SL::aListBox), rR)
2282 : {
2283 0 : }
2284 :
2285 : //Miserable hack to get a hardcoded guesstimate of the size of a list dropdown
2286 : //box's first entry to set as the lists default size
2287 0 : awt::Size SwWW8ImplReader::MiserableDropDownFormHack(const String &rString,
2288 : uno::Reference<beans::XPropertySet>& rPropSet)
2289 : {
2290 0 : awt::Size aRet;
2291 : struct CtrlFontMapEntry
2292 : {
2293 : sal_uInt16 nWhichId;
2294 : const sal_Char* pPropNm;
2295 : };
2296 : const CtrlFontMapEntry aMapTable[] =
2297 : {
2298 : { RES_CHRATR_COLOR, "TextColor" },
2299 : { RES_CHRATR_FONT, "FontName" },
2300 : { RES_CHRATR_FONTSIZE, "FontHeight" },
2301 : { RES_CHRATR_WEIGHT, "FontWeight" },
2302 : { RES_CHRATR_UNDERLINE, "FontUnderline" },
2303 : { RES_CHRATR_CROSSEDOUT, "FontStrikeout" },
2304 : { RES_CHRATR_POSTURE, "FontSlant" },
2305 : { 0, 0 }
2306 0 : };
2307 :
2308 0 : Font aFont;
2309 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
2310 0 : rPropSet->getPropertySetInfo();
2311 :
2312 0 : uno::Any aTmp;
2313 0 : for (const CtrlFontMapEntry* pMap = aMapTable; pMap->nWhichId; ++pMap)
2314 : {
2315 0 : bool bSet = true;
2316 0 : const SfxPoolItem* pItem = GetFmtAttr( pMap->nWhichId );
2317 : OSL_ENSURE(pItem, "Impossible");
2318 0 : if (!pItem)
2319 0 : continue;
2320 :
2321 0 : switch ( pMap->nWhichId )
2322 : {
2323 : case RES_CHRATR_COLOR:
2324 : {
2325 0 : String pNm;
2326 0 : if (xPropSetInfo->hasPropertyByName(pNm = "TextColor"))
2327 : {
2328 0 : aTmp <<= (sal_Int32)((SvxColorItem*)pItem)->GetValue().GetColor();
2329 0 : rPropSet->setPropertyValue(pNm, aTmp);
2330 0 : }
2331 : }
2332 0 : aFont.SetColor(((SvxColorItem*)pItem)->GetValue());
2333 0 : break;
2334 : case RES_CHRATR_FONT:
2335 : {
2336 0 : const SvxFontItem *pFontItem = (SvxFontItem *)pItem;
2337 0 : String pNm;
2338 0 : if (xPropSetInfo->hasPropertyByName(pNm = "FontStyleName"))
2339 : {
2340 0 : aTmp <<= OUString( pFontItem->GetStyleName());
2341 0 : rPropSet->setPropertyValue( pNm, aTmp );
2342 : }
2343 0 : if (xPropSetInfo->hasPropertyByName(pNm = "FontFamily"))
2344 : {
2345 0 : aTmp <<= (sal_Int16)pFontItem->GetFamily();
2346 0 : rPropSet->setPropertyValue( pNm, aTmp );
2347 : }
2348 0 : if (xPropSetInfo->hasPropertyByName(pNm = "FontCharset"))
2349 : {
2350 0 : aTmp <<= (sal_Int16)pFontItem->GetCharSet();
2351 0 : rPropSet->setPropertyValue( pNm, aTmp );
2352 : }
2353 0 : if (xPropSetInfo->hasPropertyByName(pNm = "FontPitch"))
2354 : {
2355 0 : aTmp <<= (sal_Int16)pFontItem->GetPitch();
2356 0 : rPropSet->setPropertyValue( pNm, aTmp );
2357 : }
2358 :
2359 0 : aTmp <<= OUString( pFontItem->GetFamilyName());
2360 0 : aFont.SetName( pFontItem->GetFamilyName() );
2361 0 : aFont.SetStyleName( pFontItem->GetStyleName() );
2362 0 : aFont.SetFamily( pFontItem->GetFamily() );
2363 0 : aFont.SetCharSet( pFontItem->GetCharSet() );
2364 0 : aFont.SetPitch( pFontItem->GetPitch() );
2365 : }
2366 0 : break;
2367 :
2368 : case RES_CHRATR_FONTSIZE:
2369 : {
2370 0 : Size aSize( aFont.GetSize().Width(),
2371 0 : ((SvxFontHeightItem*)pItem)->GetHeight() );
2372 0 : aTmp <<= ((float)aSize.Height()) / 20.0;
2373 :
2374 : aFont.SetSize(OutputDevice::LogicToLogic(aSize, MAP_TWIP,
2375 0 : MAP_100TH_MM));
2376 : }
2377 0 : break;
2378 :
2379 : case RES_CHRATR_WEIGHT:
2380 0 : aTmp <<= (float)VCLUnoHelper::ConvertFontWeight(
2381 0 : ((SvxWeightItem*)pItem)->GetWeight() );
2382 0 : aFont.SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
2383 0 : break;
2384 :
2385 : case RES_CHRATR_UNDERLINE:
2386 0 : aTmp <<= (sal_Int16)(((SvxUnderlineItem*)pItem)->GetLineStyle());
2387 0 : aFont.SetUnderline(((SvxUnderlineItem*)pItem)->GetLineStyle());
2388 0 : break;
2389 :
2390 : case RES_CHRATR_CROSSEDOUT:
2391 0 : aTmp <<= (sal_Int16)( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
2392 0 : aFont.SetStrikeout( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
2393 0 : break;
2394 :
2395 : case RES_CHRATR_POSTURE:
2396 0 : aTmp <<= (sal_Int16)( ((SvxPostureItem*)pItem)->GetPosture() );
2397 0 : aFont.SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
2398 0 : break;
2399 :
2400 : default:
2401 0 : bSet = false;
2402 0 : break;
2403 : }
2404 :
2405 0 : if (bSet && xPropSetInfo->hasPropertyByName(OUString::createFromAscii(pMap->pPropNm)))
2406 0 : rPropSet->setPropertyValue(OUString::createFromAscii(pMap->pPropNm), aTmp);
2407 : }
2408 : // now calculate the size of the control
2409 0 : OutputDevice* pOut = Application::GetDefaultDevice();
2410 : OSL_ENSURE(pOut, "Impossible");
2411 0 : if (pOut)
2412 : {
2413 0 : pOut->Push( PUSH_FONT | PUSH_MAPMODE );
2414 0 : pOut->SetMapMode( MapMode( MAP_100TH_MM ));
2415 0 : pOut->SetFont( aFont );
2416 0 : aRet.Width = pOut->GetTextWidth(rString);
2417 0 : aRet.Width += 500; //plus size of button, total hack territory
2418 0 : aRet.Height = pOut->GetTextHeight();
2419 0 : pOut->Pop();
2420 : }
2421 0 : return aRet;
2422 : }
2423 :
2424 0 : sal_Bool WW8FormulaListBox::Import(const uno::Reference <
2425 : lang::XMultiServiceFactory> &rServiceFactory,
2426 : uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
2427 : {
2428 0 : uno::Reference<uno::XInterface> xCreate = rServiceFactory->createInstance("com.sun.star.form.component.ComboBox");
2429 0 : if( !xCreate.is() )
2430 0 : return sal_False;
2431 :
2432 0 : rFComp = uno::Reference<form::XFormComponent>(xCreate, uno::UNO_QUERY);
2433 0 : if( !rFComp.is() )
2434 0 : return sal_False;
2435 :
2436 0 : uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY);
2437 :
2438 0 : uno::Any aTmp;
2439 0 : if (!sTitle.isEmpty())
2440 0 : aTmp <<= sTitle;
2441 : else
2442 0 : aTmp <<= sName;
2443 0 : xPropSet->setPropertyValue("Name", aTmp );
2444 :
2445 0 : if (!sToolTip.isEmpty())
2446 : {
2447 0 : aTmp <<= sToolTip;
2448 0 : xPropSet->setPropertyValue("HelpText", aTmp );
2449 : }
2450 :
2451 0 : sal_Bool bDropDown(sal_True);
2452 0 : xPropSet->setPropertyValue("Dropdown", cppu::bool2any(bDropDown));
2453 :
2454 0 : if (!maListEntries.empty())
2455 : {
2456 0 : sal_uInt32 nLen = maListEntries.size();
2457 0 : uno::Sequence< OUString > aListSource(nLen);
2458 0 : for (sal_uInt32 nI = 0; nI < nLen; ++nI)
2459 0 : aListSource[nI] = OUString(maListEntries[nI]);
2460 0 : aTmp <<= aListSource;
2461 0 : xPropSet->setPropertyValue("StringItemList", aTmp );
2462 :
2463 0 : if (fDropdownIndex < nLen)
2464 : {
2465 0 : aTmp <<= aListSource[fDropdownIndex];
2466 : }
2467 : else
2468 : {
2469 0 : aTmp <<= aListSource[0];
2470 : }
2471 :
2472 0 : xPropSet->setPropertyValue("DefaultText", aTmp );
2473 :
2474 0 : rSz = rRdr.MiserableDropDownFormHack(maListEntries[0], xPropSet);
2475 : }
2476 : else
2477 : {
2478 : static const sal_Unicode aBlank[] =
2479 : {
2480 : 0x2002,0x2002,0x2002,0x2002,0x2002
2481 : };
2482 0 : rSz = rRdr.MiserableDropDownFormHack(OUString(aBlank, SAL_N_ELEMENTS(aBlank)), xPropSet);
2483 : }
2484 :
2485 0 : return sal_True;
2486 : }
2487 :
2488 0 : WW8FormulaCheckBox::WW8FormulaCheckBox(SwWW8ImplReader &rR)
2489 0 : : WW8FormulaControl(OUString(SL::aCheckBox), rR)
2490 : {
2491 0 : }
2492 :
2493 0 : static void lcl_AddToPropertyContainer
2494 : (uno::Reference<beans::XPropertySet> xPropSet,
2495 : const OUString & rPropertyName, const OUString & rValue)
2496 : {
2497 : uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
2498 0 : xPropSet->getPropertySetInfo();
2499 0 : if (xPropSetInfo.is() &&
2500 0 : ! xPropSetInfo->hasPropertyByName(rPropertyName))
2501 : {
2502 : uno::Reference<beans::XPropertyContainer>
2503 0 : xPropContainer(xPropSet, uno::UNO_QUERY);
2504 0 : uno::Any aAny(OUString(""));
2505 0 : xPropContainer->addProperty
2506 : (rPropertyName,
2507 : static_cast<sal_Int16>(beans::PropertyAttribute::BOUND |
2508 : beans::PropertyAttribute::REMOVABLE),
2509 0 : aAny);
2510 : }
2511 :
2512 0 : uno::Any aAnyValue(rValue);
2513 0 : xPropSet->setPropertyValue(rPropertyName, aAnyValue );
2514 0 : }
2515 :
2516 0 : sal_Bool WW8FormulaCheckBox::Import(const uno::Reference <
2517 : lang::XMultiServiceFactory> &rServiceFactory,
2518 : uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
2519 : {
2520 0 : uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance("com.sun.star.form.component.CheckBox");
2521 0 : if( !xCreate.is() )
2522 0 : return sal_False;
2523 :
2524 0 : rFComp = uno::Reference< form::XFormComponent >( xCreate, uno::UNO_QUERY );
2525 0 : if( !rFComp.is() )
2526 0 : return sal_False;
2527 :
2528 0 : uno::Reference< beans::XPropertySet > xPropSet( xCreate, uno::UNO_QUERY );
2529 :
2530 0 : rSz.Width = 16 * hpsCheckBox;
2531 0 : rSz.Height = 16 * hpsCheckBox;
2532 :
2533 0 : uno::Any aTmp;
2534 0 : if (!sTitle.isEmpty())
2535 0 : aTmp <<= sTitle;
2536 : else
2537 0 : aTmp <<= sName;
2538 0 : xPropSet->setPropertyValue("Name", aTmp );
2539 :
2540 0 : aTmp <<= (sal_Int16)nChecked;
2541 0 : xPropSet->setPropertyValue("DefaultState", aTmp);
2542 :
2543 0 : if (!sToolTip.isEmpty())
2544 0 : lcl_AddToPropertyContainer(xPropSet, "HelpText", sToolTip);
2545 :
2546 0 : if (!sHelp.isEmpty())
2547 0 : lcl_AddToPropertyContainer(xPropSet, "HelpF1Text", sHelp);
2548 :
2549 0 : return sal_True;
2550 :
2551 : }
2552 :
2553 0 : WW8FormulaEditBox::WW8FormulaEditBox(SwWW8ImplReader &rR)
2554 0 : : WW8FormulaControl(OUString(SL::aTextField) ,rR)
2555 : {
2556 0 : }
2557 :
2558 1 : sal_Bool SwMSConvertControls::InsertControl(
2559 : const uno::Reference< form::XFormComponent > & rFComp,
2560 : const awt::Size& rSize, uno::Reference< drawing::XShape > *pShape,
2561 : sal_Bool bFloatingCtrl)
2562 : {
2563 1 : const uno::Reference< container::XIndexContainer > &rComps = GetFormComps();
2564 : uno::Any aTmp( &rFComp, ::getCppuType((const uno::Reference<
2565 1 : form::XFormComponent >*)0) );
2566 1 : rComps->insertByIndex( rComps->getCount(), aTmp );
2567 :
2568 : const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory =
2569 1 : GetServiceFactory();
2570 1 : if( !rServiceFactory.is() )
2571 0 : return sal_False;
2572 :
2573 1 : uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance(
2574 2 : "com.sun.star.drawing.ControlShape");
2575 1 : if( !xCreate.is() )
2576 0 : return sal_False;
2577 :
2578 : uno::Reference< drawing::XShape > xShape =
2579 2 : uno::Reference< drawing::XShape >(xCreate, uno::UNO_QUERY);
2580 :
2581 : OSL_ENSURE(xShape.is(), "XShape nicht erhalten");
2582 1 : xShape->setSize(rSize);
2583 :
2584 : uno::Reference< beans::XPropertySet > xShapePropSet(
2585 2 : xCreate, uno::UNO_QUERY );
2586 :
2587 : //I lay a small bet that this will change to
2588 : //sal_Int16 nTemp=TextContentAnchorType::AS_CHARACTER;
2589 : sal_Int16 nTemp;
2590 1 : if (bFloatingCtrl)
2591 1 : nTemp= text::TextContentAnchorType_AT_PARAGRAPH;
2592 : else
2593 0 : nTemp= text::TextContentAnchorType_AS_CHARACTER;
2594 :
2595 1 : aTmp <<= nTemp;
2596 1 : xShapePropSet->setPropertyValue("AnchorType", aTmp );
2597 :
2598 1 : nTemp= text::VertOrientation::TOP;
2599 1 : aTmp <<= nTemp;
2600 1 : xShapePropSet->setPropertyValue("VertOrient", aTmp );
2601 :
2602 2 : uno::Reference< text::XText > xDummyTxtRef;
2603 : uno::Reference< text::XTextRange > xTxtRg =
2604 2 : new SwXTextRange( *pPaM, xDummyTxtRef );
2605 :
2606 : aTmp.setValue(&xTxtRg,::getCppuType((
2607 1 : uno::Reference< text::XTextRange >*)0));
2608 1 : xShapePropSet->setPropertyValue("TextRange", aTmp );
2609 :
2610 : // Das Control-Model am Control-Shape setzen
2611 : uno::Reference< drawing::XControlShape > xControlShape( xShape,
2612 2 : uno::UNO_QUERY );
2613 : uno::Reference< awt::XControlModel > xControlModel( rFComp,
2614 2 : uno::UNO_QUERY );
2615 1 : xControlShape->setControl( xControlModel );
2616 :
2617 1 : if (pShape)
2618 1 : *pShape = xShape;
2619 :
2620 2 : return sal_True;
2621 18 : }
2622 :
2623 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|