LibreOffice Module svx (master)  1
fmexpl.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 
21 #include <svx/strings.hrc>
22 #include <fmexpl.hxx>
23 
24 #include <helpids.h>
25 #include <svx/fmglob.hxx>
26 #include <svx/fmtools.hxx>
27 #include <fmexch.hxx>
28 
29 #include <svx/svxids.hrc>
30 
31 #include <fmprop.hxx>
32 #include <bitmaps.hlst>
33 #include <svx/dialmgr.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <sfx2/objitem.hxx>
37 
38 #include <svx/fmshell.hxx>
39 #include <comphelper/types.hxx>
40 
41 using namespace ::svxform;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::form;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::lang;
46 using namespace ::com::sun::star::container;
47 
48 FmNavInsertedHint::FmNavInsertedHint( FmEntryData* pInsertedEntryData, sal_uInt32 nRelPos )
49  :pEntryData( pInsertedEntryData )
50  ,nPos( nRelPos )
51 
52 {
53 }
54 
55 
57 {
58 }
59 
60 
61 
63  :pEntryData( pAffectedEntryData )
64 {
65 }
66 
67 
69 {
70 }
71 
73  :pEntryData( pRemovedEntryData )
74 {
75 }
76 
77 
79 {
80 }
81 
82 FmNavNameChangedHint::FmNavNameChangedHint( FmEntryData* pData, const OUString& rNewName )
83  :pEntryData( pData )
84  ,aNewName( rNewName )
85 {
86 }
87 
88 
90 {
91 }
92 
94 {
95 }
96 
97 
99 {
100 }
101 
102 
104 {
105 }
106 
107 
109 {
110 }
111 
112 
114 {
115  auto it = std::find_if(maEntryDataList.begin(), maEntryDataList.end(),
116  [&pItem](const std::unique_ptr<FmEntryData>& rEntryData) { return rEntryData.get() == pItem; });
117  if (it != maEntryDataList.end())
118  {
119  it->release();
120  maEntryDataList.erase( it );
121  return;
122  }
123  assert(false);
124 }
125 
126 
127 void FmEntryDataList::insert( std::unique_ptr<FmEntryData> pItem, size_t Index )
128 {
129  if ( Index < maEntryDataList.size() )
130  {
131  maEntryDataList.insert( maEntryDataList.begin() + Index, std::move(pItem) );
132  }
133  else
134  maEntryDataList.push_back( std::move(pItem) );
135 }
136 
137 
139 {
140  maEntryDataList.clear();
141 }
142 
143 
144 FmEntryData::FmEntryData( FmEntryData* pParentData, const Reference< XInterface >& _rxIFace )
145  :pParent( pParentData )
146 {
147  pChildList.reset( new FmEntryDataList() );
148 
149  newObject( _rxIFace );
150 }
151 
152 
154 {
155  pChildList->clear();
156 }
157 
158 
159 void FmEntryData::newObject( const css::uno::Reference< css::uno::XInterface >& _rxIFace )
160 {
161  // do not just copy, normalize it
162  m_xNormalizedIFace.set( _rxIFace, UNO_QUERY );
163  m_xProperties.set(m_xNormalizedIFace, css::uno::UNO_QUERY);
164  m_xChild.set(m_xNormalizedIFace, css::uno::UNO_QUERY);
165 }
166 
167 
169 {
170  pChildList.reset( new FmEntryDataList() );
171  aText = rEntryData.GetText();
172  m_aNormalImage = rEntryData.GetNormalImage();
173  pParent = rEntryData.GetParent();
174 
175  FmEntryData* pChildData;
176  size_t nEntryCount = rEntryData.GetChildList()->size();
177  for( size_t i = 0; i < nEntryCount; i++ )
178  {
179  pChildData = rEntryData.GetChildList()->at( i );
180  std::unique_ptr<FmEntryData> pNewChildData = pChildData->Clone();
181  pChildList->insert( std::move(pNewChildData), size_t(-1) );
182  }
183 
185  m_xProperties = rEntryData.m_xProperties;
186  m_xChild = rEntryData.m_xChild;
187 }
188 
189 
190 
192 {
193  if(this == pEntryData)
194  return true;
195 
196  if( !pEntryData )
197  return false;
198 
199  if( aText != pEntryData->GetText() )
200  return false;
201 
202  if( !pEntryData->GetParent() && pParent )
203  return false;
204 
205  if( pEntryData->GetParent() && !pParent )
206  return false;
207 
208  if( !pEntryData->GetParent() && !pParent )
209  return true;
210 
211  if( !pParent->IsEqualWithoutChildren(pEntryData->GetParent()) )
212  return false;
213 
214  return true;
215 }
216 
217 FmFormData::FmFormData(const Reference< XForm >& _rxForm, FmFormData* _pParent)
218  : FmEntryData(_pParent, _rxForm)
219  , m_xForm(_rxForm)
220 {
221  // set images
222  m_aNormalImage = Image(RID_SVXBMP_FORM);
223 
224  // set title
225  if (m_xForm.is())
226  {
227  Reference< XPropertySet > xSet(m_xForm, UNO_QUERY);
228  if (xSet.is())
229  {
230  OUString aEntryName(::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME )));
231  SetText(aEntryName);
232  }
233  }
234  else
235  SetText( OUString() );
236 }
237 
239 {
240 }
241 
243  :FmEntryData( rFormData )
244 {
245  m_xForm = rFormData.GetFormIface();
246 }
247 
248 
249 std::unique_ptr<FmEntryData> FmFormData::Clone()
250 {
251  return std::unique_ptr<FmEntryData>(new FmFormData( *this ));
252 }
253 
254 
256 {
257  if(this == pEntryData)
258  return true;
259  if( dynamic_cast<const FmFormData*>( pEntryData) == nullptr )
260  return false;
261  FmFormData* pFormData = static_cast<FmFormData*>(pEntryData);
262  if( m_xForm.get() != pFormData->GetFormIface().get() )
263  return false;
264 
265  return FmEntryData::IsEqualWithoutChildren( pFormData );
266 }
267 
268 FmControlData::FmControlData(const Reference< XFormComponent >& _rxComponent, FmFormData* _pParent)
269 : FmEntryData( _pParent, _rxComponent ),
270  m_xFormComponent( _rxComponent )
271 {
272 
273  // set images
274  m_aNormalImage = GetImage();
275 
276 
277  // set title
278  Reference< XPropertySet > xSet(m_xFormComponent, UNO_QUERY);
279  if( xSet.is() )
280  {
281  SetText( ::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME )));
282  }
283 }
284 
285 
287 {
288 }
289 
290 
292  :FmEntryData( rControlData )
293 {
294  m_xFormComponent = rControlData.GetFormComponent();
295 }
296 
297 
298 std::unique_ptr<FmEntryData> FmControlData::Clone()
299 {
300  return std::unique_ptr<FmEntryData>(new FmControlData( *this ));
301 }
302 
303 
305 {
306  // Default-Image
307  Image aImage(StockImage::Yes, RID_SVXBMP_CONTROL);
308 
309  Reference< XServiceInfo > xInfo( m_xFormComponent, UNO_QUERY );
310  if (!m_xFormComponent.is())
311  return aImage;
312 
313 
314  // Spezielle Control-Images
315  sal_Int16 nObjectType = getControlTypeByObject(xInfo);
316  switch (nObjectType)
317  {
318  case OBJ_FM_BUTTON:
319  aImage = Image(StockImage::Yes, RID_SVXBMP_BUTTON);
320  break;
321 
322  case OBJ_FM_FIXEDTEXT:
323  aImage = Image(StockImage::Yes, RID_SVXBMP_FIXEDTEXT);
324  break;
325 
326  case OBJ_FM_EDIT:
327  aImage = Image(StockImage::Yes, RID_SVXBMP_EDITBOX);
328  break;
329 
330  case OBJ_FM_RADIOBUTTON:
331  aImage = Image(StockImage::Yes, RID_SVXBMP_RADIOBUTTON);
332  break;
333 
334  case OBJ_FM_CHECKBOX:
335  aImage = Image(StockImage::Yes, RID_SVXBMP_CHECKBOX);
336  break;
337 
338  case OBJ_FM_LISTBOX:
339  aImage = Image(StockImage::Yes, RID_SVXBMP_LISTBOX);
340  break;
341 
342  case OBJ_FM_COMBOBOX:
343  aImage = Image(StockImage::Yes, RID_SVXBMP_COMBOBOX);
344  break;
345 
347  aImage = Image(StockImage::Yes, RID_SVXBMP_NAVIGATIONBAR);
348  break;
349 
350  case OBJ_FM_GROUPBOX:
351  aImage = Image(StockImage::Yes, RID_SVXBMP_GROUPBOX);
352  break;
353 
354  case OBJ_FM_IMAGEBUTTON:
355  aImage = Image(StockImage::Yes, RID_SVXBMP_IMAGEBUTTON);
356  break;
357 
358  case OBJ_FM_FILECONTROL:
359  aImage = Image(StockImage::Yes, RID_SVXBMP_FILECONTROL);
360  break;
361 
362  case OBJ_FM_HIDDEN:
363  aImage = Image(StockImage::Yes, RID_SVXBMP_HIDDEN);
364  break;
365 
366  case OBJ_FM_DATEFIELD:
367  aImage = Image(StockImage::Yes, RID_SVXBMP_DATEFIELD);
368  break;
369 
370  case OBJ_FM_TIMEFIELD:
371  aImage = Image(StockImage::Yes, RID_SVXBMP_TIMEFIELD);
372  break;
373 
374  case OBJ_FM_NUMERICFIELD:
375  aImage = Image(StockImage::Yes, RID_SVXBMP_NUMERICFIELD);
376  break;
377 
379  aImage = Image(StockImage::Yes, RID_SVXBMP_CURRENCYFIELD);
380  break;
381 
382  case OBJ_FM_PATTERNFIELD:
383  aImage = Image(StockImage::Yes, RID_SVXBMP_PATTERNFIELD);
384  break;
385 
386  case OBJ_FM_IMAGECONTROL:
387  aImage = Image(StockImage::Yes, RID_SVXBMP_IMAGECONTROL);
388  break;
389 
391  aImage = Image(StockImage::Yes, RID_SVXBMP_FORMATTEDFIELD);
392  break;
393 
394  case OBJ_FM_GRID:
395  aImage = Image(StockImage::Yes, RID_SVXBMP_GRID);
396  break;
397 
398  case OBJ_FM_SCROLLBAR:
399  aImage = Image(StockImage::Yes, RID_SVXBMP_SCROLLBAR);
400  break;
401 
402  case OBJ_FM_SPINBUTTON:
403  aImage = Image(StockImage::Yes, RID_SVXBMP_SPINBUTTON);
404  break;
405  }
406 
407  return aImage;
408 }
409 
411 {
412  if(this == pEntryData)
413  return true;
414 
415  if( dynamic_cast<const FmControlData*>( pEntryData) == nullptr )
416  return false;
417  FmControlData* pControlData = static_cast<FmControlData*>(pEntryData);
418 
419  if( m_xFormComponent.get() != pControlData->GetFormComponent().get() )
420  return false;
421 
422  return FmEntryData::IsEqualWithoutChildren( pControlData );
423 }
424 
425 void FmControlData::ModelReplaced(const Reference< XFormComponent >& _rxNew)
426 {
427  m_xFormComponent = _rxNew;
429  // set images anew
431 }
432 
433 namespace svxform
434 {
435 
437  vcl::Window* _pParent )
439  ,SfxControllerItem( SID_FM_FMEXPLORER_CONTROL, *_pBindings )
440  {
441  SetHelpId( HID_FORM_NAVIGATOR_WIN );
442 
444  m_pNavigatorTree->Show();
445  SetText( SvxResId(RID_STR_FMEXPLORER) );
447  }
448 
449 
451  {
452  disposeOnce();
453  }
454 
456  {
457  m_pNavigatorTree.disposeAndClear();
460  }
461 
462 
464  {
465  m_pNavigatorTree->UpdateContent( pFormShell );
466  }
467 
468 
469  void NavigatorFrame::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
470  {
471  if( !pState || SID_FM_FMEXPLORER_CONTROL != nSID )
472  return;
473 
474  if( eState >= SfxItemState::DEFAULT )
475  {
476  FmFormShell* pShell = dynamic_cast<FmFormShell*>( static_cast<const SfxObjectItem*>(pState)->GetShell() );
477  UpdateContent( pShell );
478  }
479  else
480  UpdateContent( nullptr );
481  }
482 
483 
485  {
486  if ( m_pNavigatorTree )
487  m_pNavigatorTree->GrabFocus();
488  else
489  SfxDockingWindow::GetFocus();
490  }
491 
492 
494  {
495  UpdateContent( nullptr );
496  return SfxDockingWindow::Close();
497  }
498 
499 
501  {
503  rInfo.bVisible = false;
504  }
505 
506 
508  {
509  if ( ( eAlign == SfxChildAlignment::TOP ) || ( eAlign == SfxChildAlignment::BOTTOM ) )
510  return Size();
511 
512  return SfxDockingWindow::CalcDockingSize( eAlign );
513  }
514 
515 
517  {
518  if ( ( _eAlign == SfxChildAlignment::LEFT ) || ( _eAlign == SfxChildAlignment::RIGHT ) || ( _eAlign == SfxChildAlignment::NOALIGNMENT ) )
519  return _eAlign;
520  return _eActAlign;
521  }
522 
523 
525  {
527 
528  Size aLogOutputSize = PixelToLogic(GetOutputSizePixel(), MapMode(MapUnit::MapAppFont));
529  Size aLogExplSize = aLogOutputSize;
530  aLogExplSize.AdjustWidth( -6 );
531  aLogExplSize.AdjustHeight( -6 );
532 
533  Point aExplPos = LogicToPixel(Point(3, 3), MapMode(MapUnit::MapAppFont));
534  Size aExplSize = LogicToPixel(aLogExplSize, MapMode(MapUnit::MapAppFont));
535 
536  m_pNavigatorTree->SetPosSizePixel( aExplPos, aExplSize );
537  }
538 
539 
540 
541 
542  SFX_IMPL_DOCKINGWINDOW( NavigatorFrameManager, SID_FM_SHOW_FMEXPLORER )
543 
544 
545  NavigatorFrameManager::NavigatorFrameManager( vcl::Window* _pParent, sal_uInt16 _nId,
546  SfxBindings* _pBindings, SfxChildWinInfo* _pInfo )
547  :SfxChildWindow( _pParent, _nId )
548  {
549  SetWindow( VclPtr<NavigatorFrame>::Create( _pBindings, this, _pParent ) );
550  static_cast<SfxDockingWindow*>(GetWindow())->Initialize( _pInfo );
551  }
552 }
553 
554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
WinBits const WB_ROLLABLE
css::uno::Reference< css::form::XForm > m_xForm
Definition: fmexpl.hxx:227
WinBits const WB_DOCKABLE
void UpdateContent(FmFormShell *pFormShell)
Definition: fmexpl.cxx:463
void removeNoDelete(FmEntryData *pItem)
Definition: fmexpl.cxx:113
long AdjustWidth(long n)
virtual ~FmControlData() override
Definition: fmexpl.cxx:286
virtual ~FmNavClearedHint() override
Definition: fmexpl.cxx:98
virtual SfxChildAlignment CheckAlignment(SfxChildAlignment, SfxChildAlignment) override
Definition: fmexpl.cxx:516
sal_Int16 getControlTypeByObject(const Reference< css::lang::XServiceInfo > &_rxObject)
Definition: fmtools.cxx:296
FmEntryData * GetParent() const
Definition: fmexpl.hxx:159
const sal_uInt16 OBJ_FM_NAVIGATIONBAR
Definition: fmglob.hxx:48
FmNavRemovedHint(FmEntryData *pInsertedEntryData)
Definition: fmexpl.cxx:72
css::uno::Reference< css::beans::XPropertySet > m_xProperties
Definition: fmexpl.hxx:133
const sal_uInt16 OBJ_FM_NUMERICFIELD
Definition: fmglob.hxx:40
virtual bool IsEqualWithoutChildren(FmEntryData *pEntryData) override
Definition: fmexpl.cxx:410
virtual void GetFocus() override
Definition: fmexpl.cxx:484
long AdjustHeight(long n)
virtual Size CalcDockingSize(SfxChildAlignment) override
Definition: fmexpl.cxx:507
virtual ~FmNavModelReplacedHint() override
Definition: fmexpl.cxx:68
sal_Int64 WinBits
void insert(std::unique_ptr< FmEntryData > pItem, size_t Index)
Definition: fmexpl.cxx:127
std::unique_ptr< FmEntryDataList > pChildList
Definition: fmexpl.hxx:141
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
const sal_uInt16 OBJ_FM_IMAGEBUTTON
Definition: fmglob.hxx:36
void SetFloatingSize(const Size &rSize)
css::uno::Reference< css::uno::XInterface > m_xNormalizedIFace
Definition: fmexpl.hxx:132
FmEntryData * at(size_t Index)
Definition: fmexpl.hxx:193
Image m_aNormalImage
Definition: fmexpl.hxx:137
virtual bool Close() override
virtual void Resize() override
Definition: fmexpl.cxx:524
const sal_uInt16 OBJ_FM_PATTERNFIELD
Definition: fmglob.hxx:42
void SetText(const OUString &rText)
Definition: fmexpl.hxx:153
const sal_uInt16 OBJ_FM_EDIT
Definition: fmglob.hxx:27
void FillInfo(SfxChildWinInfo &rInfo) const override
Definition: fmexpl.cxx:500
FmEntryData * pParent
Definition: fmexpl.hxx:142
VclPtr< ::svxform::NavigatorTree > m_pNavigatorTree
Definition: fmexpl.hxx:513
virtual ~FmNavNameChangedHint() override
Definition: fmexpl.cxx:89
virtual bool IsEqualWithoutChildren(FmEntryData *pEntryData)
Definition: fmexpl.cxx:191
virtual ~FmNavInsertedHint() override
Definition: fmexpl.cxx:56
const OUString & GetText() const
Definition: fmexpl.hxx:158
Shell * GetShell()
int i
const css::uno::Reference< css::form::XForm > & GetFormIface() const
Definition: fmexpl.hxx:234
virtual void dispose()
const sal_uInt16 OBJ_FM_GROUPBOX
Definition: fmglob.hxx:34
virtual Size CalcDockingSize(SfxChildAlignment)
std::vector< std::unique_ptr< FmEntryData > > maEntryDataList
Definition: fmexpl.hxx:187
NavigatorFrame(SfxBindings *pBindings, SfxChildWindow *pMgr, vcl::Window *pParent)
Definition: fmexpl.cxx:436
void newObject(const css::uno::Reference< css::uno::XInterface > &_rxIFace)
Definition: fmexpl.cxx:159
const Image & GetNormalImage() const
Definition: fmexpl.hxx:156
css::uno::Reference< css::container::XChild > m_xChild
Definition: fmexpl.hxx:134
const sal_uInt16 OBJ_FM_FILECONTROL
Definition: fmglob.hxx:37
const sal_uInt16 OBJ_FM_COMBOBOX
Definition: fmglob.hxx:32
virtual std::unique_ptr< FmEntryData > Clone()=0
const css::uno::Reference< css::form::XFormComponent > & GetFormComponent() const
Definition: fmexpl.hxx:256
#define HID_FORM_NAVIGATOR_WIN
Definition: helpids.h:45
FmNavNameChangedHint(FmEntryData *pData, const OUString &rNewName)
Definition: fmexpl.cxx:82
virtual ~FmEntryData()
Definition: fmexpl.cxx:153
void clear()
Definition: fmexpl.cxx:138
const sal_uInt16 OBJ_FM_CHECKBOX
Definition: fmglob.hxx:31
virtual bool IsEqualWithoutChildren(FmEntryData *pEntryData) override
Definition: fmexpl.cxx:255
const sal_uInt16 OBJ_FM_SCROLLBAR
Definition: fmglob.hxx:46
const sal_uInt16 OBJ_FM_FIXEDTEXT
Definition: fmglob.hxx:29
const sal_uInt16 OBJ_FM_SPINBUTTON
Definition: fmglob.hxx:47
const sal_uInt16 OBJ_FM_GRID
Definition: fmglob.hxx:35
virtual ~NavigatorFrame() override
Definition: fmexpl.cxx:450
size_t size() const
Definition: fmexpl.hxx:196
WinBits const WB_3DLOOK
virtual std::unique_ptr< FmEntryData > Clone() override
Definition: fmexpl.cxx:249
WinBits const WB_SIZEABLE
FmNavModelReplacedHint(FmEntryData *pAffectedEntryData)
Definition: fmexpl.cxx:62
FmEntryData(FmEntryData *pParentData, const css::uno::Reference< css::uno::XInterface > &_rIFace)
const sal_uInt16 OBJ_FM_RADIOBUTTON
Definition: fmglob.hxx:33
void StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem *pState) override
Definition: fmexpl.cxx:469
virtual void FillInfo(SfxChildWinInfo &) const
SfxItemState
SfxChildAlignment
const sal_uInt16 OBJ_FM_FORMATTEDFIELD
Definition: fmglob.hxx:45
FmControlData(const css::uno::Reference< css::form::XFormComponent > &_rxComponent, FmFormData *_pParent)
static VclPtr< reference_type > Create(Arg &&...arg)
const sal_uInt16 OBJ_FM_LISTBOX
Definition: fmglob.hxx:30
void ModelReplaced(const css::uno::Reference< css::form::XFormComponent > &_rxNew)
Definition: fmexpl.cxx:425
char aEntryName[20]
const sal_uInt16 OBJ_FM_IMAGECONTROL
Definition: fmglob.hxx:44
virtual ~FmNavRemovedHint() override
Definition: fmexpl.cxx:78
virtual bool Close() override
Definition: fmexpl.cxx:493
class FmSearchEngine - Impl class for FmSearchDialog
Image GetImage() const
Definition: fmexpl.cxx:304
virtual void Resize() override
WinBits const WB_STDMODELESS
virtual std::unique_ptr< FmEntryData > Clone() override
Definition: fmexpl.cxx:298
FmFormData(const css::uno::Reference< css::form::XForm > &_rxForm, FmFormData *_pParent)
OUString getString(const Any &_rAny)
css::uno::Reference< css::form::XFormComponent > m_xFormComponent
Definition: fmexpl.hxx:243
virtual void dispose() override
const sal_uInt16 OBJ_FM_HIDDEN
Definition: fmglob.hxx:43
struct _ADOIndex Index
const sal_uInt16 OBJ_FM_BUTTON
Definition: fmglob.hxx:28
const sal_uInt16 OBJ_FM_TIMEFIELD
Definition: fmglob.hxx:39
const sal_uInt16 OBJ_FM_CURRENCYFIELD
Definition: fmglob.hxx:41
virtual void dispose() override
Definition: fmexpl.cxx:455
FmEntryDataList * GetChildList() const
Definition: fmexpl.hxx:160
const sal_uInt16 OBJ_FM_DATEFIELD
Definition: fmglob.hxx:38
sal_uInt16 nPos
FmNavInsertedHint(FmEntryData *pInsertedEntryData, sal_uInt32 nRelPos)
Definition: fmexpl.cxx:48
virtual ~FmFormData() override
Definition: fmexpl.cxx:238
OUString aText
Definition: fmexpl.hxx:138