DbGridControl's confusion of BrowseBox's column number vs. column ID
Stephan Bergmann
sbergman at redhat.com
Fri Mar 10 12:52:36 UTC 2017
svtools' BrowseBox class (include/svtools/brwbox.hxx; effectively a
collection of BrowseColumn via the BrowseBox::pCols member) apparently
distinguishes between a column's index/position/number (i.e., the
BrowseColumn's position within the BrowseBox::pCols vector) and its ID
(i.e., the BrowseColumn::_nId member, svtools/source/brwbox/datwin.hxx).
Columns are inserted into a BrowseBox with (both in
svtools/source/brwbox/brwbox1.cxx:) BrowseBox::InsertHandleColumn
(inserting a "handle" column at position 0 with ID 0) and
BrowseBox::InsertDataColumn (inserting a "data" column with a given
nItemId somewhere in the collection).
Historically both column numbers and column IDs have been represented
with unsigned 16-bit integers (both sal_uInt16, by now), which doesn't
necessarily help in avoiding confusion between the two concepts. (And
indeed e.g. BROWSER_INVALIDID = SAL_MAX_UNIT16 appears to be used to
represent both "no column ID", BrowseBox::GetColumnId,
svtools/source/brwbox/brwbox2.cxx, and "no column number",
BrowseBox::GetColumnAtXPosPixel, svtools/source/brwbox/brwbox1.cxx).
Now, BrowseBox::GetColumnAtXPosPixel (svtools/source/brwbox/brwbox1.cxx)
apparently always returned a column number (from
<https://cgit.freedesktop.org/libreoffice/core/commit/?id=8ab086b6cc054501bfbf7ef6fa509c393691e860>
"initial import"),
> USHORT BrowseBox::GetColumnAtXPosPixel( long nX, BOOL ) const
> {
> DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
>
> // accumulate the withds of the visible columns
> long nColX = 0;
> USHORT nCol;
> for ( nCol = 0; nCol < USHORT(pCols->Count()); ++nCol )
> {
> BrowserColumn *pCol = pCols->GetObject(nCol);
> if ( pCol->IsFrozen() || nCol >= nFirstCol )
> nColX += pCol->Width();
>
> if ( nColX > nX )
> return nCol;
> }
>
> return BROWSER_INVALIDID;
> }
while DbGridControl::GetModelColumnPos (svx/source/fmcomp/gridctrl.cxx)
apparently always expected a column ID as input (from
<http://cgit.freedesktop.org/libreoffice/core/commit/?id=fd069bee7e57ad529c3c0974559fd2d84ec3151a>
"initial import"),
> sal_uInt16 DbGridControl::GetModelColumnPos( sal_uInt16 nId ) const
> {
> for (sal_uInt16 i=0; i<m_aColumns.Count(); ++i)
> if (m_aColumns.GetObject(i)->GetId() == nId)
> return i;
>
> return -1;
> }
But there is two occurrences of code in svx/source/fmcomp/gridctrl.cxx
that feeds the output of GetColumnAtXPosPixel as input into
GetModelColumnPos, i.e., misinterprets a column number as a column ID.
Meanwhile that code lives in DbGridControl::StartDrag,
[...]
> sal_uInt16 nColId = GetColumnAtXPosPixel(rPosPixel.X());
> long nRow = GetRowAtYPosPixel(rPosPixel.Y());
> if (nColId != HandleColumnId && nRow >= 0)
> {
> if (GetDataWindow().IsMouseCaptured())
> GetDataWindow().ReleaseMouse();
>
> size_t Location = GetModelColumnPos( nColId );
[...]
and DbGridControl::Command,
[...]
> sal_uInt16 nColId = GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X());
> long nRow = GetRowAtYPosPixel(rEvt.GetMousePosPixel().Y());
>
> if (nColId == HandleColumnId)
> {
> executeRowContextMenu( nRow, rEvt.GetMousePosPixel() );
> }
> else if (canCopyCellText(nRow, nColId))
> {
> ScopedVclPtrInstance<PopupMenu> aContextMenu(SVX_RES(RID_SVXMNU_CELL));
> aContextMenu->RemoveDisabledEntries(true, true);
> switch (aContextMenu->Execute(this, rEvt.GetMousePosPixel()))
> {
> case SID_COPY:
> copyCellText(nRow, nColId);
[...]
where DbGridControl::copyCellText (svx/source/fmcomp/gridctrl.cxx) calls
GetModelColumnPos,
> void DbGridControl::copyCellText(sal_Int32 _nRow, sal_uInt16 _nColId)
> {
> DBG_ASSERT(canCopyCellText(_nRow, _nColId), "DbGridControl::copyCellText: invalid call!");
> DbGridColumn* pColumn = m_aColumns[ GetModelColumnPos(_nColId) ];
> SeekRow(_nRow);
> OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
> }
Does anybody (Linoel?) known something about that DbGridControl code?
Would this be a bug (if so, any idea how to reproduce it at the GUI?) or
is it maybe an invariant of such a DbGridControl that it's columns' ID
always match the columns' positions?
More information about the LibreOffice
mailing list