LibreOffice Module sw (master)  1
swatrset.cxx
Go to the documentation of this file.
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 <memory>
21 
22 #include <cellatr.hxx>
23 #include <charfmt.hxx>
24 #include <cmdid.h>
25 #include <doc.hxx>
26 #include <IDocumentListsAccess.hxx>
27 #include <editeng/colritem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <editeng/lineitem.hxx>
30 #include <editeng/boxitem.hxx>
31 #include <editeng/editeng.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtpdsc.hxx>
34 #include <hintids.hxx>
35 #include <istyleaccess.hxx>
36 #include <list.hxx>
37 #include <node.hxx>
38 #include <numrule.hxx>
39 #include <pagedesc.hxx>
40 #include <paratr.hxx>
41 #include <osl/diagnose.h>
42 #include <svl/whiter.hxx>
43 #include <svx/xtable.hxx>
44 
45 #include <svx/svdpool.hxx>
46 #include <svx/sxenditm.hxx>
47 #include <svx/sdsxyitm.hxx>
48 
50  : SfxItemPool( "SWG",
52  aSlotTab, &aAttrTab ),
53  m_pDoc( pD )
54 {
55  // create secondary pools immediately
57 }
58 
60 {
61  // cleanup secondary pools first
63 }
64 
66 {
67  const SfxItemPool* pCheckAlreadySet = GetSecondaryPool();
68 
69  if(pCheckAlreadySet)
70  {
71  OSL_ENSURE(false, "SwAttrPool already has a secondary pool (!)");
72  return;
73  }
74 
75  // create SfxItemPool and EditEngine pool and add these in a chain. These
76  // belong us and will be removed/destroyed in removeAndDeleteSecondaryPools() used from
77  // the destructor
78  SfxItemPool *pSdrPool = new SdrItemPool(this);
79 
80  // #75371# change DefaultItems for the SdrEdgeObj distance items
81  // to TWIPS.
82  // 1/100th mm in twips
83  const long nDefEdgeDist = (500 * 72) / 127;
84 
85  pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
86  pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
87  pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
88  pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
89 
90  // #i33700# // Set shadow distance defaults as PoolDefaultItems
91  pSdrPool->SetPoolDefaultItem(makeSdrShadowXDistItem((300 * 72) / 127));
92  pSdrPool->SetPoolDefaultItem(makeSdrShadowYDistItem((300 * 72) / 127));
93 
94  SfxItemPool *pEEgPool = EditEngine::CreatePool();
95 
96  pSdrPool->SetSecondaryPool(pEEgPool);
97 
98  if(!GetFrozenIdRanges())
99  {
100  FreezeIdRanges();
101  }
102  else
103  {
104  pSdrPool->FreezeIdRanges();
105  }
106 }
107 
109 {
110  SfxItemPool *pSdrPool = GetSecondaryPool();
111 
112  if(!pSdrPool)
113  {
114  OSL_ENSURE(false, "SwAttrPool has no secondary pool, it's missing (!)");
115  return;
116  }
117 
118  SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
119 
120  if(!pEEgPool)
121  {
122  OSL_ENSURE(false, "i don't accept additional pools");
123  return;
124  }
125 
126  // first delete the items, then break the linking
127  pSdrPool->Delete();
128 
129  SetSecondaryPool(nullptr);
130  pSdrPool->SetSecondaryPool(nullptr);
131 
132  // final cleanup of secondary pool(s)
133  SfxItemPool::Free(pSdrPool);
134  SfxItemPool::Free(pEEgPool);
135 }
136 
137 SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
138  : SfxItemSet( rPool, {{nWh1, nWh2}} ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
139 {
140 }
141 
142 SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable )
143  : SfxItemSet( rPool, nWhichPairTable ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
144 {
145 }
146 
148  : SfxItemSet( rSet ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
149 {
150 }
151 
152 std::unique_ptr<SfxItemSet> SwAttrSet::Clone( bool bItems, SfxItemPool *pToPool ) const
153 {
154  if ( pToPool && pToPool != GetPool() )
155  {
156  SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
157  std::unique_ptr<SfxItemSet> pTmpSet;
158  if ( !pAttrPool )
159  pTmpSet = SfxItemSet::Clone( bItems, pToPool );
160  else
161  {
162  pTmpSet.reset(new SwAttrSet( *pAttrPool, GetRanges() ));
163  if ( bItems )
164  {
165  SfxWhichIter aIter(*pTmpSet);
166  sal_uInt16 nWhich = aIter.FirstWhich();
167  while ( nWhich )
168  {
169  const SfxPoolItem* pItem;
170  if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
171  pTmpSet->Put( *pItem );
172  nWhich = aIter.NextWhich();
173  }
174  }
175  }
176  return pTmpSet;
177  }
178  else
179  return std::unique_ptr<SfxItemSet>(
180  bItems
181  ? new SwAttrSet( *this )
182  : new SwAttrSet( *GetPool(), GetRanges() ));
183 }
184 
185 bool SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
186  SwAttrSet* pOld, SwAttrSet* pNew )
187 {
188  m_pNewSet = pNew;
189  m_pOldSet = pOld;
190  bool bRet = nullptr != SfxItemSet::Put( rAttr );
191  m_pOldSet = m_pNewSet = nullptr;
192  return bRet;
193 }
194 
195 bool SwAttrSet::Put_BC( const SfxItemSet& rSet,
196  SwAttrSet* pOld, SwAttrSet* pNew )
197 {
198  m_pNewSet = pNew;
199  m_pOldSet = pOld;
200  bool bRet = SfxItemSet::Put( rSet );
201  m_pOldSet = m_pNewSet = nullptr;
202  return bRet;
203 }
204 
205 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
206  SwAttrSet* pOld, SwAttrSet* pNew )
207 {
208  m_pNewSet = pNew;
209  m_pOldSet = pOld;
210  sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
211  m_pOldSet = m_pNewSet = nullptr;
212  return nRet;
213 }
214 
215 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
216  SwAttrSet* pOld, SwAttrSet* pNew )
217 {
218  OSL_ENSURE( nWhich1 <= nWhich2, "no valid range" );
219  m_pNewSet = pNew;
220  m_pOldSet = pOld;
221  sal_uInt16 nRet = 0;
222  for( ; nWhich1 <= nWhich2; ++nWhich1 )
223  nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
224  m_pOldSet = m_pNewSet = nullptr;
225  return nRet;
226 }
227 
229  SwAttrSet* pOld, SwAttrSet* pNew )
230 {
231  m_pNewSet = pNew;
232  m_pOldSet = pOld;
233  SfxItemSet::Intersect( rSet );
234  m_pOldSet = m_pNewSet = nullptr;
235  return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 );
236 }
237 
239 void SwAttrSet::Changed( const SfxPoolItem& rOld, const SfxPoolItem& rNew )
240 {
241  if( m_pOldSet )
242  m_pOldSet->PutChgd( rOld );
243  if( m_pNewSet )
244  m_pNewSet->PutChgd( rNew );
245 }
246 
255 bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify )
256 {
257  bool bSet = false;
258 
259  const SfxPoolItem* pItem;
260  if( SfxItemState::SET == GetItemState( RES_PAGEDESC, false, &pItem ) &&
261  static_cast<const SwFormatPageDesc*>(pItem)->GetDefinedIn() != pModify )
262  {
263  const_cast<SwFormatPageDesc*>(static_cast<const SwFormatPageDesc*>(pItem))->ChgDefinedIn( pModify );
264  bSet = true;
265  }
266 
267  if( SfxItemState::SET == GetItemState( RES_PARATR_DROP, false, &pItem ) &&
268  static_cast<const SwFormatDrop*>(pItem)->GetDefinedIn() != pModify )
269  {
270  // If CharFormat is set and it is set in different attribute pools then
271  // the CharFormat has to be copied.
272  SwCharFormat* pCharFormat;
273  if( nullptr != ( pCharFormat = const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->GetCharFormat() )
274  && GetPool() != pCharFormat->GetAttrSet().GetPool() )
275  {
276  pCharFormat = GetDoc()->CopyCharFormat( *pCharFormat );
277  const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->SetCharFormat( pCharFormat );
278  }
279  const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->ChgDefinedIn( pModify );
280  bSet = true;
281  }
282 
283  if( SfxItemState::SET == GetItemState( RES_BOXATR_FORMULA, false, &pItem ) &&
284  static_cast<const SwTableBoxFormula*>(pItem)->GetDefinedIn() != pModify )
285  {
286  const_cast<SwTableBoxFormula*>(static_cast<const SwTableBoxFormula*>(pItem))->ChgDefinedIn( pModify );
287  bSet = true;
288  }
289 
290  return bSet;
291 }
292 
294 {
295  // copy attributes across multiple documents if needed
296  SwContentNode* pCNd = dynamic_cast<SwContentNode*>( &rMod );
297  SwFormat* pFormat = dynamic_cast<SwFormat*>( &rMod );
298 
299  if( pCNd || pFormat )
300  {
301  if( Count() )
302  {
303  // #i92811#
304  std::unique_ptr<SfxStringItem> pNewListIdItem;
305 
306  const SfxPoolItem* pItem;
307  const SwDoc *pSrcDoc = GetDoc();
308  SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFormat->GetDoc();
309 
310  // Does the NumRule has to be copied?
311  if( pSrcDoc != pDstDoc &&
312  SfxItemState::SET == GetItemState( RES_PARATR_NUMRULE, false, &pItem ) )
313  {
314  const OUString& rNm = static_cast<const SwNumRuleItem*>(pItem)->GetValue();
315  if( !rNm.isEmpty() )
316  {
317  SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
318  if( pDestRule )
319  pDestRule->SetInvalidRule( true );
320  else
321  pDstDoc->MakeNumRule( rNm, pSrcDoc->FindNumRulePtr( rNm ) );
322  }
323  }
324 
325  // copy list and if needed also the corresponding list style
326  // for text nodes
327  if ( pSrcDoc != pDstDoc &&
328  pCNd && pCNd->IsTextNode() &&
329  GetItemState( RES_PARATR_LIST_ID, false, &pItem ) == SfxItemState::SET )
330  {
331  auto pStrItem = dynamic_cast<const SfxStringItem*>(pItem);
332  assert(pStrItem);
333  const OUString& sListId = pStrItem->GetValue();
334  if ( !sListId.isEmpty() &&
335  !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
336  {
337  const SwList* pList = pSrcDoc->getIDocumentListsAccess().getListByName( sListId );
338  // copy list style, if needed
339  const OUString& sDefaultListStyleName =
340  pList->GetDefaultListStyleName();
341  // #i92811#
342  const SwNumRule* pDstDocNumRule =
343  pDstDoc->FindNumRulePtr( sDefaultListStyleName );
344  if ( !pDstDocNumRule )
345  {
346  pDstDoc->MakeNumRule( sDefaultListStyleName,
347  pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
348  }
349  else
350  {
351  const SwNumRule* pSrcDocNumRule =
352  pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
353  // If list id of text node equals the list style's
354  // default list id in the source document, the same
355  // should be hold in the destination document.
356  // Thus, create new list id item.
357  if (pSrcDocNumRule && sListId == pSrcDocNumRule->GetDefaultListId())
358  {
359  pNewListIdItem.reset(new SfxStringItem (
361  pDstDocNumRule->GetDefaultListId() ));
362  }
363  }
364  // check again, if list exist, because <SwDoc::MakeNumRule(..)>
365  // could have also created it.
366  if ( pNewListIdItem == nullptr &&
367  !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
368  {
369  // copy list
370  pDstDoc->getIDocumentListsAccess().createList( sListId, sDefaultListStyleName );
371  }
372  }
373  }
374 
375  std::unique_ptr< SfxItemSet > tmpSet;
376 
377  const SwPageDesc* pPgDesc;
378  if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState(
379  RES_PAGEDESC, false, &pItem ) &&
380  nullptr != ( pPgDesc = static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()) )
381  {
382  tmpSet.reset(new SfxItemSet(*this));
383 
384  SwPageDesc* pDstPgDesc = pDstDoc->FindPageDesc(pPgDesc->GetName());
385  if( !pDstPgDesc )
386  {
387  pDstPgDesc = pDstDoc->MakePageDesc(pPgDesc->GetName());
388  pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
389  }
390  SwFormatPageDesc aDesc( pDstPgDesc );
391  aDesc.SetNumOffset( static_cast<const SwFormatPageDesc*>(pItem)->GetNumOffset() );
392  tmpSet->Put( aDesc );
393  }
394 
395  if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState( RES_ANCHOR, false, &pItem )
396  && static_cast< const SwFormatAnchor* >( pItem )->GetContentAnchor() != nullptr )
397  {
398  if( !tmpSet )
399  tmpSet.reset( new SfxItemSet( *this ));
400  // Anchors at any node position cannot be copied to another document, because the SwPosition
401  // would still point to the old document. It needs to be fixed up explicitly.
402  tmpSet->ClearItem( RES_ANCHOR );
403  }
404 
405  if( tmpSet )
406  {
407  if( pCNd )
408  {
409  // #i92811#
410  if ( pNewListIdItem != nullptr )
411  {
412  tmpSet->Put( *pNewListIdItem );
413  }
414  pCNd->SetAttr( *tmpSet );
415  }
416  else
417  {
418  pFormat->SetFormatAttr( *tmpSet );
419  }
420  }
421  else if( pCNd )
422  {
423  // #i92811#
424  if ( pNewListIdItem != nullptr )
425  {
426  SfxItemSet aTmpSet( *this );
427  aTmpSet.Put( *pNewListIdItem );
428  pCNd->SetAttr( aTmpSet );
429  }
430  else
431  {
432  pCNd->SetAttr( *this );
433  }
434  }
435  else
436  {
437  pFormat->SetFormatAttr( *this );
438  }
439  }
440  }
441 #if OSL_DEBUG_LEVEL > 0
442  else
443  OSL_FAIL("neither Format nor ContentNode - no Attributes copied");
444 #endif
445 }
446 
448 bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId )
449 {
450  while( *pRange )
451  {
452  if( *pRange <= nId && nId <= *(pRange+1) )
453  return true;
454  pRange += 2;
455  }
456  return false;
457 }
458 
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ChgDefinedIn(const SwModify *pNew)
Definition: fmtpdsc.hxx:70
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
const OUString & GetDefaultListStyleName() const
Definition: list.cxx:233
virtual void Changed(const SfxPoolItem &rOld, const SfxPoolItem &rNew) override
Notification callback.
Definition: swatrset.cxx:239
std::string GetValue
SfxItemSet(const SfxItemSet &)
SwAttrPool(SwDoc *pDoc)
Definition: swatrset.cxx:49
virtual SwList * createList(const OUString &rListId, const OUString &rDefaultListStyleName)=0
const OUString & GetDefaultListId() const
Definition: numrule.hxx:192
Definition: list.hxx:33
Definition: doc.hxx:185
sal_uInt16 FirstWhich()
#define RES_PARATR_LIST_ID
Definition: hintids.hxx:185
void Delete()
void FreezeIdRanges()
void ChgDefinedIn(const SwModify *pNew)
Definition: paratr.hxx:106
sal_uInt16 NextWhich()
const OUString & GetName() const
Definition: pagedesc.hxx:186
#define POOLATTR_END
Definition: hintids.hxx:64
void PutChgd(const SfxPoolItem &rI)
Definition: swatrset.hxx:169
bool Put_BC(const SfxPoolItem &rAttr, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:185
const sal_uInt16 * GetFrozenIdRanges() const
bool SetModifyAtAttr(const SwModify *pModify)
special treatment for some attributes
Definition: swatrset.cxx:255
void removeAndDeleteSecondaryPools()
Definition: swatrset.cxx:108
void SetNumOffset(const ::boost::optional< sal_uInt16 > &oNum)
Definition: fmtpdsc.hxx:66
bool IsInRange(const sal_uInt16 *pRange, const sal_uInt16 nId)
check if ID is in range of attribute set IDs
Definition: swatrset.cxx:448
#define RES_PARATR_NUMRULE
Definition: hintids.hxx:170
void Intersect(const SfxItemSet &rSet)
SwAttrPool * GetPool() const
Definition: swatrset.hxx:190
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const override
Definition: swatrset.cxx:152
SwPageDesc * FindPageDesc(const OUString &rName, size_t *pPos=nullptr) const
Definition: docdesc.cxx:829
Base class for various Writer styles.
Definition: format.hxx:43
SwAttrSet * m_pNewSet
Definition: swatrset.hxx:164
#define POOLATTR_BEGIN
Definition: hintids.hxx:63
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2423
virtual SwList * getListByName(const OUString &rListId) const =0
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
#define RES_ANCHOR
Definition: hintids.hxx:209
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void CopyToModify(SwModify &rMod) const
Definition: swatrset.cxx:293
SwPageDesc * MakePageDesc(const OUString &rName, const SwPageDesc *pCpy=nullptr, bool bRegardLanguage=true, bool bBroadcast=false)
Definition: docdesc.cxx:646
sal_uInt16 Count() const
SwDoc * GetDoc()
Definition: node.hxx:702
void createAndAddSecondaryPools()
Definition: swatrset.cxx:65
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
void ChgDefinedIn(const SwModify *pNew)
Definition: cellatr.hxx:65
int Intersect_BC(const SfxItemSet &rSet, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:228
SdrMetricItem makeSdrShadowYDistItem(long nDist)
static SfxItemPool * CreatePool()
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:460
SfxItemPool * GetSecondaryPool() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
void CopyPageDesc(const SwPageDesc &rSrcDesc, SwPageDesc &rDstDesc, bool bCopyPoolIds=true)
Copy the complete PageDesc - beyond document and "deep"! Optionally copying of PoolFormatId, -HlpId can be prevented.
Definition: docfmt.cxx:1427
static void Free(SfxItemPool *pPool)
void SetInvalidRule(bool bFlag)
Definition: number.cxx:862
virtual bool SetAttr(const SfxPoolItem &)
made virtual
Definition: node.cxx:1471
SfxItemInfo aSlotTab[]
Definition: init.cxx:275
virtual ~SwAttrPool() override
Definition: swatrset.cxx:59
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const
SwCharFormat * CopyCharFormat(const SwCharFormat &)
copy the char format
Definition: docfmt.cxx:1180
SwDfltAttrTab aAttrTab
const SwFormatPageDesc & GetPageDesc(bool=true) const
Definition: fmtpdsc.hxx:76
const SwDoc * GetDoc() const
Definition: swatrset.hxx:204
sal_uInt16 MakeNumRule(const OUString &rName, const SwNumRule *pCpy=nullptr, bool bBroadcast=false, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode=SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
Definition: docnum.cxx:2457
SwAttrSet * m_pOldSet
Definition: swatrset.hxx:164
SwAttrSet(SwAttrPool &, sal_uInt16 nWhich1, sal_uInt16 nWhich2)
Definition: swatrset.cxx:137
const sal_uInt16 * GetRanges() const
#define RES_PARATR_DROP
Definition: hintids.hxx:168
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
If SwFormatDrop is a Client, it is the CharFormat that describes the font for the DropCaps...
Definition: paratr.hxx:50
#define RES_PAGEDESC
Definition: hintids.hxx:198
IDocumentListsAccess const & getIDocumentListsAccess() const
Definition: doc.cxx:325
bool IsTextNode() const
Definition: node.hxx:636
sal_uInt16 ClearItem_BC(sal_uInt16 nWhich, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:205
void SetSecondaryPool(SfxItemPool *pPool)
void SetCharFormat(SwCharFormat *pNew)
Definition: paratr.cxx:66
SdrMetricItem makeSdrShadowXDistItem(long nDist)
void SetPoolDefaultItem(const SfxPoolItem &)
#define RES_BOXATR_FORMULA
Definition: hintids.hxx:262