LibreOffice Module sw (master)  1
gctable.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 <hintids.hxx>
21 #include <tblrwcl.hxx>
22 #include <algorithm>
23 #include <editeng/borderline.hxx>
24 #include <editeng/boxitem.hxx>
25 #include <osl/diagnose.h>
26 
27 using namespace ::editeng;
28 
29 static const SvxBorderLine* GetLineTB( const SvxBoxItem* pBox, bool bTop )
30 {
31  return bTop ? pBox->GetTop() : pBox->GetBottom();
32 }
33 
35 {
36  if( const SvxBoxItem* pItem = rFormat.GetItemIfSet( RES_BOX ) )
37  {
38  const SvxBorderLine* pBrd = pItem->GetLeft();
39  if( pBrd )
40  {
41  if( *m_pBorderLine == *pBrd )
42  m_bAnyBorderFind = true;
43  return true;
44  }
45  }
46  return false;
47 }
48 
49 static bool lcl_GCBorder_ChkBoxBrd_B( const SwTableBox* pBox, SwGCBorder_BoxBrd* pPara );
50 
51 static bool lcl_GCBorder_ChkBoxBrd_L( const SwTableLine* pLine, SwGCBorder_BoxBrd* pPara )
52 {
53  const SwTableBox* pBox = pLine->GetTabBoxes().front();
54  return lcl_GCBorder_ChkBoxBrd_B( pBox, pPara );
55 }
56 
57 static bool lcl_GCBorder_ChkBoxBrd_B( const SwTableBox* pBox, SwGCBorder_BoxBrd* pPara )
58 {
59  if( !pBox->GetTabLines().empty() )
60  {
61  for( auto pLine : pBox->GetTabLines() )
62  {
63  if (!lcl_GCBorder_ChkBoxBrd_L( pLine, pPara ))
64  {
65  return false;
66  }
67  }
68  return true;
69  }
70 
71  return pPara->CheckLeftBorderOfFormat( *pBox->GetFrameFormat() );
72 }
73 
74 static void lcl_GCBorder_GetLastBox_B( const SwTableBox* pBox, SwTableBoxes* pPara );
75 
76 static void lcl_GCBorder_GetLastBox_L( const SwTableLine* pLine, SwTableBoxes* pPara )
77 {
78  const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
79  SwTableBox* pBox = rBoxes.back();
80  lcl_GCBorder_GetLastBox_B( pBox, pPara );
81 }
82 
83 static void lcl_GCBorder_GetLastBox_B( const SwTableBox* pBox, SwTableBoxes* pPara )
84 {
85  const SwTableLines& rLines = pBox->GetTabLines();
86  if( !rLines.empty() )
87  {
88  for( const SwTableLine* pLine : rLines )
89  lcl_GCBorder_GetLastBox_L( pLine, pPara );
90  }
91  else
92  pPara->push_back( const_cast<SwTableBox*>(pBox) );
93 }
94 
95 // Find the "end" of the passed BorderLine. Returns the "Layout"Pos!
96 static sal_uInt16 lcl_FindEndPosOfBorder( const SwCollectTableLineBoxes& rCollTLB,
97  const SvxBorderLine& rBrdLn, size_t& rStt, bool bTop )
98 {
99  sal_uInt16 nPos, nLastPos = 0;
100  for( size_t nEnd = rCollTLB.Count(); rStt < nEnd; ++rStt )
101  {
102  const SvxBorderLine* pBrd;
103  const SwTableBox& rBox = rCollTLB.GetBox( rStt, &nPos );
104  const SvxBoxItem* pItem = rBox.GetFrameFormat()->GetItemIfSet(RES_BOX);
105 
106  if( !pItem )
107  break;
108  pBrd = GetLineTB( pItem, bTop );
109  if( !pBrd || *pBrd != rBrdLn )
110  break;
111  nLastPos = nPos;
112  }
113  return nLastPos;
114 }
115 
116 static const SvxBorderLine* lcl_GCBorder_GetBorder( const SwTableBox& rBox,
117  bool bTop,
118  const SvxBoxItem** ppItem )
119 {
120  *ppItem = rBox.GetFrameFormat()->GetItemIfSet( RES_BOX );
121  if (*ppItem)
122  return GetLineTB( *ppItem, bTop );
123  return nullptr;
124 }
125 
126 static void lcl_GCBorder_DelBorder( const SwCollectTableLineBoxes& rCollTLB,
127  size_t& rStt, bool bTop,
128  const SvxBorderLine& rLine,
129  const SvxBoxItem* pItem,
130  sal_uInt16 nEndPos,
131  SwShareBoxFormats* pShareFormats )
132 {
133  SwTableBox* pBox = const_cast<SwTableBox*>(&rCollTLB.GetBox( rStt ));
134  sal_uInt16 nNextPos;
135  const SvxBorderLine* pLn = &rLine;
136 
137  do {
138  if( pLn && *pLn == rLine )
139  {
140  SvxBoxItem aBox( *pItem );
141  if( bTop )
142  aBox.SetLine( nullptr, SvxBoxItemLine::TOP );
143  else
144  aBox.SetLine( nullptr, SvxBoxItemLine::BOTTOM );
145 
146  if( pShareFormats )
147  pShareFormats->SetAttr( *pBox, aBox );
148  else
149  pBox->ClaimFrameFormat()->SetFormatAttr( aBox );
150  }
151 
152  if( ++rStt >= rCollTLB.Count() )
153  break;
154 
155  pBox = const_cast<SwTableBox*>(&rCollTLB.GetBox( rStt, &nNextPos ));
156  if( nNextPos > nEndPos )
157  break;
158 
159  pLn = lcl_GCBorder_GetBorder( *pBox, bTop, &pItem );
160 
161  } while( true );
162 }
163 
164 static void lcl_GC_Box_Border( const SwTableBox* pBox, SwGCLineBorder* pPara );
165 
166 void sw_GC_Line_Border( const SwTableLine* pLine, SwGCLineBorder* pGCPara )
167 {
168  // First the right edge with the left edge of the succeeding Box within this Line
169  {
170  SwGCBorder_BoxBrd aBPara;
171  const SvxBorderLine* pBrd;
172  const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
173  for( SwTableBoxes::size_type n = 0, nBoxes = rBoxes.size() - 1; n < nBoxes; ++n )
174  {
175  SwTableBoxes aBoxes;
176  {
177  SwTableBox* pBox = rBoxes[ n ];
178  if( pBox->GetSttNd() )
179  aBoxes.insert( aBoxes.begin(), pBox );
180  else
181  lcl_GCBorder_GetLastBox_B( pBox, &aBoxes );
182  }
183 
184  for( SwTableBoxes::size_type i = aBoxes.size(); i; )
185  {
186  SwTableBox* pBox = aBoxes[ --i ];
187  if( const SvxBoxItem* pItem = pBox->GetFrameFormat()->GetItemIfSet( RES_BOX ) )
188  {
189  pBrd = pItem->GetRight();
190  if( pBrd )
191  {
192  aBPara.SetBorder( *pBrd );
193  const SwTableBox* pNextBox = rBoxes[n+1];
194  if( lcl_GCBorder_ChkBoxBrd_B( pNextBox, &aBPara ) &&
195  aBPara.IsAnyBorderFound() )
196  {
197  SvxBoxItem aBox( *pItem );
198  aBox.SetLine( nullptr, SvxBoxItemLine::RIGHT );
199  if( pGCPara->pShareFormats )
200  pGCPara->pShareFormats->SetAttr( *pBox, aBox );
201  else
202  pBox->ClaimFrameFormat()->SetFormatAttr( aBox );
203  }
204  }
205  }
206  }
207 
208  aBoxes.clear();
209  }
210  }
211 
212  // And now the own bottom edge with the succeeding top edge
213  if( !pGCPara->IsLastLine() )
214  {
215  SwCollectTableLineBoxes aBottom( false );
216  SwCollectTableLineBoxes aTop( true );
217 
218  sw_Line_CollectBox( pLine, &aBottom );
219 
220  const SwTableLine* pNextLine = (*pGCPara->pLines)[ pGCPara->nLinePos+1 ];
221  sw_Line_CollectBox( pNextLine, &aTop );
222 
223  // remove all "duplicated" Lines that are the same
224  sal_uInt16 nBtmPos, nTopPos;
225 
226  size_t nSttBtm {0};
227  size_t nSttTop {0};
228  const size_t nEndBtm {aBottom.Count()};
229  const size_t nEndTop {aTop.Count()};
230 
231  const SwTableBox *pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
232  const SwTableBox *pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
233  const SvxBoxItem *pBtmItem = nullptr, *pTopItem = nullptr;
234  const SvxBorderLine *pBtmLine(nullptr), *pTopLine(nullptr);
235  bool bGetTopItem = true, bGetBtmItem = true;
236 
237  do {
238  if( bGetBtmItem )
239  pBtmLine = lcl_GCBorder_GetBorder( *pBtmBox, false, &pBtmItem );
240  if( bGetTopItem )
241  pTopLine = lcl_GCBorder_GetBorder( *pTopBox, true, &pTopItem );
242 
243  if( pTopLine && pBtmLine && *pTopLine == *pBtmLine )
244  {
245  // We can remove one, but which one?
246  const size_t nSavSttBtm {nSttBtm};
247  const size_t nSavSttTop {nSttTop};
248  sal_uInt16 nBtmEndPos = ::lcl_FindEndPosOfBorder( aBottom,
249  *pTopLine, nSttBtm, false );
250  if( !nBtmEndPos ) nBtmEndPos = nBtmPos;
251  sal_uInt16 nTopEndPos = ::lcl_FindEndPosOfBorder( aTop,
252  *pTopLine, nSttTop, true );
253  if( !nTopEndPos ) nTopEndPos = nTopPos;
254 
255  if( nTopEndPos <= nBtmEndPos )
256  {
257  // Delete the TopBorders until BottomEndPos
258  nSttTop = nSavSttTop;
259  if( nTopPos <= nBtmEndPos )
260  lcl_GCBorder_DelBorder( aTop, --nSttTop, true,
261  *pBtmLine, pTopItem, nBtmEndPos,
262  pGCPara->pShareFormats );
263  else
264  nSttBtm = nSavSttBtm;
265  }
266  else
267  {
268  // Else delete the BottomBorders until TopEndPos
269  nSttBtm = nSavSttBtm;
270  if( nBtmPos <= nTopEndPos )
271  lcl_GCBorder_DelBorder( aBottom, --nSttBtm, false,
272  *pTopLine, pBtmItem, nTopEndPos,
273  pGCPara->pShareFormats );
274  else
275  nSttTop = nSavSttTop;
276  }
277  nTopPos = nBtmPos;
278  }
279 
280  if( nTopPos == nBtmPos )
281  {
282  if( nSttBtm >= nEndBtm || nSttTop >= nEndTop )
283  break;
284 
285  pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
286  pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
287  bGetTopItem = bGetBtmItem = true;
288  }
289  else if( nTopPos < nBtmPos )
290  {
291  if( nSttTop >= nEndTop )
292  break;
293  pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
294  bGetTopItem = true;
295  bGetBtmItem = false;
296  }
297  else
298  {
299  if( nSttBtm >= nEndBtm )
300  break;
301  pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
302  bGetTopItem = false;
303  bGetBtmItem = true;
304  }
305 
306  } while( true );
307  }
308 
309  for( const auto& rpBox : pLine->GetTabBoxes() )
310  lcl_GC_Box_Border(rpBox, pGCPara );
311 
312  ++pGCPara->nLinePos;
313 }
314 
315 static void lcl_GC_Box_Border( const SwTableBox* pBox, SwGCLineBorder* pPara )
316 {
317  if( !pBox->GetTabLines().empty() )
318  {
319  SwGCLineBorder aPara( *pBox );
320  aPara.pShareFormats = pPara->pShareFormats;
321  for( const SwTableLine* pLine : pBox->GetTabLines() )
322  sw_GC_Line_Border( pLine, &aPara );
323  }
324 }
325 
326 namespace {
327 
328 struct GCLinePara
329 {
330  SwTableLines* pLns;
331  SwShareBoxFormats* pShareFormats;
332 
333  GCLinePara( SwTableLines& rLns, GCLinePara* pPara = nullptr )
334  : pLns( &rLns ), pShareFormats( pPara ? pPara->pShareFormats : nullptr )
335  {}
336 };
337 
338 }
339 
340 static bool lcl_MergeGCLine(SwTableLine* pLine, GCLinePara* pPara);
341 
342 static bool lcl_MergeGCBox(SwTableBox* pTableBox, GCLinePara* pPara)
343 {
344  if( !pTableBox->GetTabLines().empty() )
345  {
346  // ATTENTION: The Line count can change!
347  GCLinePara aPara( pTableBox->GetTabLines(), pPara );
348  for( SwTableLines::size_type n = 0;
349  n < pTableBox->GetTabLines().size() && lcl_MergeGCLine( pTableBox->GetTabLines()[n], &aPara );
350  ++n )
351  ;
352 
353  if( 1 == pTableBox->GetTabLines().size() )
354  {
355  // we have a box with a single line, so we just replace it by the line's boxes
356  SwTableLine* pInsLine = pTableBox->GetUpper();
357  SwTableLine* pCpyLine = pTableBox->GetTabLines()[0];
358  SwTableBoxes::iterator it = std::find( pInsLine->GetTabBoxes().begin(), pInsLine->GetTabBoxes().end(), pTableBox );
359  for( auto pTabBox : pCpyLine->GetTabBoxes() )
360  pTabBox->SetUpper( pInsLine );
361 
362  SfxPoolItem const* pRowBrush(nullptr);
363  pCpyLine->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pRowBrush);
364  if (pRowBrush)
365  {
366  for (auto pBox : pCpyLine->GetTabBoxes())
367  {
368  if (pBox->GetFrameFormat()->GetItemState(RES_BACKGROUND) != SfxItemState::SET)
369  { // set inner row background on inner cell
370  pBox->ClaimFrameFormat();
371  pBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
372  }
373  }
374  }
375 
376  // remove the old box from its parent line
377  it = pInsLine->GetTabBoxes().erase( it );
378  // insert the nested line's boxes in its place
379  pInsLine->GetTabBoxes().insert( it, pCpyLine->GetTabBoxes().begin(), pCpyLine->GetTabBoxes().end());
380  pCpyLine->GetTabBoxes().clear();
381  // destroy the removed box
382  delete pTableBox;
383 
384  return false; // set up anew
385  }
386  }
387  return true;
388 }
389 
390 static bool lcl_MergeGCLine(SwTableLine* pLn, GCLinePara* pGCPara)
391 {
392  SwTableBoxes::size_type nBoxes = pLn->GetTabBoxes().size();
393  if( nBoxes )
394  {
395  while( 1 == nBoxes )
396  {
397  // We have a Box with Lines
398  SwTableBox* pBox = pLn->GetTabBoxes().front();
399  if( pBox->GetTabLines().empty() )
400  break;
401 
402  SwTableLine* pLine = pBox->GetTabLines()[0];
403 
404  // pLine turns into the current Line (that is rpLine), the rest is moved
405  // into the LinesArray past the current one.
406  // The LinesArray is in pPara!
407  SwTableLines::size_type nLines = pBox->GetTabLines().size();
408 
409  SwTableLines& rLns = *pGCPara->pLns;
410  sal_uInt16 nInsPos = rLns.GetPos( pLn );
411  OSL_ENSURE( USHRT_MAX != nInsPos, "Could not find Line!" );
412 
413  SwTableBox* pUpper = pLn->GetUpper();
414 
415  rLns.erase( rLns.begin() + nInsPos ); // remove the Line from the array
416  rLns.insert( rLns.begin() + nInsPos, pBox->GetTabLines().begin(), pBox->GetTabLines().end() );
417 
418  // JP 31.03.99: Bug 60000
419  // Pass the attributes of the to-be-deleted Lines to the "inserted" one
420  const SfxPoolItem* pItem;
421  if( SfxItemState::SET == pLn->GetFrameFormat()->GetItemState(
422  RES_BACKGROUND, true, &pItem ))
423  {
424  SwTableLines& rBoxLns = pBox->GetTabLines();
425  for( auto pBoxLine : rBoxLns )
426  if( SfxItemState::SET != pBoxLine->GetFrameFormat()->
427  GetItemState( RES_BACKGROUND ))
428  pGCPara->pShareFormats->SetAttr( *pBoxLine, *pItem );
429  }
430 
431  pBox->GetTabLines().erase( pBox->GetTabLines().begin(), pBox->GetTabLines().begin() + nLines ); // Remove Lines from the array
432 
433  delete pLn;
434 
435  // Set the dependency anew
436  while( nLines-- )
437  rLns[ nInsPos++ ]->SetUpper( pUpper );
438 
439  pLn = pLine; // and set up anew
440  nBoxes = pLn->GetTabBoxes().size();
441  }
442 
443  // ATTENTION: The number of boxes can change!
444  for( SwTableBoxes::size_type nLen = 0; nLen < pLn->GetTabBoxes().size(); ++nLen )
445  if( !lcl_MergeGCBox( pLn->GetTabBoxes()[nLen], pGCPara ))
446  --nLen;
447  }
448  return true;
449 }
450 
451 // Clean structure a bit
453 {
454  // ATTENTION: The Line count can change!
455  GCLinePara aPara( GetTabLines() );
456  SwShareBoxFormats aShareFormats;
457  aPara.pShareFormats = &aShareFormats;
458  for( SwTableLines::size_type n = 0; n < GetTabLines().size() &&
459  lcl_MergeGCLine( GetTabLines()[n], &aPara ); ++n )
460  ;
461 }
462 
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< SwTableLine * >::size_type size_type
Definition: swtable.hxx:68
static void lcl_GC_Box_Border(const SwTableBox *pBox, SwGCLineBorder *pPara)
Definition: gctable.cxx:315
static bool lcl_MergeGCBox(SwTableBox *pTableBox, GCLinePara *pPara)
Definition: gctable.cxx:342
static sal_uInt16 lcl_FindEndPosOfBorder(const SwCollectTableLineBoxes &rCollTLB, const SvxBorderLine &rBrdLn, size_t &rStt, bool bTop)
Definition: gctable.cxx:96
sal_Int64 n
SwTableLine is one table row in the document model.
Definition: swtable.hxx:357
sal_uInt16 nLinePos
Definition: tblrwcl.hxx:121
iterator begin()
Definition: swtable.hxx:77
static void lcl_GCBorder_DelBorder(const SwCollectTableLineBoxes &rCollTLB, size_t &rStt, bool bTop, const SvxBorderLine &rLine, const SvxBoxItem *pItem, sal_uInt16 nEndPos, SwShareBoxFormats *pShareFormats)
Definition: gctable.cxx:126
const SwTableLines * pLines
Definition: tblrwcl.hxx:119
size_type size() const
Definition: swtable.hxx:76
SwShareBoxFormats * pShareFormats
Definition: tblrwcl.hxx:120
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Templatized version of GetItemState() to directly return the correct type.
Definition: format.hxx:111
static void lcl_GCBorder_GetLastBox_L(const SwTableLine *pLine, SwTableBoxes *pPara)
Definition: gctable.cxx:76
static const SvxBorderLine * GetLineTB(const SvxBoxItem *pBox, bool bTop)
Definition: gctable.cxx:29
iterator insert(iterator aIt, SwTableLine *pLine)
Definition: swtable.hxx:86
bool IsLastLine() const
Definition: tblrwcl.hxx:128
Class for SplitTable Collects the uppermost or lowermost Lines of a Box from a Line in an array...
Definition: tblrwcl.hxx:60
const editeng::SvxBorderLine * GetTop() const
Style of a layout element.
Definition: frmfmt.hxx:59
int i
bool empty() const
Definition: swtable.hxx:75
const SwTableBox & GetBox(std::size_t nPos, sal_uInt16 *pWidth=nullptr) const
Definition: tblrwcl.hxx:83
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:380
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:386
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:457
SwTableLines & GetTabLines()
Definition: swtable.hxx:201
SwTableLines & GetTabLines()
Definition: swtable.hxx:450
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:448
bool sw_Line_CollectBox(const SwTableLine *&rpLine, void *pPara)
Definition: ndtbl.cxx:2989
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:368
size_t Count() const
Definition: tblrwcl.hxx:82
static bool lcl_MergeGCLine(SwTableLine *pLine, GCLinePara *pPara)
Definition: gctable.cxx:390
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:471
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(105)
void GCLines()
Definition: gctable.cxx:452
static bool lcl_GCBorder_ChkBoxBrd_B(const SwTableBox *pBox, SwGCBorder_BoxBrd *pPara)
Definition: gctable.cxx:57
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:418
void SetAttr(SwTableBox &rBox, const SfxPoolItem &rItem)
Definition: tblrwcl.cxx:3311
bool CheckLeftBorderOfFormat(const SwFrameFormat &rFormat)
Check whether the left Border is the same as the set one.
Definition: gctable.cxx:34
static void lcl_GCBorder_GetLastBox_B(const SwTableBox *pBox, SwTableBoxes *pPara)
Definition: gctable.cxx:83
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1903
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
const editeng::SvxBorderLine * m_pBorderLine
Definition: tblrwcl.hxx:133
SwTableBox * GetUpper()
Definition: swtable.hxx:376
void sw_GC_Line_Border(const SwTableLine *pLine, SwGCLineBorder *pGCPara)
Definition: gctable.cxx:166
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:98
iterator end()
Definition: swtable.hxx:79
bool IsAnyBorderFound() const
Definition: tblrwcl.hxx:147
static const SvxBorderLine * lcl_GCBorder_GetBorder(const SwTableBox &rBox, bool bTop, const SvxBoxItem **ppItem)
Definition: gctable.cxx:116
SwTableLine * GetUpper()
Definition: swtable.hxx:453
void SetBorder(const editeng::SvxBorderLine &rBorderLine)
Definition: tblrwcl.hxx:138
const editeng::SvxBorderLine * GetBottom() const
static bool lcl_GCBorder_ChkBoxBrd_L(const SwTableLine *pLine, SwGCBorder_BoxBrd *pPara)
Definition: gctable.cxx:51
sal_uInt16 nPos
iterator erase(iterator aIt)
Definition: swtable.hxx:84
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)