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