2014-12-13 12:56:31 -06:00
// 13 december 2014
// damn winsock
static void doselect ( struct table * t , intptr_t row , intptr_t column )
{
2014-12-14 09:22:15 -06:00
RECT r , client ;
intptr_t oldrow ;
2014-12-14 16:10:08 -06:00
LONG width , height ;
2014-12-14 10:09:59 -06:00
struct rowcol rc ;
BOOL dovscroll ;
2014-12-14 16:10:08 -06:00
intptr_t i ;
intptr_t xpos ;
LONG clientWidth ;
2014-12-14 09:22:15 -06:00
oldrow = t - > selectedRow ;
2014-12-13 12:56:31 -06:00
t - > selectedRow = row ;
t - > selectedColumn = column ;
2014-12-14 09:22:15 -06:00
if ( GetClientRect ( t - > hwnd , & client ) = = 0 )
panic ( " error getting Table client rect in doselect() " ) ;
client . top + = t - > headerHeight ;
height = rowht ( t ) ;
2014-12-14 10:09:59 -06:00
// first vertically scroll to the new row to make it fully visible (or as visible as possible)
if ( t - > selectedRow < t - > vscrollpos )
vscrollto ( t , t - > selectedRow ) ;
else {
rc . row = t - > selectedRow ;
rc . column = t - > selectedColumn ;
// first assume entirely outside the client area
dovscroll = TRUE ;
if ( rowColumnToClientRect ( t , rc , & r ) )
// partially outside the client area?
if ( r . bottom < = client . bottom ) // <= here since we are comparing bottoms (which are the first pixels outside the rectangle)
dovscroll = FALSE ;
if ( dovscroll )
vscrollto ( t , t - > selectedRow - t - > vpagesize + 1 ) ; // + 1 because apparently just t->selectedRow - t->vpagesize results in no scrolling (t->selectedRow - t->vpagesize == t->vscrollpos)...
}
2014-12-14 16:10:08 -06:00
// now see if the cell we want is to the left of offscreen, in which case scroll to its x-position
xpos = 0 ;
for ( i = 0 ; i < t - > selectedColumn ; i + + )
xpos + = columnWidth ( t , i ) ;
if ( xpos < t - > hscrollpos )
hscrollto ( t , xpos ) ;
else while ( 1 ) { break ;
// if the full cell is not visible, scroll to the right just enough to make it fully visible (or as visible as possible)
width = columnWidth ( t , t - > selectedColumn ) ;
clientWidth = client . right - client . left ;
if ( xpos + width < t - > hscrollpos + clientWidth )
// if the column is too wide, then just make it occupy the whole visible area (left-aligned)
if ( width > clientWidth )
hscrollto ( t , xpos ) ;
else
hscrollby ( t , clientWidth - width ) ;
}
2014-12-14 10:09:59 -06:00
// now redraw the old and new /rows/
// we do this after scrolling so the rectangles to be invalidated make sense
2014-12-14 09:22:15 -06:00
r . left = client . left ;
r . right = client . right ;
if ( oldrow ! = - 1 & & oldrow > = t - > vscrollpos ) {
r . top = client . top + ( ( oldrow - t - > vscrollpos ) * height ) ;
r . bottom = r . top + height ;
if ( InvalidateRect ( t - > hwnd , & r , TRUE ) = = 0 )
panic ( " error queueing previously selected row for redraw in doselect() " ) ;
}
// t->selectedRow must be visible by this point; we scrolled to it
if ( t - > selectedRow ! = - 1 & & t - > selectedRow ! = oldrow ) {
r . top = client . top + ( ( t - > selectedRow - t - > vscrollpos ) * height ) ;
r . bottom = r . top + height ;
if ( InvalidateRect ( t - > hwnd , & r , TRUE ) = = 0 )
panic ( " error queueing newly selected row for redraw in doselect() " ) ;
}
2014-12-13 12:56:31 -06:00
}
// TODO which WM_xBUTTONDOWNs?
HANDLER ( mouseDownSelectHandler )
{
struct rowcol rc ;
rc = lParamToRowColumn ( t , lParam ) ;
// don't check if lParamToRowColumn() returned row -1 or column -1; we want deselection behavior
doselect ( t , rc . row , rc . column ) ;
* lResult = 0 ;
return TRUE ;
}