1b14ec9415
git-svn-id: svn://10.65.10.50/branches/R_10_00@23236 c028cbd2-c16b-5b4b-a496-9718f37d4682
4900 lines
150 KiB
C
Executable File
4900 lines
150 KiB
C
Executable File
/*******************************************************************************
|
|
* Copyright 1991-1996 by ORCA Software, Inc. *
|
|
* *
|
|
* All rights reserved. May not be reproduced or distributed, in printed or *
|
|
* electronic form, without permission of ORCA Software, Inc. May not be *
|
|
* distributed as object code, separately or linked with other object modules, *
|
|
* without permission. *
|
|
*******************************************************************************/
|
|
|
|
#define XI_INTERNAL
|
|
#include "xi.h"
|
|
#include "xitext.h"
|
|
#include "xilm.h"
|
|
#include "xilmst.h"
|
|
#include "xiutils.h"
|
|
#include "xidisply.h"
|
|
#include <limits.h>
|
|
|
|
static XinDrawTools lm_normal_ctools;
|
|
|
|
#define LM_COL_ATTR(lm, col) (LMP(lm)->lm_column_data[col]->attrib)
|
|
#define LM_REDRAW_COL_ATR (LM_COL_ATR_ENABLED | LM_COL_ATR_RJUST | LM_COL_ATR_PASSWORD | LM_COL_ATR_SELECTED)
|
|
#define LM_REDRAW_ROW_ATR (LM_ROW_ATR_ENABLED | LM_ROW_ATR_SELECTED)
|
|
|
|
#define LM_REDRAW_CELL_ATR (LM_CELL_ATR_SELECTED | LM_CELL_ATR_RJUST | LM_CELL_ATR_HCENTER)
|
|
#define SELECT_CELLS_OFFSET 1
|
|
|
|
typedef struct
|
|
{
|
|
BOOLEAN XinWindowPaintNeeds;
|
|
XinRect rct;
|
|
XinRect prct;
|
|
} ROW_INFO;
|
|
|
|
static XinBrush lm_white_cbrush;
|
|
static XinPen lm_black_cpen;
|
|
static BOOLEAN lm_tools_inited = FALSE;
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_clipped_text
|
|
lmp: current lmp
|
|
s: string
|
|
bound_rctp:
|
|
clip_rctp:
|
|
attrib:
|
|
set_the_cpen:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_clipped_text( LM_DATA * lmp, char *s, XinRect * bound_rctp,
|
|
XinRect * clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen,
|
|
BOOLEAN adj_v )
|
|
{
|
|
XinRect br,
|
|
cr;
|
|
BOOLEAN left,
|
|
right;
|
|
|
|
br = *bound_rctp;
|
|
br.left += lmp->rct.left;
|
|
br.right += lmp->rct.left;
|
|
|
|
if ( adj_v )
|
|
{
|
|
lm_adj_v( lmp, br.top );
|
|
lm_adj_v( lmp, br.bottom );
|
|
}
|
|
|
|
left = lm_adj_h( lmp, &br.left );
|
|
right = lm_adj_h( lmp, &br.right );
|
|
if ( !left && !right )
|
|
return;
|
|
xi_rect_intersect( &cr, &br, clip_rctp );
|
|
xi_draw_clipped_text( lmp->win, lmp->cur_font, s, &br, &cr, attrib,
|
|
set_the_cpen, 0, -1, '\0', 0, NULL );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to draw
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_rect( LM_DATA * lmp, XinRect * rctp, BOOLEAN adj_v )
|
|
{
|
|
XinRect r;
|
|
BOOLEAN leftb,
|
|
rightb;
|
|
|
|
r = *rctp;
|
|
r.left += lmp->rct.left;
|
|
if ( r.right != SHRT_MAX )
|
|
r.right += lmp->rct.left;
|
|
|
|
if ( adj_v )
|
|
{
|
|
lm_adj_v( lmp, r.top );
|
|
lm_adj_v( lmp, r.bottom );
|
|
}
|
|
|
|
leftb = lm_adj_h( lmp, &r.left );
|
|
if ( r.right == SHRT_MAX )
|
|
rightb = TRUE;
|
|
else
|
|
rightb = lm_adj_h( lmp, &r.right );
|
|
if ( !leftb && !rightb )
|
|
return;
|
|
xi_draw_rect( lmp->win, &r );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_icon
|
|
lmp: current lmp
|
|
left: h position
|
|
top: v position
|
|
icon_rid: resource id
|
|
vir_clip: virtual clip rectangle
|
|
phys_rct:
|
|
fore_color: desired colors if icons
|
|
back_color:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_icon( LM_DATA * lmp, int left, int top, int icon_rid, XI_BITMAP * bitmap,
|
|
XinRect * vir_clip, XinRect * phys_rct, BOOLEAN adj_v,
|
|
XinColor fore_color, XinColor back_color )
|
|
{
|
|
XinRect crct,
|
|
r;
|
|
short sleft;
|
|
BOOLEAN leftb,
|
|
rightb;
|
|
|
|
left += lmp->rct.left;
|
|
r = *phys_rct;
|
|
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
if ( adj_v )
|
|
{
|
|
lm_adj_v( lmp, r.top );
|
|
lm_adj_v( lmp, r.bottom );
|
|
}
|
|
|
|
leftb = lm_adj_h( lmp, &r.left );
|
|
rightb = lm_adj_h( lmp, &r.right );
|
|
if ( !leftb && !rightb )
|
|
return;
|
|
if ( adj_v )
|
|
lm_adj_v( lmp, top );
|
|
if ( xi_rect_intersect( &crct, &r, vir_clip ) )
|
|
{
|
|
xi_set_clip( lmp->win, &crct );
|
|
sleft = left;
|
|
if ( lm_adj_h( lmp, &sleft ) )
|
|
{
|
|
if ( bitmap != NULL )
|
|
xi_bitmap_draw( bitmap, lmp->win, &r, &crct, FALSE );
|
|
else
|
|
xi_draw_icon( lmp->win, sleft, top, icon_rid, fore_color, back_color );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_3d_rect
|
|
lmp: current lmp
|
|
rctp: rectangle
|
|
well: or platform
|
|
depth: in pixels
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_3d_rect( LM_DATA * lmp, XinRect * rctp, BOOLEAN well, int depth, BOOLEAN adj_v )
|
|
{
|
|
XinRect r;
|
|
BOOLEAN left, right;
|
|
const XinColor color_light = aga_get_pref(AGA_PREF_BTN_COLOR_LIGHT);
|
|
const XinColor color_ctrl = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL);
|
|
const XinColor color_dark = aga_get_pref(AGA_PREF_BTN_COLOR_DARK);
|
|
|
|
r = *rctp;
|
|
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
if ( adj_v )
|
|
{
|
|
lm_adj_v( lmp, r.top );
|
|
lm_adj_v( lmp, r.bottom );
|
|
}
|
|
|
|
left = lm_adj_h( lmp, &r.left );
|
|
right = lm_adj_h( lmp, &r.right );
|
|
if ( !left && !right )
|
|
return;
|
|
|
|
if ( xi_get_pref( XI_PREF_3D_LOOK ) )
|
|
xi_draw_shaded_rect( lmp->win, &r, well, depth, color_light, color_ctrl, color_dark);
|
|
else
|
|
xi_draw_3d_rect( lmp->win, &r, well, depth, color_light, color_ctrl, color_dark);
|
|
}
|
|
|
|
/*********** draw column headings ***********/
|
|
static void
|
|
draw_column_headings( LM_DATA * lmp, XinRect * actual_rct )
|
|
{
|
|
XinWindow win = lmp->win;
|
|
LM lm = ( LM ) lmp;
|
|
XinRect clip_rct;
|
|
|
|
clip_rct = *actual_rct;
|
|
if ( !lmp->update_cells_only )
|
|
{
|
|
if ( !( lmp->update_rows_at_top + lmp->update_rows_at_bottom ) )
|
|
{
|
|
if ( !lmp->no_heading )
|
|
{
|
|
int col;
|
|
|
|
if ( lmp->nbr_columns == 0 )
|
|
{
|
|
XinRect hr;
|
|
XinBrush cb;
|
|
|
|
hr.top = lmp->pix_top + BORDER_WIDTH;
|
|
hr.bottom = lmp->pix_hdr_bottom + BORDER_WIDTH;
|
|
hr.left = lmp->rct.left;
|
|
hr.right = lmp->rct.right;
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
cb = white_cbrush;
|
|
cb.fore_color = lmp->white_space_color;
|
|
XinWindowBrushSet( win, &cb );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
xi_set_clip( win, actual_rct );
|
|
xi_draw_rect( win, &hr );
|
|
}
|
|
for ( col = 0; col < lmp->nbr_columns; col++ )
|
|
{
|
|
XinRect heading_rct,
|
|
cell_rct;
|
|
LM_COLUMN_DATA *col_data;
|
|
unsigned long attrib;
|
|
|
|
col_data = lmp->lm_column_data[col];
|
|
if ( col_data->suppress_update_heading )
|
|
continue;
|
|
|
|
lm_get_cell_rect( &heading_rct, lm, 1, col, FALSE, FALSE );
|
|
heading_rct.top = lmp->pix_top + BORDER_WIDTH;
|
|
#if XIWS == XIWS_WM
|
|
heading_rct.bottom = lmp->pix_hdr_bottom - VPIX_PER_CH;
|
|
lm_get_cell_rect( &cell_rct, lm, 1, col, TRUE, FALSE );
|
|
cell_rct.top = lmp->rct.top + VPIX_PER_CH;
|
|
#else
|
|
heading_rct.bottom = lmp->pix_hdr_bottom;
|
|
lm_get_cell_rect( &cell_rct, lm, 1, col, TRUE, FALSE );
|
|
cell_rct.top = lmp->rct.top + 2 * BORDER_WIDTH;
|
|
#endif
|
|
cell_rct.bottom = lmp->pix_hdr_bottom;
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
XinWindowBrushSet( win, &white_cbrush );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
xi_set_clip( win, actual_rct );
|
|
if ( col_data->font )
|
|
lmp->cur_font = col_data->font;
|
|
else
|
|
lmp->cur_font = lmp->font;
|
|
|
|
if ( col_data->heading_well || col_data->heading_platform )
|
|
{
|
|
XinColor fore_color,
|
|
back_color;
|
|
|
|
lm_draw_3d_rect( lmp, &heading_rct,
|
|
( BOOLEAN ) ( COLUMN_IS_SELECTED( lm, col )
|
|
|| COLUMN_IS_PUSHED( lm, col ) ?
|
|
!col_data->heading_well :
|
|
col_data->heading_well ),
|
|
2, FALSE );
|
|
/* Adjust for exact drawable area */
|
|
cell_rct.left++;
|
|
cell_rct.right--;
|
|
cell_rct.top++;
|
|
cell_rct.bottom = heading_rct.bottom - 2 + BORDER_WIDTH;
|
|
/* Reimplemented below 10/05/2012
|
|
if ( COLUMN_IS_ENABLED( lm, col ) )
|
|
{
|
|
if ( LIST_IS_ENABLED( lmp ) )
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->disabled_back_color;
|
|
}
|
|
*/
|
|
if ( col_data->heading_well || col_data->heading_platform ) // Alway true ???
|
|
{
|
|
fore_color = aga_get_pref(AGA_PREF_BTN_COLOR_TEXT);
|
|
back_color = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL);
|
|
}
|
|
XinWindowColorTextForeSet( win, fore_color );
|
|
XinWindowColorTextBackSet( win, back_color );
|
|
}
|
|
else
|
|
{
|
|
XinColor fore_color;
|
|
|
|
if ( COLUMN_IS_ENABLED( lm, col ) )
|
|
{
|
|
if ( LIST_IS_ENABLED( lmp ) )
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
XinWindowColorTextForeSet( win, fore_color );
|
|
XinWindowColorTextBackSet( win, lmp->back_color );
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
XinWindowColorTextForeSet( win, fore_color );
|
|
XinWindowColorTextBackSet( win, lmp->disabled_back_color );
|
|
}
|
|
if ( COLUMN_IS_SELECTED( lm, col ) )
|
|
{
|
|
XinBrush cb;
|
|
|
|
cb = white_cbrush;
|
|
cb.fore_color = fore_color;
|
|
XinWindowBrushSet( win, &cb );
|
|
XinWindowColorTextForeSet( win, XI_COLOR_WHITE );
|
|
}
|
|
lm_draw_rect( lmp, &heading_rct, FALSE );
|
|
/* Adjust for exact drawable area */
|
|
cell_rct.left--;
|
|
cell_rct.right++;
|
|
cell_rct.top--;
|
|
cell_rct.bottom++;
|
|
}
|
|
attrib = ( ( LM_COL_ATTR( lm, col ) | XI_ATR_VISIBLE ) &
|
|
~XI_ATR_PASSWORD ) |
|
|
( lmp->min_heading_height ? XI_ATR_VCENTER : 0 );
|
|
if ( col_data->center_heading )
|
|
{
|
|
attrib |= XI_ATR_HCENTER;
|
|
attrib &= ~XI_ATR_RJUST;
|
|
}
|
|
clip_rct.top = cell_rct.top;
|
|
clip_rct.bottom = cell_rct.bottom;
|
|
if ( col_data->icon_mode == XIM_ICON_HAS_PRIORITY
|
|
|| col_data->icon_mode == XIM_TEXT_AND_BITMAP_OVERLAP )
|
|
{
|
|
if ( col_data->icon_rid || col_data->bitmap != NULL )
|
|
{
|
|
XinColor fore_color,
|
|
back_color;
|
|
|
|
if ( COLUMN_IS_ENABLED( lm, col ) )
|
|
{
|
|
if ( LIST_IS_ENABLED( lmp ) )
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->disabled_back_color;
|
|
}
|
|
if ( col_data->heading_well || col_data->heading_platform )
|
|
back_color = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL);
|
|
{
|
|
XinRect temp_rct = cell_rct;
|
|
|
|
temp_rct.top--;
|
|
temp_rct.left--;
|
|
temp_rct.right++;
|
|
temp_rct.bottom--;
|
|
if ( col_data->heading_well || col_data->heading_platform )
|
|
temp_rct.bottom--;
|
|
clip_rct.top--;
|
|
lm_draw_icon( lmp, temp_rct.left + col_data->icon_x,
|
|
temp_rct.top + col_data->icon_y, col_data->icon_rid,
|
|
col_data->bitmap, &clip_rct, &temp_rct, FALSE,
|
|
fore_color, back_color );
|
|
clip_rct.top++;
|
|
}
|
|
}
|
|
if ( col_data->icon_mode == XIM_TEXT_AND_BITMAP_OVERLAP
|
|
|| ( col_data->icon_rid == 0 && col_data->bitmap == NULL ) )
|
|
{
|
|
char *ch;
|
|
int lines;
|
|
|
|
ch = col_data->heading_text;
|
|
lines = 1;
|
|
while ( *ch != '\0' )
|
|
{
|
|
if ( *ch == '\n' )
|
|
++lines;
|
|
++ch;
|
|
}
|
|
XinWindowTextOpaqueSet( lmp->win, FALSE );
|
|
if ( lines == 1 )
|
|
{
|
|
lm_draw_clipped_text( lmp, col_data->heading_text, &cell_rct,
|
|
&clip_rct,
|
|
attrib, TRUE, FALSE );
|
|
}
|
|
else
|
|
{
|
|
char *s;
|
|
char *first_char;
|
|
char *ch;
|
|
BOOLEAN bk = FALSE;
|
|
int leading,
|
|
ascent,
|
|
descent;
|
|
|
|
s = (char*)XinMemoryAlloc( strlen( col_data->heading_text ) + 1 );
|
|
strcpy( s, col_data->heading_text );
|
|
ch = s;
|
|
first_char = ch;
|
|
XinFontMetricsGet( lmp->cur_font, &leading, &ascent, &descent );
|
|
cell_rct.top +=
|
|
( cell_rct.bottom - cell_rct.top -
|
|
( leading + ascent + descent ) * lines ) / 2;
|
|
cell_rct.bottom = cell_rct.top + leading + ascent + descent;
|
|
while ( TRUE )
|
|
{
|
|
while ( *ch != '\n' && *ch != '\0' )
|
|
++ch;
|
|
if ( *ch == '\0' )
|
|
bk = TRUE;
|
|
*ch = 0;
|
|
lm_draw_clipped_text( lmp, first_char, &cell_rct,
|
|
&clip_rct,
|
|
attrib & ~XI_ATR_VCENTER, TRUE, FALSE );
|
|
if ( bk )
|
|
break;
|
|
cell_rct.top += ( leading + ascent + descent );
|
|
cell_rct.bottom += ( leading + ascent + descent );
|
|
++ch;
|
|
first_char = ch;
|
|
}
|
|
XinMemoryFree( s );
|
|
}
|
|
}
|
|
}
|
|
if ( col_data->icon_mode == XIM_TEXT_WITH_ICON_ON_LEFT
|
|
|| col_data->icon_mode == XIM_TEXT_WITH_ICON_ON_RIGHT )
|
|
{ /* Draw both text and icon, even if the icon is
|
|
* currently zero. */
|
|
XinColor fore_color,
|
|
back_color;
|
|
char *ch;
|
|
int lines;
|
|
short bitmap_width;
|
|
short bitmap_height;
|
|
|
|
if ( col_data->icon_rid || col_data->bitmap != NULL )
|
|
{
|
|
if ( col_data->bitmap != NULL )
|
|
xi_bitmap_size_get( col_data->bitmap, &bitmap_width, &bitmap_height );
|
|
if ( COLUMN_IS_ENABLED( lm, col ) )
|
|
{
|
|
if ( LIST_IS_ENABLED( lmp ) )
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->disabled_back_color;
|
|
}
|
|
if ( col_data->heading_well || col_data->heading_platform )
|
|
back_color = xi_get_pref( XI_PREF_COLOR_CTRL );
|
|
{
|
|
XinRect temp_rct = cell_rct;
|
|
|
|
if ( col_data->icon_mode == XIM_TEXT_WITH_ICON_ON_LEFT )
|
|
{
|
|
temp_rct.left = cell_rct.left - 1;
|
|
if ( col_data->bitmap != NULL )
|
|
temp_rct.right = temp_rct.left + bitmap_width;
|
|
}
|
|
else
|
|
{
|
|
if ( col_data->bitmap != NULL )
|
|
{
|
|
temp_rct.left = cell_rct.right - bitmap_width;
|
|
temp_rct.right = temp_rct.left + bitmap_width;
|
|
}
|
|
else
|
|
temp_rct.left = cell_rct.right - (short)XinMetricGet(XinMetricIconWidth);
|
|
if ( temp_rct.left < cell_rct.left - 1 )
|
|
temp_rct.left = cell_rct.left - 1;
|
|
}
|
|
temp_rct.top--;
|
|
temp_rct.bottom--;
|
|
if ( col_data->heading_well || col_data->heading_platform )
|
|
temp_rct.bottom--;
|
|
clip_rct.top--;
|
|
lm_draw_icon( lmp, temp_rct.left, temp_rct.top, col_data->icon_rid,
|
|
col_data->bitmap, &clip_rct, &temp_rct, FALSE,
|
|
fore_color, back_color );
|
|
clip_rct.top++;
|
|
}
|
|
}
|
|
if ( col_data->icon_mode == XIM_TEXT_WITH_ICON_ON_LEFT )
|
|
{
|
|
if ( col_data->bitmap != NULL )
|
|
cell_rct.left += bitmap_width;
|
|
else
|
|
cell_rct.left += (short)XinMetricGet(XinMetricIconWidth);
|
|
if ( cell_rct.left > cell_rct.right )
|
|
cell_rct.left = cell_rct.right;
|
|
}
|
|
else
|
|
{
|
|
if ( col_data->bitmap != NULL )
|
|
cell_rct.right -= bitmap_width;
|
|
else
|
|
cell_rct.right -= (short)XinMetricGet(XinMetricIconWidth);
|
|
if ( cell_rct.right < cell_rct.left )
|
|
cell_rct.right = cell_rct.left;
|
|
}
|
|
ch = col_data->heading_text;
|
|
lines = 1;
|
|
while ( *ch != '\0' )
|
|
{
|
|
if ( *ch == '\n' )
|
|
++lines;
|
|
++ch;
|
|
}
|
|
XinWindowTextOpaqueSet( lmp->win, FALSE );
|
|
if ( lines == 1 )
|
|
{
|
|
lm_draw_clipped_text( lmp, col_data->heading_text, &cell_rct,
|
|
&clip_rct,
|
|
attrib, TRUE, FALSE );
|
|
}
|
|
else
|
|
{
|
|
char *s;
|
|
char *first_char;
|
|
char *ch;
|
|
BOOLEAN bk = FALSE;
|
|
int leading,
|
|
ascent,
|
|
descent;
|
|
|
|
s = XinMemoryAlloc( strlen( col_data->heading_text ) + 1 );
|
|
strcpy( s, col_data->heading_text );
|
|
ch = s;
|
|
first_char = ch;
|
|
XinFontMetricsGet( lmp->cur_font, &leading, &ascent, &descent );
|
|
cell_rct.top +=
|
|
( cell_rct.bottom - cell_rct.top -
|
|
( leading + ascent + descent ) * lines ) / 2;
|
|
cell_rct.bottom = cell_rct.top + leading + ascent + descent;
|
|
while ( TRUE )
|
|
{
|
|
while ( *ch != '\n' && *ch != '\0' )
|
|
++ch;
|
|
if ( *ch == '\0' )
|
|
bk = TRUE;
|
|
*ch = 0;
|
|
lm_draw_clipped_text( lmp, first_char, &cell_rct,
|
|
&clip_rct,
|
|
attrib & ~XI_ATR_VCENTER, TRUE, FALSE );
|
|
if ( bk )
|
|
break;
|
|
cell_rct.top += ( leading + ascent + descent );
|
|
cell_rct.bottom += ( leading + ascent + descent );
|
|
++ch;
|
|
first_char = ch;
|
|
}
|
|
XinMemoryFree( s );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*********** draw cells ***********/
|
|
static void
|
|
draw_cells( LM_DATA * lmp, BOOLEAN update )
|
|
{
|
|
int first_row;
|
|
int last_row;
|
|
|
|
first_row = lmp->first_fully_vis;
|
|
if ( first_row < 0 )
|
|
first_row = 0;
|
|
last_row = min( lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1 );
|
|
if ( last_row < 0 )
|
|
return;
|
|
draw_cell_range( lmp, first_row, last_row, 0, lmp->nbr_columns - 1, update );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* draw_other_rectangles */
|
|
/*-------------------------------------------------------------------------*/
|
|
static void
|
|
draw_other_rectangles( LM_DATA * lmp, XinRect * actual_rct )
|
|
{
|
|
XinWindow win = lmp->win;
|
|
XinRect lmp_rct,
|
|
vr,
|
|
hr;
|
|
int i,
|
|
actual_r,
|
|
hrule_h;
|
|
XinBrush cbrush;
|
|
XI_LIST_DATA *list_data;
|
|
XI_OBJ *list_obj;
|
|
|
|
lmp_rct = lmp->rct;
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
list_obj = lmp->list_obj;
|
|
list_data = list_obj->v.list;
|
|
hrule_h = actual_r;
|
|
|
|
/*********** Graphical: border at right of last column ***********/
|
|
/*********** Graphical: rectangle around entire list ***********/
|
|
/*********** Graphical: rectangle at bottom of list ***********/
|
|
/* NOTE: GRAPHICAL SYSTEMS ONLY, HERE. CH is in beginning of draw_lm */
|
|
#if XIWS != XIWS_WM
|
|
xi_set_clip( win, actual_rct );
|
|
XinWindowPenSet( win, &black_cpen );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
if ( lmp->pixel_width )
|
|
{
|
|
XinPoint p,
|
|
p2;
|
|
int width;
|
|
|
|
p.h = lmp->rct.right - 1 - lmp->rct.left;
|
|
p.v = lmp_rct.top;
|
|
p2 = p;
|
|
p2.v = min( lmp_rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top );
|
|
width = BORDER_WIDTH;
|
|
XinWindowPenSet( win, &black_cpen );
|
|
if ( !lmp->no_vert_lines && lmp->nbr_columns != 0 )
|
|
{ /* Only draw this line if there are actually
|
|
* columns */
|
|
WIDTHLOOP( i, width )
|
|
{
|
|
lm_move_to( lmp, p, FALSE, TRUE );
|
|
lm_draw_line( lmp, p2, FALSE, TRUE );
|
|
--p.h;
|
|
--p2.h;
|
|
}
|
|
}
|
|
|
|
{
|
|
XinRect r;
|
|
|
|
r = lmp->rct;
|
|
r.left = lmp->rct.right - lmp->rct.left;
|
|
r.right = SHRT_MAX;
|
|
if ( lmp->no_vert_lines )
|
|
r.left -= BORDER_WIDTH;
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
cbrush.pattern = XinBrushSolid;
|
|
cbrush.fore_color = lmp->white_space_color;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
xi_set_clip( win, actual_rct );
|
|
|
|
lm_draw_rect( lmp, &r, FALSE );
|
|
}
|
|
|
|
/* draw border around entire list */
|
|
lmp_rct.right = actual_r;
|
|
{
|
|
XinRect r;
|
|
XinBrush cb;
|
|
|
|
r = lmp->rct;
|
|
if ( list_data->sb_win )
|
|
{
|
|
xi_get_sb_rect( list_obj, &vr );
|
|
/* add one, so that one pixel of the double border will overlap one
|
|
* pixel of the scroll bar. */
|
|
r.right = vr.right + 1;
|
|
}
|
|
else if ( list_data->hsb_win )
|
|
r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
xi_get_hsb_rect( list_obj, &hr );
|
|
r.bottom = hr.bottom + 1;
|
|
XinWindowBrushSet( win, &hollow_cbrush );
|
|
XinWindowPenSet( win, &black_cpen );
|
|
xi_set_clip( win, NULL );
|
|
xi_draw_rect( win, &r );
|
|
xi_inflate_rect( &r, -1 );
|
|
xi_draw_rect( win, &r );
|
|
|
|
cb = white_cbrush;
|
|
cb.fore_color = lmp->white_space_color;
|
|
XinWindowBrushSet( win, &cb );
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
r.left += 1;
|
|
r.top = lmp->rct.bottom;
|
|
r.right -= 1;
|
|
r.bottom -= 1;
|
|
xi_draw_rect( win, &r );
|
|
}
|
|
}
|
|
|
|
/* RGM: Changed this rectangle to stop at the top of the horizontal scroll
|
|
* bar instead of the bottom. The bottom area is drawn just above. Was this
|
|
* rectangle supposed to draw both? If so, it is drawing over the line at the
|
|
* bottom of the list, when there are fixed columns. */
|
|
{ /* rectangle at bottom of list */
|
|
XinRect r;
|
|
XinRect hsb_rect;
|
|
|
|
xi_get_hsb_rect( lmp->list_obj, &hsb_rect );
|
|
cbrush.pattern = XinBrushSolid;
|
|
cbrush.fore_color = lmp->white_space_color;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
r = lmp->mlr;
|
|
r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
r.top = min( r.top, hsb_rect.top );
|
|
r.bottom = hsb_rect.top;
|
|
r.right = lmp->rct.right;
|
|
if ( lmp->pixel_width )
|
|
r.right = lmp->rct.left + lmp->pixel_width + 2;
|
|
xi_draw_rect( win, &r );
|
|
}
|
|
|
|
/* border around entire list */
|
|
if ( !( lmp->update_rows_at_top + lmp->update_rows_at_bottom ) )
|
|
{
|
|
XinWindowPenSet( win, &black_cpen );
|
|
XinWindowBrushSet( win, &hollow_cbrush );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
xi_set_clip( win, NULL );
|
|
lmp_rct = lmp->rct;
|
|
if ( lmp->pixel_width )
|
|
lmp_rct.right = hrule_h;
|
|
WIDTHLOOP( i, BORDER_WIDTH )
|
|
{
|
|
xi_draw_rect( win, &lmp_rct );
|
|
xi_inflate_rect( &lmp_rct, -1 );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#if XIWS == XIWS_WM
|
|
xi_set_clip( win, actual_rct );
|
|
XinWindowPenSet( win, &black_cpen );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
if ( lmp->pixel_width )
|
|
{
|
|
XinRect r;
|
|
XinPoint p1,
|
|
p2;
|
|
|
|
r = lmp->rct;
|
|
r.left = lmp->rct.right - lmp->rct.left + BORDER_WIDTH;
|
|
r.top += BORDER_WIDTH;
|
|
r.right = 9999;
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
cbrush.pat = XinPatternSolid;
|
|
cbrush.color = lmp->white_space_color;
|
|
XinWindowPaintBrushSet( win, &cbrush );
|
|
xi_set_clip( win, actual_rct );
|
|
lm_draw_rect( lmp, &r, FALSE );
|
|
|
|
XinWindowPenSet( win, &black_cpen );
|
|
p1.h = r.left;
|
|
p1.v = lmp->rct.top;
|
|
p2.h = r.left;
|
|
p2.v = r.bottom;
|
|
lm_move_to( lmp, p1, FALSE, TRUE );
|
|
lm_draw_line( lmp, p2, FALSE, TRUE );
|
|
|
|
}
|
|
|
|
{ /* rectangle at bottom of list */
|
|
XinRect r;
|
|
|
|
cbrush.pat = XinPatternSolid;
|
|
cbrush.color = lmp->white_space_color;
|
|
XinWindowPaintBrushSet( win, &cbrush );
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
r = lmp->mlr;
|
|
r.left += BORDER_WIDTH;
|
|
r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
r.right = lmp->rct.right;
|
|
if ( lmp->pixel_width )
|
|
r.right = lmp->rct.left + 2 * lmp->pixel_width;
|
|
if ( r.top < r.bottom )
|
|
xi_draw_rect( win, &r );
|
|
}
|
|
#endif
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
lmp->update_cells_only = FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_size_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
columnp: column, to be filled in
|
|
returns: FALSE if hit test did not fall on place where column could be sized.
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_size_hit_test( LM lm, XinEvent * ep, int *columnp )
|
|
{
|
|
int column,
|
|
temp,
|
|
col_offset;
|
|
LM_DATA *lmp = LMP( lm );
|
|
XinPoint where;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
where = ep->v.mouse.where;
|
|
if ( where.h < 0 )
|
|
return FALSE;
|
|
if ( lmp->pixel_width && ( where.h > ( lmp->pixel_width + lmp->delta_x )
|
|
+ 2 * BORDER_WIDTH ) )
|
|
return FALSE;
|
|
if ( where.v > lmp->pix_top && where.v < lmp->pix_row1_top )
|
|
{
|
|
for ( column = 0; column < lmp->nbr_columns; column++ )
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
if ( column >= lmp->fixed_columns && column < lmp->first_vis )
|
|
continue;
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos +
|
|
col_offset +
|
|
column_data->pix_width;
|
|
if ( where.h >= temp &&
|
|
where.h < temp + col_offset * 2 + RULE_WIDTH_V )
|
|
{
|
|
*columnp = column;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
draw_cell_text( LM_DATA * lmp, LM_CELL_DATA * cell_data, LM_COLUMN_DATA * column_data,
|
|
int row, int col, int col_offset, int leading, int ascent,
|
|
int descent, XinColor fore_color, XinColor back_color, BOOLEAN set_clip )
|
|
{
|
|
XinRect rct;
|
|
unsigned long attrib,
|
|
cell_attrib;
|
|
char *s;
|
|
int len,
|
|
baseline,
|
|
wid;
|
|
XinWindow win = lmp->win;
|
|
|
|
if ( lm_focus_cell_has( lmp, row, col, FALSE ) && !cell_data->button_full_cell )
|
|
return;
|
|
|
|
cell_attrib = cell_data->attrib &
|
|
( XI_ATR_HCENTER | XI_ATR_RJUST );
|
|
attrib = LM_COL_ATTR( lmp, col ) | XI_ATR_VISIBLE |
|
|
( lmp->min_cell_height ? XI_ATR_VCENTER : 0 );
|
|
if ( cell_attrib )
|
|
{
|
|
attrib &= ~( XI_ATR_HCENTER | XI_ATR_RJUST );
|
|
attrib |= cell_attrib;
|
|
}
|
|
if ( cell_data->button_full_cell )
|
|
attrib = attrib | XI_ATR_HCENTER | XI_ATR_VCENTER;
|
|
lm_xi_text_prect_get( lmp, column_data, cell_data, row, col, col_offset, leading,
|
|
ascent, descent, &rct );
|
|
xi_text_prect_set( cell_data->xi_text, &rct );
|
|
if ( column_data->wrap_text )
|
|
{
|
|
XinRect mlr = lmp->mlr;
|
|
|
|
if ( lmp->pixel_width )
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_text_max_lines_to_draw_set( cell_data->xi_text, lmp->max_lines_in_cell );
|
|
xi_text_draw( cell_data->xi_text, fore_color, back_color, FALSE );
|
|
}
|
|
else
|
|
{
|
|
if ( set_clip )
|
|
{
|
|
XinRect mlr = lmp->mlr;
|
|
XinRect cell_rct;
|
|
|
|
if ( lmp->pixel_width )
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
cell_rct = rct;
|
|
if ( cell_data->button_full_cell )
|
|
{
|
|
xi_inflate_rect( &cell_rct, -2 );
|
|
}
|
|
xi_rect_intersect( &cell_rct, &mlr, &cell_rct );
|
|
xi_set_clip( win, &cell_rct );
|
|
}
|
|
s = xi_get_text_string( xi_text_get( cell_data->xi_text ), LM_COL_ATTR( lmp, col ) );
|
|
len = strlen( s );
|
|
#if XIWS == XIWS_WM
|
|
baseline = rct.top + 8;
|
|
#else
|
|
if ( attrib & XI_ATR_VCENTER )
|
|
baseline = rct.top + leading + ascent +
|
|
( rct.bottom - rct.top - leading - ascent - descent ) / 2 - 1;
|
|
else
|
|
baseline = rct.top + leading + ascent;
|
|
#endif
|
|
if ( attrib & XI_ATR_RJUST )
|
|
{
|
|
XinWindowFontMap( win, lmp->cur_font );
|
|
wid = XinFontTextWidthGet( lmp->cur_font, s, -1 );
|
|
xi_draw_text( win, lmp->cur_font, rct.right - wid, baseline, s, len );
|
|
}
|
|
else
|
|
{
|
|
if ( attrib & XI_ATR_HCENTER )
|
|
{
|
|
int x;
|
|
|
|
wid = XinFontTextWidthGet( lmp->cur_font, s, len );
|
|
x = ( rct.left + rct.right ) / 2 - wid / 2;
|
|
if ( x < rct.left )
|
|
x = rct.left;
|
|
xi_draw_text( win, lmp->cur_font, x, baseline, s, len );
|
|
}
|
|
else
|
|
xi_draw_text( win, lmp->cur_font, rct.left, baseline, s, len );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: redraw_cell_button
|
|
lmp: current lmp
|
|
row:
|
|
col: 0
|
|
clip_rct: clip rectangle
|
|
down: if TRUE, then button is depressed
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
redraw_cell_button( LM_DATA * lmp, int row, int col, XinRect * clip_rct,
|
|
BOOLEAN down, BOOLEAN clear_button )
|
|
{
|
|
XinRect r,
|
|
outer_rct,
|
|
col_rct,
|
|
clip_rect;
|
|
int cell_btn_icon_x,
|
|
cell_btn_icon_y;
|
|
LM_CELL_DATA *cell_data;
|
|
BOOLEAN button_on_left;
|
|
BOOLEAN button_full_cell;
|
|
int button_icon_rid;
|
|
LM_COLUMN_DATA *column_data;
|
|
XinPoint p;
|
|
XinDrawTools ct;
|
|
XinRect actual_rct;
|
|
int actual_r;
|
|
|
|
actual_rct = lmp->rct;
|
|
#if XIWS != XIWS_WM
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r - BORDER_WIDTH;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
#endif
|
|
column_data = lmp->lm_column_data[col];
|
|
col_rct.left = column_data->x_pix_pos;
|
|
col_rct.right = col_rct.left + column_data->pix_width +
|
|
2 * ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
col_rct.top = clip_rct->top;
|
|
col_rct.bottom = clip_rct->bottom;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
button_on_left = cell_data->button_on_left;
|
|
button_full_cell = cell_data->button_full_cell;
|
|
button_icon_rid = cell_data->button_icon_rid;
|
|
lm_get_cell_rect( &outer_rct, ( LM ) lmp, row, col, FALSE, FALSE );
|
|
r = outer_rct;
|
|
xi_inflate_rect( &r, 1 );
|
|
if ( !button_full_cell )
|
|
{
|
|
if ( button_on_left )
|
|
{
|
|
r.right = r.left + lmp->pix_row_spacing;
|
|
p.h = r.right - 1;
|
|
}
|
|
else
|
|
{
|
|
r.left = r.right - lmp->pix_row_spacing;
|
|
p.h = r.left;
|
|
}
|
|
}
|
|
XinWindowPenSet( lmp->win, &black_cpen );
|
|
XinWindowDrawModeSet( lmp->win, XinDrawModeCopy );
|
|
clip_rect = col_rct;
|
|
clip_rect.left += lmp->rct.left;
|
|
clip_rect.right += lmp->rct.left;
|
|
|
|
lm_adj_h( lmp, &clip_rect.left );
|
|
lm_adj_h( lmp, &clip_rect.right );
|
|
xi_rect_intersect( &clip_rect, &clip_rect, &lmp->mlr );
|
|
xi_rect_intersect( &clip_rect, &clip_rect, &actual_rct );
|
|
xi_set_clip( lmp->win, &clip_rect );
|
|
if ( clear_button )
|
|
{
|
|
if ( lmp->no_horz_lines )
|
|
{
|
|
/* if there is a button below, then decrement r.bottom */
|
|
int nr;
|
|
LM_CELL_DATA *row_below_cell_data;
|
|
|
|
nr = row;
|
|
row_below_cell_data = &lmp->cell_data[nr + 1][col];
|
|
if ( row < lmp->nbr_realized_rows - 1 &&
|
|
row_below_cell_data->button &&
|
|
row_below_cell_data->button_on_left == lmp->cell_data[nr][col].button_on_left &&
|
|
row_below_cell_data->button_full_cell == lmp->cell_data[nr][col].button_full_cell &&
|
|
( !row_below_cell_data->button_on_focus ) )
|
|
r.bottom--;
|
|
|
|
XinWindowPenSet( lmp->win, &hollow_cpen );
|
|
XinWindowBrushSet( lmp->win, &white_cbrush );
|
|
lm_draw_rect( lmp, &r, TRUE );
|
|
}
|
|
return;
|
|
}
|
|
if ( lmp->no_horz_lines || lmp->no_vert_lines )
|
|
lm_draw_rect( lmp, &r, TRUE );
|
|
else
|
|
{
|
|
p.v = r.top;
|
|
lm_move_to( lmp, p, TRUE, TRUE );
|
|
p.v = r.bottom;
|
|
lm_draw_line( lmp, p, TRUE, TRUE );
|
|
}
|
|
xi_inflate_rect( &r, -1 );
|
|
lm_draw_3d_rect( lmp, &r, down, 2, TRUE );
|
|
xi_inflate_rect( &r, -2 );
|
|
|
|
// Guy was here: le icone vanno centrate nel bottone
|
|
// cell_btn_icon_x = ( int ) xi_get_pref( XI_PREF_CELL_BTN_ICON_X );
|
|
// cell_btn_icon_y = ( int ) xi_get_pref( XI_PREF_CELL_BTN_ICON_Y );
|
|
cell_btn_icon_x = (r.right-r.left - XinMetricGet(XinMetricIconWidth))/2;
|
|
cell_btn_icon_y = (r.bottom-r.top - XinMetricGet(XinMetricIconHeight))/2;
|
|
|
|
r.left = max( r.left, col_rct.left );
|
|
r.right = min( r.right, col_rct.right );
|
|
XinWindowDrawToolsGet( lmp->win, &ct );
|
|
ct.text_fore_color = lmp->enabled_color;
|
|
ct.text_back_color = aga_get_pref( AGA_PREF_BTN_COLOR_CTRL );
|
|
ct.opaque_text = FALSE;
|
|
if ( lmp->row_colors[row] )
|
|
ct.text_fore_color = lmp->row_colors[row];
|
|
if ( cell_data->color )
|
|
ct.text_fore_color = cell_data->color;
|
|
XinWindowDrawToolsSet( lmp->win, &ct );
|
|
if ( !button_full_cell )
|
|
{
|
|
lm_draw_icon( lmp, r.left + cell_btn_icon_x, r.top + cell_btn_icon_y + down,
|
|
button_icon_rid ? button_icon_rid : ( int ) xi_get_pref( XI_PREF_COMBO_ICON ),
|
|
cell_data->button_bitmap, clip_rct, &r, TRUE, XI_COLOR_BLACK,
|
|
aga_get_pref( AGA_PREF_BTN_COLOR_CTRL ) );
|
|
}
|
|
else if ( button_full_cell && ( cell_data->icon_rid || cell_data->bitmap != NULL ) )
|
|
{
|
|
lm_draw_icon( lmp, r.left, r.top, cell_data->icon_rid, cell_data->bitmap,
|
|
clip_rct, &r, TRUE, XI_COLOR_BLACK, aga_get_pref( AGA_PREF_BTN_COLOR_CTRL ) );
|
|
}
|
|
else
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
int col_offset;
|
|
int leading,
|
|
ascent,
|
|
descent;
|
|
|
|
cell_data = &lmp->cell_data[row][col];
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
XinFontMetricsGet( lmp->cur_font, &leading, &ascent, &descent );
|
|
draw_cell_text( lmp, cell_data, column_data,
|
|
row, col, col_offset, leading, ascent,
|
|
descent, 0L, 0L, TRUE );
|
|
if ( lm_focus_cell_has( lmp, row, col, FALSE ) )
|
|
{
|
|
XinRect mlr = lmp->mlr;
|
|
XinRect cell_rct,
|
|
clip_rct,
|
|
text_rct;
|
|
int baseline;
|
|
|
|
if ( lmp->pixel_width )
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
lm_xi_text_prect_get( lmp, column_data, cell_data, row, col, col_offset, leading,
|
|
ascent, descent, &cell_rct );
|
|
xi_rect_intersect( &clip_rct, &mlr, &cell_rct );
|
|
xi_set_clip( lmp->win, &clip_rct );
|
|
#if XIWS == XIWS_WM
|
|
baseline = cell_rct.top + 8;
|
|
#else
|
|
baseline = cell_rct.top + leading + ascent +
|
|
( cell_rct.bottom - cell_rct.top - leading - ascent - descent ) / 2 - 1;
|
|
#endif
|
|
text_rct = cell_rct;
|
|
text_rct.top = baseline - leading - ascent - 2;
|
|
text_rct.top = max( text_rct.top, ( cell_rct.top ) );
|
|
text_rct.bottom = baseline + descent + 2;
|
|
text_rct.bottom = min( text_rct.bottom, ( cell_rct.bottom - 2 ) );
|
|
XinWindowPenSet( lmp->win, &black_cpen );
|
|
XinWindowDrawModeSet( lmp->win, XinDrawModeCopy );
|
|
xi_draw_dotted_rect( lmp->win, &text_rct );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
draw_cell_buttons( LM_DATA * lmp, ROW_INFO * row_info, int first_row, int last_row,
|
|
BOOLEAN in_update_event )
|
|
{
|
|
int col,
|
|
row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
|
|
NOREF( in_update_event );
|
|
/* draw exception rectangles - draw enabled, not selected cells */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinRect mr;
|
|
BOOLEAN button;
|
|
BOOLEAN button_on_focus;
|
|
BOOLEAN button_full_cell;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
mr = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
button = cell_data->button;
|
|
button_on_focus = cell_data->button_on_focus;
|
|
button_full_cell = cell_data->button_full_cell;
|
|
if ( lmp->button_on_cell_focus )
|
|
{
|
|
if ( ( button && !button_on_focus ) ||
|
|
( button && button_full_cell ) ||
|
|
( button && button_on_focus &&
|
|
lm_focus_cell_has( lmp, row, col, FALSE ) ) )
|
|
redraw_cell_button( lmp, row, col, &mr, FALSE, FALSE );
|
|
}
|
|
else
|
|
{
|
|
if ( ( button && !button_on_focus ) ||
|
|
( button && button_full_cell ) ||
|
|
( button && button_on_focus &&
|
|
lm_row_has_focus( lmp, row, FALSE ) ) )
|
|
redraw_cell_button( lmp, row, col, &mr, FALSE, FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_XinWindowPaintNeeds
|
|
lmp: current lmp
|
|
rctp: rectangle to test
|
|
adj_h: adjust h
|
|
adj_v: adjust v
|
|
returns: TRUE if rectangle needs update
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_XinWindowPaintNeeds( LM_DATA * lmp, XinRect * rctp, BOOLEAN adj_h, BOOLEAN adj_v )
|
|
{
|
|
XinRect r;
|
|
|
|
r = *rctp;
|
|
if ( adj_h )
|
|
{
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
}
|
|
|
|
if ( adj_v )
|
|
{
|
|
lm_adj_v( lmp, r.top );
|
|
lm_adj_v( lmp, r.bottom );
|
|
}
|
|
|
|
if ( adj_h )
|
|
{
|
|
BOOLEAN leftb,
|
|
rightb;
|
|
|
|
leftb = lm_adj_h( lmp, &r.left );
|
|
rightb = lm_adj_h( lmp, &r.right );
|
|
if ( !leftb && !rightb )
|
|
return FALSE;
|
|
}
|
|
xi_offset_rect( &r, -lmp->list_obj->itf->v.itf->delta_x,
|
|
-lmp->list_obj->itf->v.itf->delta_y );
|
|
return XinWindowPaintNeeds( lmp->win, &r );
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* calc_col_XinWindowPaintNeeds */
|
|
/* ------------------------------------------------------------------------- */
|
|
static void
|
|
calc_col_XinWindowPaintNeeds( LM_DATA * lmp, int first_col, int last_col,
|
|
BOOLEAN update )
|
|
{
|
|
int col;
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
#if XIWS == XIWS_WM
|
|
NOREF( update );
|
|
#endif
|
|
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
lmp->lm_column_data[col]->XinWindowPaintNeeds = FALSE;
|
|
for ( col = first_col; col <= last_col; ++col )
|
|
{
|
|
XinRect rct;
|
|
BOOLEAN rightb,
|
|
leftb;
|
|
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( column_data->suppress_update_cells )
|
|
continue;
|
|
rct.left = lmp->rct.left + column_data->x_pix_pos;
|
|
rct.right = rct.left + column_data->pix_width +
|
|
2 * ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
rct.top = lmp->rct.top;
|
|
rct.bottom = lmp->rct.bottom;
|
|
column_data->column_rct = rct;
|
|
#if XIWS != XIWS_WM
|
|
leftb = lm_adj_h( lmp, &rct.left );
|
|
rightb = lm_adj_h( lmp, &rct.right );
|
|
column_data->prct = rct;
|
|
if ( !leftb && !rightb )
|
|
column_data->XinWindowPaintNeeds = FALSE;
|
|
else
|
|
{
|
|
if ( update )
|
|
{
|
|
if ( xi_XinWindowPaintNeeds( lmp->win, &column_data->prct ) )
|
|
column_data->XinWindowPaintNeeds = TRUE;
|
|
else
|
|
column_data->XinWindowPaintNeeds = FALSE;
|
|
}
|
|
else
|
|
column_data->XinWindowPaintNeeds = TRUE;
|
|
}
|
|
#else
|
|
leftb = lm_adj_h( lmp, &rct.left );
|
|
rightb = lm_adj_h( lmp, &rct.right );
|
|
column_data->prct = rct;
|
|
if ( !leftb && !rightb )
|
|
column_data->XinWindowPaintNeeds = FALSE;
|
|
else
|
|
column_data->XinWindowPaintNeeds = TRUE;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*********** draw row rules ***********/
|
|
static void
|
|
draw_row_rules( LM_DATA * lmp, int first_row_to_draw, int last_row_to_draw, BOOLEAN update )
|
|
{
|
|
int r2,
|
|
first_row,
|
|
last_row;
|
|
int row,
|
|
actual_r,
|
|
hrule_h,
|
|
col;
|
|
XinPoint p;
|
|
XinRect r;
|
|
XinRect actual_rct = lmp->mlr;
|
|
|
|
#if XIWS != XIWS_WM
|
|
if ( lmp->pixel_width )
|
|
actual_r = actual_rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
#endif
|
|
hrule_h = actual_r;
|
|
xi_set_clip( lmp->win, &actual_rct );
|
|
|
|
if ( lmp->no_horz_lines )
|
|
{
|
|
XinPen back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.fore_color = lmp->back_color;
|
|
XinWindowPenSet( lmp->win, &back_cpen );
|
|
}
|
|
else
|
|
{
|
|
#if XIWS != XIWS_WM
|
|
XinPen back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.fore_color = lmp->rule_color;
|
|
XinWindowPenSet( lmp->win, &back_cpen );
|
|
#else
|
|
XinWindowPenSet( lmp->win, &black_cpen );
|
|
#endif
|
|
}
|
|
r2 = lmp->rct.right - lmp->delta_x;
|
|
r2 = min( r2, hrule_h );
|
|
if ( r2 < hrule_h && lmp->no_vert_lines )
|
|
r2 -= 2;
|
|
|
|
first_row = max( 0, lmp->first_fully_vis - 1 );
|
|
last_row = min( lmp->nbr_realized_rows, lmp->last_fully_vis + 1 );
|
|
|
|
if ( lmp->update_rows_at_top )
|
|
{
|
|
XinRect row_rct;
|
|
int old_last_row = last_row;
|
|
|
|
last_row = min( last_row, first_row + lmp->update_rows_at_top + 1 );
|
|
lm_get_row_rect( &row_rct, ( LM ) lmp, last_row );
|
|
row_rct.bottom = lmp->mlr.bottom - lmp->mlr.top;
|
|
if ( update && lm_XinWindowPaintNeeds( lmp, &row_rct, FALSE, TRUE ) )
|
|
last_row = old_last_row;
|
|
}
|
|
if ( lmp->update_rows_at_bottom )
|
|
{
|
|
XinRect row_rct;
|
|
int old_first_row = first_row;
|
|
|
|
first_row = max( first_row, lmp->last_fully_vis - lmp->update_rows_at_bottom );
|
|
lm_get_row_rect( &row_rct, ( LM ) lmp, first_row );
|
|
row_rct.top = 0;
|
|
if ( update && lm_XinWindowPaintNeeds( lmp, &row_rct, FALSE, TRUE ) )
|
|
first_row = old_first_row;
|
|
}
|
|
|
|
if ( first_row_to_draw != -1 )
|
|
{
|
|
first_row = max( first_row_to_draw - 1, first_row );
|
|
last_row = min( last_row_to_draw + 1, last_row );
|
|
}
|
|
|
|
if ( lmp->no_horz_lines && !lmp->no_vert_lines )
|
|
{ /* Draw between the vertical lines */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
if ( !lmp->lm_column_data[col]->suppress_update_cells )
|
|
{
|
|
lm_get_rect( ( LM ) lmp, LM_COLUMN, col, &r );
|
|
if ( lmp->pixel_width != 0 && r.left > lmp->pixel_width )
|
|
break;
|
|
for ( row = first_row; row < last_row; row++ )
|
|
{
|
|
p.h = r.left;
|
|
p.v = lmp->pix_offsets[row] + lmp->pix_heights[row] - 1;
|
|
lm_move_to( lmp, p, TRUE, FALSE );
|
|
p.h = r.right;
|
|
lm_draw_line( lmp, p, TRUE, FALSE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ /* Draw single lines all the way across the
|
|
* list */
|
|
r = lmp->rct;
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
if ( !lmp->lm_column_data[col]->suppress_update_cells )
|
|
break;
|
|
if ( col )
|
|
r.left = lmp->lm_column_data[col]->x_pix_pos;
|
|
|
|
for ( row = first_row; row < last_row; ++row )
|
|
{
|
|
p.h = r.left;
|
|
p.v = lmp->pix_offsets[row] + lmp->pix_heights[row] - 1;
|
|
lm_move_to( lmp, p, TRUE, FALSE );
|
|
p.h = r2;
|
|
lm_draw_line( lmp, p, TRUE, FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
draw_background_rects( LM_DATA * lmp, XinWindow win, ROW_INFO * row_info,
|
|
int first_row, int last_row )
|
|
{
|
|
XinColor last_brush_color;
|
|
int col,
|
|
row;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
extern XinPen hollow_cpen;
|
|
BOOLEAN list_has_focus;
|
|
|
|
list_has_focus = lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
|
|
/* draw exception rectangles - draw enabled, not selected cells */
|
|
last_brush_color = 0xFFFFFFFFL; /* this is a value that will never be
|
|
* used for an actual color, so that
|
|
* the background color will be set
|
|
* properly the first time through */
|
|
XinWindowPenSet( win, &hollow_cpen );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinColor brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
BOOLEAN do_draw;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( list_has_focus && !v_scrolled && col == focus_column && row == focus_row )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
do_draw = lm_focus_cell_has( lmp, row, col, FALSE );
|
|
if ( ( CELL_IS_ENABLED( lmp, row, col ) ) && !( CELL_IS_SELECTED( lmp, row, col ) ) )
|
|
do_draw = TRUE;
|
|
if ( do_draw )
|
|
{
|
|
XinRect rct;
|
|
|
|
brush_color = lmp->back_color;
|
|
if ( cell_data->back_color )
|
|
brush_color = cell_data->back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if ( brush_color != last_brush_color )
|
|
{
|
|
XinBrush cbrush;
|
|
|
|
cbrush.fore_color = brush_color;
|
|
cbrush.pattern = XinBrushSolid;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect( win, &rct );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw exception rectangles - draw disabled, not selected cells */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinColor brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( list_has_focus && !v_scrolled && col == focus_column && row == focus_row )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( !( CELL_IS_ENABLED( lmp, row, col ) ) && !( CELL_IS_SELECTED( lmp, row, col ) ) )
|
|
{
|
|
XinRect rct;
|
|
|
|
brush_color = lmp->disabled_back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if ( brush_color != last_brush_color )
|
|
{
|
|
XinBrush cbrush;
|
|
|
|
cbrush.fore_color = brush_color;
|
|
cbrush.pattern = XinBrushSolid;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect( win, &rct );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw exception rectangles - draw selected cells */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinColor brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( list_has_focus && !v_scrolled && col == focus_column && row == focus_row )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( CELL_IS_SELECTED( lmp, row, col ) && !lm_focus_cell_has( lmp, row, col, FALSE ) )
|
|
{
|
|
XinRect rct;
|
|
|
|
if ( CELL_IS_ENABLED( lmp, row, col ) )
|
|
{
|
|
brush_color = lmp->enabled_color;
|
|
if ( lmp->row_colors[row] )
|
|
brush_color = lmp->row_colors[row];
|
|
if ( cell_data->color )
|
|
brush_color = cell_data->color;
|
|
}
|
|
else
|
|
brush_color = lmp->disabled_color;
|
|
if ( cell_data->back_color && lmp->retain_back_color_on_select )
|
|
brush_color = cell_data->back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if ( brush_color != last_brush_color )
|
|
{
|
|
XinBrush cbrush;
|
|
|
|
cbrush.fore_color = brush_color;
|
|
cbrush.pattern = XinBrushSolid;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect( win, &rct );
|
|
}
|
|
}
|
|
}
|
|
|
|
#if XIWS != XIWS_WM
|
|
/* draw 3d rectangles */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinRect rct;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( list_has_focus && !v_scrolled && col == focus_column && row == focus_row )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
if ( column_data->column_well || column_data->column_platform )
|
|
{
|
|
const XinColor color_light = aga_get_pref(AGA_PREF_BTN_COLOR_LIGHT);
|
|
const XinColor color_ctrl = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL);
|
|
const XinColor color_dark = aga_get_pref(AGA_PREF_BTN_COLOR_DARK);
|
|
|
|
if ( xi_get_pref( XI_PREF_3D_LOOK ) )
|
|
xi_draw_shaded_rect( win, &rct, ( BOOLEAN ) ( CELL_IS_SELECTED( lmp, row, col ) ? !column_data->column_well :
|
|
column_data->column_well ), 2, color_light, color_ctrl, color_dark );
|
|
else
|
|
xi_draw_3d_rect( win, &rct, ( BOOLEAN ) ( CELL_IS_SELECTED( lmp, row, col ) ? !column_data->column_well :
|
|
column_data->column_well ), 2, color_light, color_ctrl, color_dark );
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinColor brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
BOOLEAN do_draw;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( list_has_focus && !v_scrolled && col == focus_column && row == focus_row )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
do_draw = lm_focus_cell_has( lmp, row, col, FALSE );
|
|
if ( ( CELL_IS_ENABLED( lmp, row, col ) ) && !( CELL_IS_SELECTED( lmp, row, col ) ) )
|
|
do_draw = TRUE;
|
|
if ( do_draw )
|
|
{
|
|
if ( column_data->column_well || column_data->column_platform )
|
|
{
|
|
XinRect rct;
|
|
|
|
brush_color = lmp->back_color;
|
|
if ( cell_data->back_color )
|
|
brush_color = cell_data->back_color;
|
|
if ( brush_color != last_brush_color )
|
|
{
|
|
XinBrush cbrush;
|
|
|
|
cbrush.color = brush_color;
|
|
cbrush.pat = XinPatternSolid;
|
|
XinWindowPaintBrushSet( win, &cbrush );
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect( win, &rct );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if ( list_has_focus && !v_scrolled && focus_row >= first_row && focus_row <= last_row )
|
|
{
|
|
XinColor brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[focus_row][focus_column];
|
|
XinBrush cbrush;
|
|
XinRect rct,
|
|
row_rect;
|
|
|
|
column_data = lmp->lm_column_data[focus_column];
|
|
if ( column_data->XinWindowPaintNeeds )
|
|
{
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, focus_row, focus_column, FALSE );
|
|
brush_color = lmp->active_back_color; // Big brained XI put here lmp->back_color!
|
|
if ( cell_data->back_color )
|
|
brush_color = cell_data->back_color;
|
|
|
|
cbrush.fore_color = brush_color;
|
|
cbrush.pattern = XinBrushSolid;
|
|
XinWindowBrushSet( win, &cbrush );
|
|
rct = column_data->prct;
|
|
lm_get_row_rect( &row_rect, ( LM ) lmp, focus_row );
|
|
#if XIWS != XIWS_WM
|
|
row_rect.bottom--;
|
|
if ( row_rect.bottom < row_rect.top )
|
|
row_rect.bottom = row_rect.top;
|
|
#endif
|
|
lm_adj_v( lmp, row_rect.top );
|
|
lm_adj_v( lmp, row_rect.bottom );
|
|
rct.top = row_rect.top;
|
|
rct.bottom = row_rect.bottom;
|
|
#if XIWS == XIWS_MAC || XIWS == XIWS_XM || XIWS == XIWS_WXGTK
|
|
if ( cell_data->xi_text )
|
|
xi_text_rect_get_adjusted( cell_data->xi_text, &rct );
|
|
#endif
|
|
xi_draw_rect( win, &rct );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
draw_cell_icons( LM_DATA * lmp, XinWindow win, ROW_INFO * row_info,
|
|
int first_row, int last_row )
|
|
{
|
|
int col,
|
|
row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
XinDrawTools ct;
|
|
XinColor last_fore_color,
|
|
last_back_color;
|
|
|
|
XinWindowDrawToolsGet( win, &ct );
|
|
ct.text_fore_color = lmp->enabled_color;
|
|
ct.text_back_color = lmp->back_color;
|
|
ct.opaque_text = TRUE;
|
|
XinWindowDrawToolsSet( win, &ct );
|
|
last_back_color = 0L;
|
|
last_fore_color = 0L;
|
|
/* draw cell icons */
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinRect rct;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
XinColor fore_color,
|
|
back_color;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
rct = column_data->prct;
|
|
rct.top = ri->rct.top;
|
|
rct.bottom = ri->rct.bottom;
|
|
lm_adj_v( lmp, rct.top );
|
|
lm_adj_v( lmp, rct.bottom );
|
|
{
|
|
XinRect mlr = lmp->mlr;
|
|
|
|
if ( lmp->pixel_width )
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_rect_intersect( &mlr, &mlr, &rct );
|
|
xi_set_clip( win, &mlr );
|
|
}
|
|
fore_color = ct.text_fore_color;
|
|
back_color = ct.text_back_color;
|
|
if ( lmp->row_colors[row] )
|
|
fore_color = lmp->row_colors[row];
|
|
if ( cell_data->color )
|
|
fore_color = cell_data->color;
|
|
if ( cell_data->back_color )
|
|
{
|
|
back_color = cell_data->back_color;
|
|
}
|
|
if ( cell_data->bitmap != NULL && !cell_data->button_full_cell )
|
|
{
|
|
if ( lmp->no_horz_lines )
|
|
rct.bottom++;
|
|
if ( lmp->no_vert_lines )
|
|
rct.right++;
|
|
xi_bitmap_draw( cell_data->bitmap, win, &rct, &rct, FALSE );
|
|
continue;
|
|
}
|
|
if ( !cell_data->icon_rid )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
if ( fore_color != last_fore_color || back_color != last_back_color )
|
|
xi_draw_icon( win, rct.left, rct.top, cell_data->icon_rid, fore_color, back_color );
|
|
else
|
|
xi_draw_icon( win, rct.left, rct.top, cell_data->icon_rid, 0L, 0L );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
get_cell_color( LM_DATA * lmp, LM_CELL_DATA * cell_data, LM_COLUMN_DATA * column_data,
|
|
int row, int col, XinColor * color, XinColor * back_color )
|
|
{
|
|
BOOLEAN list_enabled,
|
|
col_enabled,
|
|
enabled;
|
|
XinColor temp_color;
|
|
|
|
list_enabled = ( lmp->attrib & XI_ATR_ENABLED ) != 0;
|
|
col_enabled = ( lmp->lm_column_data[col]->attrib & XI_ATR_ENABLED ) != 0;
|
|
enabled = list_enabled && col_enabled;
|
|
if ( CELL_IS_SELECTED( lmp, row, col ) )
|
|
{
|
|
XinColor enabled_back_color,
|
|
enabled_color;
|
|
XinColor disabled_back_color,
|
|
disabled_color;
|
|
|
|
/* determine enabled_back_color */
|
|
enabled_back_color = lmp->back_color;
|
|
if ( cell_data->back_color )
|
|
enabled_back_color = cell_data->back_color;
|
|
|
|
/* determine enabled_color */
|
|
enabled_color = lmp->enabled_color;
|
|
temp_color = lmp->row_colors[row];
|
|
if ( temp_color )
|
|
enabled_color = temp_color;
|
|
if ( cell_data->color )
|
|
enabled_color = cell_data->color;
|
|
|
|
/* determine disabled colors */
|
|
disabled_back_color = lmp->disabled_back_color;
|
|
disabled_color = lmp->disabled_color;
|
|
|
|
if ( enabled )
|
|
{
|
|
if ( lmp->retain_back_color_on_select && cell_data->back_color )
|
|
{
|
|
*color = enabled_color;
|
|
*back_color = enabled_back_color;
|
|
}
|
|
else
|
|
{
|
|
*color = enabled_back_color;
|
|
*back_color = enabled_color;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*color = disabled_back_color;
|
|
*back_color = disabled_color;
|
|
}
|
|
|
|
if ( column_data->column_well || column_data->column_platform )
|
|
*color = lmp->enabled_color;
|
|
}
|
|
else
|
|
{
|
|
if ( enabled )
|
|
{
|
|
*color = lmp->enabled_color;
|
|
temp_color = lmp->row_colors[row];
|
|
if ( temp_color )
|
|
*color = temp_color;
|
|
if ( cell_data->color )
|
|
*color = cell_data->color;
|
|
*back_color = lmp->back_color;
|
|
if ( cell_data->back_color )
|
|
*back_color = cell_data->back_color;
|
|
}
|
|
else
|
|
{
|
|
*color = lmp->disabled_color;
|
|
*back_color = lmp->disabled_back_color;
|
|
}
|
|
}
|
|
if ( column_data->wrap_text && !cell_data->back_color
|
|
&& ( column_data->column_platform || column_data->column_well ) )
|
|
*back_color = xi_get_pref( XI_PREF_COLOR_CTRL );
|
|
else if ( *color == XI_COLOR_BLACK )
|
|
*color = 0L;
|
|
}
|
|
|
|
static void
|
|
draw_all_cell_text( LM_DATA * lmp, XinWindow win, ROW_INFO * row_info,
|
|
int col_offset, int first_row, int last_row, XinRect * list_rect,
|
|
BOOLEAN in_update_event )
|
|
{
|
|
XinDrawTools ctools;
|
|
int row,
|
|
col;
|
|
ROW_INFO *ri;
|
|
LM_COLUMN_DATA *column_data;
|
|
int leading,
|
|
ascent,
|
|
descent;
|
|
BOOLEAN have_last_font;
|
|
BOOLEAN have_set_height = FALSE;
|
|
XinFont *last_font;
|
|
|
|
ctools = lm_normal_ctools;
|
|
|
|
/* the following two lines must come before the XinWindowFontSet, because in
|
|
* R3, setting the draw ctools also sets the font. */
|
|
ctools.text_fore_color = XI_COLOR_BLACK;
|
|
#if XIWS == XIWS_WM
|
|
ctools.BackColor = lmp->back_color;
|
|
#endif
|
|
XinWindowDrawToolsSet( win, &ctools );
|
|
|
|
lmp->cur_font = lmp->font;
|
|
XinFontMetricsGet( lmp->cur_font, &leading, &ascent, &descent );
|
|
|
|
/*
|
|
draw:
|
|
font: default
|
|
wrapped: no
|
|
color: black
|
|
|
|
one of the slowest operations is setting colors, therefore we only draw text
|
|
of the most common color. after this loop, we draw text of other colors.
|
|
because this loop draws most of the cells, don't set any colors within
|
|
this loop.
|
|
|
|
color is set to black just above.
|
|
*/
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
int col_offset;
|
|
XinRect clip_rect,
|
|
rect;
|
|
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
|
|
if ( column_data->wrap_text )
|
|
continue;
|
|
rect = column_data->prct;
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
rect.left += col_offset;
|
|
rect.right -= col_offset;
|
|
if ( !xi_rect_intersect( &clip_rect, &rect, list_rect ) )
|
|
continue;
|
|
xi_set_clip( win, &clip_rect );
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
XinColor color,
|
|
back_color;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( cell_data->font )
|
|
continue;
|
|
if ( cell_data->icon_rid || cell_data->bitmap != NULL )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
if ( lmp->set_heights[row] )
|
|
{
|
|
have_set_height = TRUE;
|
|
continue;
|
|
}
|
|
get_cell_color( lmp, cell_data, column_data, row, col, &color, &back_color );
|
|
if ( color )
|
|
continue;
|
|
draw_cell_text( lmp, cell_data, column_data,
|
|
row, col, col_offset, leading, ascent,
|
|
descent, color, back_color, FALSE );
|
|
}
|
|
}
|
|
|
|
/*
|
|
draw:
|
|
font: default
|
|
wrapped: no
|
|
color: not black
|
|
*/
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
XinRect clip_rect;
|
|
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( column_data->wrap_text )
|
|
continue;
|
|
if ( !xi_rect_intersect( &clip_rect, &column_data->prct, list_rect ) )
|
|
continue;
|
|
xi_set_clip( win, &clip_rect );
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
XinColor color,
|
|
back_color;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( cell_data->font )
|
|
continue;
|
|
if ( cell_data->icon_rid || cell_data->bitmap != NULL )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
if ( lmp->set_heights[row] )
|
|
{
|
|
have_set_height = TRUE;
|
|
continue;
|
|
}
|
|
get_cell_color( lmp, cell_data, column_data, row, col, &color, &back_color );
|
|
if ( !color )
|
|
continue;
|
|
XinWindowColorTextForeSet( win, color );
|
|
#if XIWS == XIWS_WM
|
|
XinWindowColorTextBackSet( win, lmp->enabled_color );
|
|
#endif
|
|
draw_cell_text( lmp, cell_data, column_data, row, col, col_offset,
|
|
leading, ascent, descent, color, back_color, FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
draw:
|
|
font: default
|
|
wrapped: yes
|
|
color: black
|
|
|
|
this needs to be a separate loop from above, because this loop sets the
|
|
clipping region for each cell, and the above loop sets the clipping region
|
|
for each column.
|
|
*/
|
|
XinWindowColorTextForeSet( win, XI_COLOR_BLACK );
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( !column_data->wrap_text && !have_set_height )
|
|
continue;
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
XinColor color,
|
|
back_color;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( lmp->row_colors[row] )
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( cell_data->font )
|
|
continue;
|
|
if ( cell_data->icon_rid || cell_data->bitmap != NULL )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
if ( !column_data->wrap_text && !lmp->set_heights[row] )
|
|
continue;
|
|
get_cell_color( lmp, cell_data, column_data, row, col, &color, &back_color );
|
|
if ( color )
|
|
continue;
|
|
draw_cell_text( lmp, cell_data, column_data,
|
|
row, col, col_offset, leading, ascent,
|
|
descent, color, back_color, TRUE );
|
|
}
|
|
}
|
|
|
|
/*
|
|
draw:
|
|
font: default
|
|
wrapped: yes
|
|
color: not black
|
|
|
|
this needs to be a separate loop from above, because this loop sets the
|
|
colors for each cell, and the above loop only draws black.
|
|
*/
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( !column_data->wrap_text && !have_set_height )
|
|
continue;
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
XinColor color,
|
|
back_color;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( cell_data->font )
|
|
continue;
|
|
if ( cell_data->icon_rid || cell_data->bitmap != NULL )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
if ( !column_data->wrap_text && !lmp->set_heights[row] )
|
|
continue;
|
|
get_cell_color( lmp, cell_data, column_data, row, col, &color, &back_color );
|
|
if ( !color )
|
|
continue;
|
|
XinWindowColorTextForeSet( win, color );
|
|
draw_cell_text( lmp, cell_data, column_data,
|
|
row, col, col_offset, leading, ascent,
|
|
descent, color, back_color, TRUE );
|
|
}
|
|
}
|
|
|
|
/*
|
|
draw:
|
|
font: not default
|
|
wrapped: either yes or no
|
|
color: any
|
|
|
|
draw all of the rest of the text
|
|
*/
|
|
have_last_font = FALSE;
|
|
last_font = NULL;
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
XinColor color,
|
|
back_color;
|
|
BOOLEAN need_to_set;
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
if ( !cell_data->font )
|
|
continue;
|
|
if ( cell_data->icon_rid || cell_data->bitmap != NULL )
|
|
continue;
|
|
if ( cell_data->button_full_cell )
|
|
continue;
|
|
need_to_set = FALSE;
|
|
if ( !have_last_font )
|
|
need_to_set = TRUE;
|
|
if ( have_last_font && !font_compare( last_font, cell_data->font ) )
|
|
need_to_set = TRUE;
|
|
if ( need_to_set )
|
|
{
|
|
int char_width;
|
|
|
|
lmp->cur_font = cell_data->font;
|
|
xi_get_font_metrics_font( cell_data->font, &leading, &ascent,
|
|
&descent, &char_width );
|
|
last_font = cell_data->font;
|
|
have_last_font = TRUE;
|
|
}
|
|
get_cell_color( lmp, cell_data, column_data, row, col, &color, &back_color );
|
|
XinWindowColorTextForeSet( win, color );
|
|
|
|
draw_cell_text( lmp, cell_data, column_data,
|
|
row, col, col_offset, leading, ascent,
|
|
descent, color, back_color, TRUE );
|
|
}
|
|
}
|
|
|
|
if ( lm_focus_list_has( lmp ) )
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled ) )
|
|
if ( lm_focus_cell_has( lmp, focus_row, focus_column, v_scrolled ) )
|
|
set_focus_cell_rct( lmp, focus_row, focus_column, in_update_event );
|
|
}
|
|
}
|
|
|
|
#if XIWS != XIWS_WM
|
|
static void
|
|
draw_row_focus_border( LM_DATA * lmp, ROW_INFO * row_info, int first_row, int last_row )
|
|
{
|
|
int col,
|
|
row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
XinPen color_cpen;
|
|
XinPen rule_cpen;
|
|
BOOLEAN last_was_rule = TRUE;
|
|
XinRect mr;
|
|
|
|
if ( !lmp->row_focus_border )
|
|
return;
|
|
color_cpen.width = 1;
|
|
color_cpen.fore_color = lmp->row_focus_border_color;
|
|
color_cpen.pattern = XinPenSolid;
|
|
if ( lmp->no_horz_lines )
|
|
{
|
|
rule_cpen = black_cpen;
|
|
rule_cpen.fore_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
rule_cpen.width = 1;
|
|
rule_cpen.fore_color = lmp->rule_color;
|
|
rule_cpen.pattern = XinPenSolid;
|
|
}
|
|
XinWindowPenSet( lmp->win, &rule_cpen );
|
|
{
|
|
mr = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_set_clip( lmp->win, &mr );
|
|
}
|
|
for ( row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri )
|
|
{
|
|
XinRect rct;
|
|
XinPoint p;
|
|
XinWindow win = lmp->win;
|
|
BOOLEAN row_has_focus = lm_row_has_focus( lmp, row, FALSE );
|
|
|
|
if ( !ri->XinWindowPaintNeeds )
|
|
continue;
|
|
if ( row_has_focus )
|
|
{
|
|
if ( last_was_rule )
|
|
{
|
|
XinWindowPenSet( lmp->win, &color_cpen );
|
|
last_was_rule = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !last_was_rule )
|
|
{
|
|
XinWindowPenSet( lmp->win, &rule_cpen );
|
|
last_was_rule = TRUE;
|
|
}
|
|
}
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if ( !column_data->XinWindowPaintNeeds )
|
|
continue;
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
|
|
/* draw top line */
|
|
p.h = rct.left;
|
|
p.v = rct.top - 1;
|
|
xi_move_to( win, p );
|
|
p.h = rct.right;
|
|
xi_draw_line( win, p );
|
|
|
|
if ( row_has_focus )
|
|
{
|
|
/* draw next line down */
|
|
p.v++;
|
|
p.h = rct.left;
|
|
xi_move_to( win, p );
|
|
p.h = rct.right;
|
|
xi_draw_line( win, p );
|
|
}
|
|
|
|
/* draw bottom line */
|
|
p.h = rct.left;
|
|
p.v = rct.bottom;
|
|
xi_move_to( win, p );
|
|
p.h = rct.right;
|
|
xi_draw_line( win, p );
|
|
|
|
if ( row_has_focus )
|
|
{
|
|
/* draw line above bottom line */
|
|
p.v--;
|
|
p.h = rct.left;
|
|
xi_move_to( win, p );
|
|
p.h = rct.right;
|
|
xi_draw_line( win, p );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* draw_cell_focus_border */
|
|
/* ------------------------------------------------------------------------- */
|
|
static void
|
|
draw_cell_focus_border( LM_DATA * lmp )
|
|
{
|
|
XinColor border_color;
|
|
XinRect rct,
|
|
row_rect;
|
|
XinDrawTools dt;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
if ( !lm_focus_list_has( lmp ) )
|
|
return;
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if (v_scrolled)
|
|
return;
|
|
column_data = lmp->lm_column_data[focus_column];
|
|
if ( !( column_data->attrib & XI_ATR_FOCUSBORDER ) )
|
|
return;
|
|
rct = column_data->prct;
|
|
lm_get_row_rect( &row_rect, ( LM ) lmp, focus_row );
|
|
#if XIWS != XIWS_WM
|
|
row_rect.bottom--;
|
|
if ( row_rect.bottom < row_rect.top )
|
|
row_rect.bottom = row_rect.top;
|
|
#endif
|
|
lm_adj_v( lmp, row_rect.top );
|
|
lm_adj_v( lmp, row_rect.bottom );
|
|
rct.top = row_rect.top;
|
|
rct.bottom = row_rect.bottom;
|
|
border_color = lmp->enabled_color;
|
|
|
|
XinWindowDrawToolsNormalGet( &dt );
|
|
dt.pen.fore_color = border_color;
|
|
dt.pen.width = 1;
|
|
dt.pen.pattern = XinPenSolid;
|
|
dt.brush.pattern = XinBrushHollow;
|
|
dt.brush.fore_color = XI_COLOR_WHITE;
|
|
dt.draw_mode = XinDrawModeCopy;
|
|
XinWindowDrawToolsSet( lmp->win, &dt );
|
|
xi_draw_rect( lmp->win, &rct );
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* draw_cell_block */
|
|
/* ------------------------------------------------------------------------- */
|
|
static void
|
|
draw_cell_block( LM_DATA * lmp, int first_row, int last_row,
|
|
ROW_INFO * row_info, BOOLEAN in_update_event )
|
|
{
|
|
XinWindow win = lmp->win;
|
|
XinRect actual_rct = lmp->mlr;
|
|
int actual_r;
|
|
int col_offset;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
|
|
#if XIWS != XIWS_WM
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->mlr.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->mlr.right;
|
|
actual_rct.right = actual_r;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->mlr.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->mlr.right;
|
|
actual_rct.right = actual_r;
|
|
#endif
|
|
|
|
xi_set_clip( win, &actual_rct );
|
|
|
|
/* draw backgrounds of cells */
|
|
draw_background_rects( lmp, win, row_info, first_row, last_row );
|
|
|
|
/* draw all of the text in the cells */
|
|
draw_all_cell_text( lmp, win, row_info, col_offset, first_row, last_row,
|
|
&actual_rct, in_update_event );
|
|
|
|
/* draw cell buttons */
|
|
draw_cell_buttons( lmp, row_info, first_row, last_row, in_update_event );
|
|
|
|
#if XIWS != XIWS_WM
|
|
draw_row_rules( lmp, first_row, last_row, FALSE );
|
|
#endif
|
|
|
|
draw_cell_icons( lmp, win, row_info, first_row, last_row );
|
|
|
|
#if XIWS != XIWS_WM
|
|
draw_row_focus_border( lmp, row_info, first_row, last_row );
|
|
#endif
|
|
draw_cell_focus_border( lmp );
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* draw_cell_range */
|
|
/* ------------------------------------------------------------------------- */
|
|
void
|
|
draw_cell_range( LM_DATA * lmp, int first_row, int last_row,
|
|
int first_col, int last_col,
|
|
BOOLEAN in_event_update )
|
|
{
|
|
int row,
|
|
col;
|
|
ROW_INFO *row_info;
|
|
ROW_INFO *row_ptr;
|
|
|
|
if ( lmp->list_obj->nbr_children <= 0 )
|
|
return;
|
|
if ( xi_get_attrib( lmp->list_obj ) & XI_ATR_VISIBLE )
|
|
{
|
|
row_info = ( ROW_INFO * ) XinMemoryAlloc( sizeof( ROW_INFO ) * ( last_row + 1 ) );
|
|
for ( row = first_row, row_ptr = row_info + first_row; row <= last_row;
|
|
++row, ++row_ptr )
|
|
{
|
|
lm_get_row_rect( &row_ptr->rct, ( LM ) lmp, row );
|
|
/* don't need to test for the rule, it is drawn elsewhere */
|
|
#if XIWS != XIWS_WM
|
|
row_ptr->rct.bottom--;
|
|
if ( row_ptr->rct.bottom < row_ptr->rct.top )
|
|
row_ptr->rct.bottom = row_ptr->rct.top;
|
|
#endif
|
|
row_ptr->prct = row_ptr->rct;
|
|
lm_adj_v( lmp, row_ptr->prct.top );
|
|
lm_adj_v( lmp, row_ptr->prct.bottom );
|
|
if ( in_event_update )
|
|
{
|
|
if ( lm_XinWindowPaintNeeds( lmp, &row_ptr->rct, FALSE, TRUE ) )
|
|
row_ptr->XinWindowPaintNeeds = TRUE;
|
|
else
|
|
row_ptr->XinWindowPaintNeeds = FALSE;
|
|
}
|
|
else
|
|
row_ptr->XinWindowPaintNeeds = TRUE;
|
|
}
|
|
|
|
/* force cell requests for visible cells - makes it draw nicer */
|
|
/* This used to be for columns with suppress_update_cells, but now applies to all */
|
|
/* Used to have the following line as a condition for the "for" loop: */
|
|
/* if ( lmp->lm_column_data[col]->suppress_update_cells ) */
|
|
for ( row = first_row; row <= last_row; ++row )
|
|
{
|
|
for ( col = first_col; col <= last_col; ++col )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &( lmp->cell_data[row][col] );
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, col, FALSE );
|
|
}
|
|
}
|
|
|
|
/* determine which columns need to be updated */
|
|
calc_col_XinWindowPaintNeeds( lmp, first_col, last_col, in_event_update );
|
|
|
|
/* at this point, we should never need to call lm_XinWindowPaintNeeds again
|
|
* in this function or any called functions. */
|
|
draw_cell_block( lmp, first_row, last_row, row_info, in_event_update );
|
|
XinMemoryFree( ( char * ) row_info );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_cell_btn_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
oevp: xvt event, without virtual coordinate conversion
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_cell_btn_event( LM_DATA * lmp, XinEvent * ep, XinEvent * oevp )
|
|
{
|
|
XinRect mr;
|
|
int hit_test_value,
|
|
row,
|
|
col;
|
|
|
|
mr = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
|
|
hit_test_value = lm_hit_test( ( LM ) lmp, ep, oevp, &row, &col, NULL, NULL, NULL );
|
|
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
lmp->down_in_btn = TRUE;
|
|
lmp->btn_down = TRUE;
|
|
lmp->btn_down_row = row;
|
|
lmp->btn_down_col = col;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
xi_set_trap_obj( lmp->list_obj );
|
|
redraw_cell_button( lmp, row, col, &mr, lmp->btn_down, FALSE );
|
|
break;
|
|
case XinEventMouseMove:
|
|
{
|
|
BOOLEAN last = lmp->btn_down;
|
|
|
|
if ( hit_test_value != 5 || row != lmp->btn_down_row || col != lmp->btn_down_col )
|
|
lmp->btn_down = FALSE;
|
|
else
|
|
lmp->btn_down = TRUE;
|
|
if ( last != lmp->btn_down )
|
|
{
|
|
redraw_cell_button( lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
|
|
lmp->btn_down, FALSE );
|
|
last = lmp->btn_down;
|
|
}
|
|
break;
|
|
}
|
|
case XinEventMouseUp:
|
|
{
|
|
BOOLEAN clear_button;
|
|
|
|
{
|
|
int focus_row,
|
|
focus_col;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_col, &is_vert_scrolled );
|
|
clear_button = ( lmp->btn_down_row != focus_row );
|
|
}
|
|
if ( lmp->btn_down && !clear_button )
|
|
redraw_cell_button( lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
|
|
FALSE, FALSE );
|
|
lmp->btn_down = FALSE;
|
|
lmp->down_in_btn = FALSE;
|
|
if ( hit_test_value == 5 && row == lmp->btn_down_row && col == lmp->btn_down_col )
|
|
do_lm_cb( ( LM ) lmp, LM_CB_CELL_BTN, row, col, ep, NULL, 0 );
|
|
else if ( clear_button )
|
|
redraw_cell( ( LM ) lmp, lmp->btn_down_row, lmp->btn_down_col, FALSE );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_select_column
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
get_select_column( LM_DATA * lmp )
|
|
{
|
|
int col;
|
|
|
|
for ( col = 0; col < lmp->nbr_columns; col++ )
|
|
if ( LM_COL_ATTR( ( LM ) lmp, col ) & XI_ATR_SELECTABLE )
|
|
return col;
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: find_selection
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
find_selection( LM_DATA * lmp )
|
|
{
|
|
int row_num;
|
|
|
|
for ( row_num = 0; row_num < lmp->nbr_realized_rows; row_num++ )
|
|
if ( lm_get_attrib( ( LM ) lmp, LM_ROW, row_num, 0, FALSE )
|
|
& LM_ROW_ATR_SELECTED )
|
|
return row_num;
|
|
return -1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_attrib
|
|
lm: current lm
|
|
lm_part: must be LM_LIST, LM_COLUMN, LM_ROW, or LM_CELL
|
|
idx: if LM_LIST, not used
|
|
if LM_COLUMN, column number
|
|
if LM_ROW, row number
|
|
if LM_CELL, row number
|
|
idx2: if LM_LIST, not used
|
|
if LM_COLUMN, not used
|
|
if LM_ROW, not used
|
|
if LM_CELL, column number
|
|
attrib: attribute to set
|
|
half_baked: if set, don't redraw
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
|
|
BOOLEAN v_scrolled, unsigned long attrib, int half_baked )
|
|
{
|
|
unsigned long do_redraw;
|
|
LM_DATA *lmp = LMP( lm );
|
|
int focus_row,
|
|
focus_column;
|
|
|
|
switch ( lm_part )
|
|
{
|
|
case LM_LIST:
|
|
{
|
|
XinRect r;
|
|
|
|
lmp->attrib = attrib;
|
|
xi_get_rect( lmp->list_obj, &r );
|
|
r.right += 10;
|
|
r.bottom += 4;
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
break;
|
|
}
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
XinRect rct;
|
|
|
|
column_data = lmp->lm_column_data[idx];
|
|
do_redraw = ( ( column_data->attrib ^ attrib ) & LM_REDRAW_COL_ATR );
|
|
if ( ( column_data->attrib ^ attrib )
|
|
& ( LM_COL_ATR_PASSWORD | LM_COL_ATR_READONLY ) )
|
|
{
|
|
int row;
|
|
|
|
for ( row = 0; row < lmp->nbr_realized_rows; row++ )
|
|
{
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][idx];
|
|
|
|
if ( cell_data->xi_text )
|
|
{
|
|
xi_text_password_set( cell_data->xi_text,
|
|
( attrib & LM_COL_ATR_PASSWORD ) != 0 );
|
|
xi_text_read_only_set( cell_data->xi_text,
|
|
( attrib & LM_COL_ATR_READONLY ) != 0 );
|
|
}
|
|
}
|
|
}
|
|
column_data->attrib = attrib;
|
|
if ( do_redraw )
|
|
{
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_get_rect( lm, LM_COLUMN, idx, &rct );
|
|
xi_invalidate_rect( lmp->win, &rct );
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &is_vert_scrolled ) )
|
|
if ( ( !is_vert_scrolled ) && ( focus_column == idx ) && lm_focus_state_get( lmp ) != LM_FOCUS_VISIBLE )
|
|
set_focus_cell_rct( lmp, focus_row, focus_column, FALSE );
|
|
}
|
|
break;
|
|
}
|
|
case LM_ROW:
|
|
{
|
|
unsigned long old_attrib;
|
|
|
|
do_redraw = ( ( lmp->row_attribs[idx] ^ attrib ) & LM_REDRAW_ROW_ATR );
|
|
old_attrib = lmp->row_attribs[idx];
|
|
if ( lmp->single_select && ( attrib & XI_ATR_SELECTED ) )
|
|
{
|
|
int old_row;
|
|
|
|
old_row = find_selection( lmp );
|
|
if ( old_row != -1 && old_row != idx )
|
|
lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE,
|
|
lmp->row_attribs[old_row] & ~XI_ATR_SELECTED,
|
|
half_baked );
|
|
}
|
|
lmp->row_attribs[idx] = attrib;
|
|
if ( !half_baked && do_redraw )
|
|
{
|
|
if ( ( old_attrib & XI_ATR_SELECTED ) != ( attrib & XI_ATR_SELECTED ) )
|
|
{
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_redraw_row( lmp, idx, FALSE );
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &is_vert_scrolled ) )
|
|
if ( ( !is_vert_scrolled ) && ( focus_row == idx ) && lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
set_focus_cell_rct( lmp, focus_row, focus_column, FALSE );
|
|
}
|
|
else
|
|
{
|
|
XinRect r;
|
|
|
|
lm_get_row_rect( &r, lm, idx );
|
|
xi_set_clip( lmp->win, NULL );
|
|
lm_invalidate_rect( lmp, &r, FALSE );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case LM_CELL:
|
|
{
|
|
unsigned long old_attrib;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if ( !cell_data->valid_data )
|
|
return;
|
|
if ( v_scrolled )
|
|
{
|
|
/* TODO this could be called with a v_scrolled cell when the focus is
|
|
* not really there. unlikely, but could happen. */
|
|
lm_focus_cell_attrib_set( lmp, attrib );
|
|
}
|
|
else
|
|
{
|
|
old_attrib = lmp->cell_data[idx][idx2].attrib;
|
|
do_redraw = ( ( old_attrib ^ attrib ) & LM_REDRAW_CELL_ATR );
|
|
cell_data->attrib = attrib;
|
|
if ( !half_baked && do_redraw )
|
|
{
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
redraw_cell( lm, idx, idx2, FALSE );
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &is_vert_scrolled ) )
|
|
if ( ( !is_vert_scrolled ) && ( focus_row == idx ) && ( focus_column == idx2 )
|
|
&& lm_focus_state_get( lmp ) != LM_FOCUS_VISIBLE )
|
|
set_focus_cell_rct( lmp, focus_row, focus_column, FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: select_row
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
select_row( LM lm, int row, int column, BOOLEAN dbl_click )
|
|
{
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
XI_OBJ *old_itf;
|
|
int old_row;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
old_row = find_selection( lmp );
|
|
if ( old_row != row && old_row != -1 )
|
|
{
|
|
attrib = lm_get_attrib( lm, LM_ROW, old_row, 0, FALSE );
|
|
attrib &= ~LM_ROW_ATR_SELECTED;
|
|
lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE, attrib, FALSE );
|
|
}
|
|
attrib = lm_get_attrib( lm, LM_ROW, row, 0, FALSE );
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) row;
|
|
if ( column == -1 )
|
|
column = ( unsigned char ) get_select_column( lmp );
|
|
lm_cb_data.column = column;
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = dbl_click;
|
|
lm_cb_data.v.select.shift = FALSE;
|
|
lm_cb_data.v.select.control = FALSE;
|
|
old_itf = lmp->itf_obj;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
if ( xi_is_itf( old_itf ) )
|
|
if ( !lm_cb_data.v.select.refused && old_row != row )
|
|
lm_set_attrib( lm, LM_ROW, row, 0, FALSE, attrib, FALSE );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: send_select_event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
send_select_event( LM lm, int row, int column, XinEvent * ep, unsigned long attrib )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
XI_OBJ *old_itf;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( ep->type == XinEventMouseDouble )
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
else
|
|
{
|
|
if ( attrib & LM_ROW_ATR_SELECTED )
|
|
attrib &= ~LM_ROW_ATR_SELECTED;
|
|
else
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
}
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) row;
|
|
lm_cb_data.column = ( unsigned char ) column;
|
|
lm_cb_data.v.select.selected = ( ( attrib & LM_ROW_ATR_SELECTED ) != 0 );
|
|
lm_cb_data.v.select.dbl_click = ( ep->type == XinEventMouseDouble );
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
old_itf = lmp->itf_obj;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
if ( xi_is_itf( old_itf ) )
|
|
if ( !lm_cb_data.v.select.refused )
|
|
lm_set_attrib( lm, LM_ROW, row, 0, FALSE, attrib, FALSE );
|
|
}
|
|
|
|
/*********** draw border around entire list ***********/
|
|
static void
|
|
draw_list_rect( LM_DATA * lmp, XinRect * vr, XinRect * hr )
|
|
{
|
|
XinRect r;
|
|
XI_OBJ *list_obj = lmp->list_obj;
|
|
XI_LIST_DATA *list_data = list_obj->v.list;
|
|
|
|
r = lmp->rct;
|
|
if ( list_data->sb_win )
|
|
r.right = vr->right;
|
|
else
|
|
r.right += BORDER_WIDTH;
|
|
if ( list_data->hsb_win )
|
|
r.bottom = hr->bottom;
|
|
xi_draw_rect( lmp->win, &r );
|
|
}
|
|
|
|
/*********** draw heading rules ***********/
|
|
static void
|
|
draw_heading_rules( LM_DATA * lmp, int hrule_h )
|
|
{
|
|
if ( !( lmp->update_rows_at_top + lmp->update_rows_at_bottom ) )
|
|
{
|
|
if ( !lmp->no_heading )
|
|
{
|
|
int i;
|
|
XinPoint p;
|
|
|
|
#if XIWS != XIWS_WM
|
|
int r2;
|
|
XinWindow win = lmp->win;
|
|
|
|
#endif
|
|
|
|
#if XIWS == XIWS_WM
|
|
/* heading rule, Release 3.0 */
|
|
p.h = lmp->rct.left;
|
|
p.v = lmp->pix_hdr_bottom;
|
|
xi_move_to( lmp->win, p );
|
|
p.h = hrule_h - VPIX_PER_CH;
|
|
xi_draw_line( lmp->win, p );
|
|
#endif
|
|
#if XIWS != XIWS_WM
|
|
r2 = lmp->rct.right - lmp->delta_x;
|
|
if ( lmp->nbr_columns == 0 )
|
|
r2 -= 2 * BORDER_WIDTH;
|
|
r2 = min( r2, hrule_h );
|
|
WIDTHLOOP( i, BORDER_WIDTH )
|
|
{
|
|
p.h = lmp->rct.left;
|
|
p.v = lmp->pix_row1_top - BORDER_WIDTH + i;
|
|
xi_move_to( win, p );
|
|
p.h = r2;
|
|
xi_draw_line( win, p );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********** draw column rules ***********/
|
|
static void
|
|
draw_column_rules( LM_DATA * lmp )
|
|
{
|
|
LM_COLUMN_DATA **lmcd;
|
|
int col;
|
|
XinPoint p;
|
|
|
|
#if XIWS == XIWS_WM
|
|
XinPoint from_p;
|
|
|
|
#endif
|
|
|
|
if ( lmp->no_vert_lines )
|
|
{
|
|
XinPen back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.fore_color = lmp->back_color;
|
|
XinWindowPenSet( lmp->win, &back_cpen );
|
|
}
|
|
else
|
|
{
|
|
XinPen back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.fore_color = lmp->rule_color;
|
|
XinWindowPenSet( lmp->win, &back_cpen );
|
|
}
|
|
for ( col = 1, lmcd = &lmp->lm_column_data[1]; col < lmp->nbr_columns; col++, ++lmcd )
|
|
{
|
|
p.h = ( *lmcd )->x_pix_pos - RULE_WIDTH_V;
|
|
#if XIWS == XIWS_WM
|
|
p.v = lmp->pix_top;
|
|
lm_move_to( lmp, p, FALSE, TRUE );
|
|
p.v = lmp->mlr.bottom - VPIX_PER_CH;
|
|
lm_draw_line( lmp, p, FALSE, TRUE );
|
|
#endif
|
|
#if XIWS != XIWS_WM
|
|
/* if RULE_WIDTH_V were used, this is where it would be used */
|
|
p.v = lmp->rct.top;
|
|
lm_move_to( lmp, p, FALSE, TRUE );
|
|
p.v = min( lmp->rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top );
|
|
lm_draw_line( lmp, p, FALSE, TRUE );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
lm: current lm
|
|
update: if TRUE, draw_lm is being called due to an XinEventPaint event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
draw_lm( LM lm, BOOLEAN update )
|
|
{
|
|
int hrule_h,
|
|
actual_r,
|
|
idx;
|
|
XinRect lmp_rct,
|
|
actual_rct,
|
|
clip_rct;
|
|
XinRect hr,
|
|
vr;
|
|
XI_OBJ *list_obj;
|
|
XI_LIST_DATA *list_data;
|
|
LM_DATA *lmp = LMP( lm );
|
|
XinWindow win = lmp->win;
|
|
XinBrush back_cbrush;
|
|
|
|
#if XIWS != XIWS_WM
|
|
XinRect urct;
|
|
|
|
#else
|
|
XinBrush lm_cbrush;
|
|
XinPoint from_p;
|
|
|
|
/***********************************************************************/
|
|
/* set up variables for drawing */
|
|
c_xd = C_XD;
|
|
c_xu = C_XU;
|
|
c_v = C_V;
|
|
c_xx = C_XX;
|
|
#endif
|
|
if ( !( lmp->attrib & LM_ATR_VISIBLE ) )
|
|
{
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
return;
|
|
}
|
|
list_obj = lmp->list_obj;
|
|
list_data = list_obj->v.list;
|
|
lmp_rct = lmp->rct;
|
|
actual_rct = lmp_rct;
|
|
#if XIWS != XIWS_WM
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r - BORDER_WIDTH;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right + 8;
|
|
actual_rct.right = actual_r;
|
|
#endif
|
|
hrule_h = actual_r;
|
|
if ( lmp->pixel_width )
|
|
lmp_rct.right = hrule_h;
|
|
urct = lmp_rct;
|
|
if ( list_data->sb_win )
|
|
{
|
|
if ( list_data->have_sb_rct )
|
|
vr = list_data->sb_rct;
|
|
else
|
|
xi_get_sb_rect( list_obj, &vr );
|
|
urct.right = vr.right;
|
|
}
|
|
if ( list_data->hsb_win )
|
|
{
|
|
if ( list_data->have_hsb_rct )
|
|
hr = list_data->hsb_rct;
|
|
else
|
|
xi_get_hsb_rect( list_obj, &hr );
|
|
urct.bottom = hr.bottom;
|
|
}
|
|
#if XIWS != XIWS_WM
|
|
if ( update && !xi_XinWindowPaintNeeds( win, &urct ) )
|
|
{
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
return;
|
|
}
|
|
#endif
|
|
lmp_rct = lmp->rct;
|
|
if ( lmp->nbr_realized_rows )
|
|
{
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
|
|
}
|
|
else
|
|
lmp->rrr_bottom = 0;
|
|
if ( !lm_tools_inited )
|
|
{
|
|
lm_white_cbrush.fore_color = XI_COLOR_WHITE;
|
|
lm_white_cbrush.pattern = XinBrushSolid;
|
|
lm_black_cpen.width = 1;
|
|
lm_black_cpen.fore_color = XI_COLOR_BLACK;
|
|
lm_black_cpen.pattern = XinPenSolid;
|
|
XinWindowDrawToolsNormalGet( &lm_normal_ctools );
|
|
lm_tools_inited = TRUE; // Added by Guy :-(
|
|
}
|
|
|
|
/***********************************************************************/
|
|
/* draw anything other than in the cell region */
|
|
/* prior to this, there are no calls for drawing */
|
|
|
|
back_cbrush = lm_white_cbrush;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE THE FOLLOWING LINE, AND DON'T SET TO HOLLOW
|
|
back_cbrush.color = lmp->back_color;
|
|
*/
|
|
#if XIWS != XIWS_WM
|
|
back_cbrush.pattern = XinBrushHollow;
|
|
#endif
|
|
XinWindowBrushSet( win, &back_cbrush );
|
|
XinWindowPenSet( win, &lm_black_cpen );
|
|
clip_rct = actual_rct;
|
|
#if XIWS == XIWS_WM
|
|
if ( list_data->hsb_win )
|
|
clip_rct.bottom += 8;
|
|
clip_rct.right += 8;
|
|
#endif
|
|
xi_set_clip( win, &clip_rct );
|
|
XinWindowDrawModeSet( win, XinDrawModeCopy );
|
|
|
|
/* XinBrush: white_cbrush XinDrawPen: black_cpen CLIP: actual_rct */
|
|
|
|
/*********** draw the rectangle around the list ***********/
|
|
draw_list_rect( lmp, &vr, &hr );
|
|
|
|
#if XIWS == XIWS_WM
|
|
xi_set_clip( win, &actual_rct );
|
|
#endif
|
|
|
|
/*********** draw the rules between the heading and the cells ***********/
|
|
if ( !lmp->update_cells_only )
|
|
draw_heading_rules( lmp, hrule_h );
|
|
|
|
/*********** draw column rules ***********/
|
|
draw_column_rules( lmp );
|
|
|
|
/* XinBrush: white_cbrush XinDrawPen: black_cpen OR back_color cpen CLIP:
|
|
* actual_rct */
|
|
|
|
/*********** draw column headings ***********/
|
|
if ( !lmp->update_cells_only )
|
|
draw_column_headings( lmp, &actual_rct );
|
|
xi_set_clip( win, NULL );
|
|
|
|
/*********** draw text in cells ***********/
|
|
draw_cells( lmp, update );
|
|
|
|
draw_other_rectangles( lmp, &actual_rct );
|
|
|
|
xi_set_clip( win, NULL );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: send_cell_event
|
|
lm: current lm
|
|
ep: xvt event
|
|
gaining_focus: if TRUE, the edit control is gaining focus as this function is called
|
|
returns: TRUE if the event was used
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
send_cell_event( LM lm, XinEvent * ep, BOOLEAN gaining_focus, BOOLEAN send_to_txt )
|
|
{
|
|
BOOLEAN retval = FALSE;
|
|
int ch;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( lm_focus_state_get( lmp ) != LM_FOCUS_VISIBLE )
|
|
return FALSE;
|
|
if ( ep->type == XinEventCharacter )
|
|
{
|
|
if ( ep->v.character.alt )
|
|
return FALSE;
|
|
ch = ep->v.character.ch;
|
|
if ( ( ch >= ' ' || ch == XI_KEY_CLEAR || ch == XI_KEY_DEL || ch == '\b'
|
|
|| ch == '\r' || ch == '\n' )
|
|
&& ch != XI_KEY_BTAB && ch != XI_KEY_UP && ch != XI_KEY_DOWN &&
|
|
(!(lmp->attrib & LM_ATR_NAVIGATE) || ( ch != XI_KEY_LEFT && ch != XI_KEY_RIGHT)))
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
retval = do_lm_cb( lm, LM_CB_CHAR, focus_row, focus_column, ep, NULL, 0 );
|
|
/* retval = FALSE if event refused */
|
|
if ( !retval )
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( send_to_txt )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
BOOLEAN changed = FALSE;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
cell_data = &lmp->cell_data[focus_row][focus_column];
|
|
if ( cell_data->button_full_cell && ep->type == XinEventCharacter )
|
|
{
|
|
ch = ep->v.character.ch;
|
|
if ( ch == ' ' || ch == '\r' || ch == '\n' )
|
|
{
|
|
do_lm_cb( ( LM ) lmp, LM_CB_CELL_BTN, focus_row, focus_column, ep, NULL, 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = xi_text_event( cell_data->xi_text, ep, gaining_focus, &changed );
|
|
if ( changed )
|
|
{
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
|
|
lm_column_data = lmp->lm_column_data[focus_column];
|
|
retval = do_lm_cb( lm, LM_CB_CHANGE, focus_row, focus_column, ep, NULL, 0 );
|
|
if ( lm_column_data->auto_tab
|
|
&& ( int ) strlen( xi_text_get( cell_data->xi_text ) )
|
|
>= lm_column_data->text_size - 1 )
|
|
{
|
|
XinEvent ev;
|
|
|
|
MEMCLEAR( ev );
|
|
ev.type = XinEventCharacter;
|
|
ev.v.character.ch = '\t';
|
|
xi_event( lmp->win, &ev );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_vsize_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
rowp: row, to be filled in
|
|
columnp: column, to be filled in
|
|
returns: FALSE if hit test did not fall on place where column could be vertically sized.
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_vsize_hit_test( LM_DATA * lmp, XinEvent * ep, int *rowp, int *columnp )
|
|
{
|
|
int i,
|
|
n,
|
|
v;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
|
|
if ( lmp->lm_column_data[*columnp]->size_rows )
|
|
{
|
|
v = ep->v.mouse.where.v - lmp->rrr_offset - lmp->mlr.top;
|
|
for ( i = 0,
|
|
pix_offsetsp = &lmp->pix_offsets[i],
|
|
pix_heightsp = &lmp->pix_heights[i];
|
|
i < lmp->nbr_realized_rows;
|
|
++i, ++pix_offsetsp, ++pix_heightsp )
|
|
{
|
|
n = *pix_offsetsp + *pix_heightsp;
|
|
if ( v >= n - 3 && v <= n + 1 )
|
|
{
|
|
*rowp = i;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_y
|
|
lmp: current lmp
|
|
y: draw a rubber line at position y
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_y( LM_DATA * lmp, int y )
|
|
{
|
|
#if XIWS != XIWS_WM
|
|
int left,
|
|
right;
|
|
XinDrawTools new_ctools;
|
|
XinPoint pnt;
|
|
XinWindow win = lmp->win;
|
|
|
|
left = lmp->mlr.left;
|
|
right = lmp->mlr.right;
|
|
if ( lmp->pixel_width )
|
|
right = left + lmp->pixel_width + BORDER_WIDTH;
|
|
XinWindowDrawToolsNormalGet( &new_ctools );
|
|
XinWindowDrawToolsSet( win, &new_ctools );
|
|
XinWindowPenSet( win, &rubber_cpen );
|
|
XinWindowDrawModeSet( win, XinDrawModeXor );
|
|
xi_set_clip( win, NULL );
|
|
pnt.h = left;
|
|
pnt.v = y;
|
|
lm_move_to( lmp, pnt, TRUE, FALSE );
|
|
pnt.h = right;
|
|
lm_draw_line( lmp, pnt, TRUE, FALSE );
|
|
#else
|
|
NOREF( lmp );
|
|
NOREF( y );
|
|
#endif
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_y
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
returns: Calculates and returns the Y pixel position of the rubber band line.
|
|
Used only when sizing rows.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calc_y( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
int row = lmp->row_being_sized;
|
|
int temp;
|
|
int min_height_in_pix = 4;
|
|
int v;
|
|
|
|
v = min( lmp->mlr.bottom, ep->v.mouse.where.v ) - lmp->rrr_offset - lmp->mlr.top;
|
|
temp = lmp->pix_offsets[row] + min_height_in_pix;
|
|
temp = max( v, temp );
|
|
return temp;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_vsize_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_vsize_event( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
int y;
|
|
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
y = calc_y( lmp, ep );
|
|
lmp->last_y = y;
|
|
rubber_y( lmp, y );
|
|
break;
|
|
case XinEventMouseMove:
|
|
y = calc_y( lmp, ep );
|
|
rubber_y( lmp, lmp->last_y );
|
|
lmp->last_y = y;
|
|
rubber_y( lmp, y );
|
|
break;
|
|
case XinEventMouseUp:
|
|
{
|
|
int delta,
|
|
row;
|
|
XI_OBJ row_obj;
|
|
|
|
row = lmp->row_being_sized;
|
|
y = calc_y( lmp, ep );
|
|
rubber_y( lmp, lmp->last_y );
|
|
delta = y - lmp->pix_offsets[row] + 1;
|
|
XI_MAKE_ROW( &row_obj, lmp->list_obj, row );
|
|
if ( do_lm_cb( ( LM ) lmp, LM_CB_ROW_SIZE, row, 0, NULL, NULL, delta ) )
|
|
{
|
|
xi_set_row_height( &row_obj, delta );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
}
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_select_cells_hit_test
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
rowp: row number, to be filled in
|
|
columnp: column number, to be filled in
|
|
on_disabled: if TRUE, then the hit was on a disabled column
|
|
returns: TRUE if there was a hit
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_select_cells_hit_test( LM_DATA * lmp, XinEvent * ep, int *rowp,
|
|
int *columnp, BOOLEAN * on_disabled )
|
|
{
|
|
int delta_top,
|
|
column,
|
|
col_offset,
|
|
last_vis,
|
|
row,
|
|
idx;
|
|
LM_COLUMN_DATA *column_data;
|
|
BOOLEAN retval;
|
|
BOOLEAN inv_v,
|
|
inv_h; /* if set to TRUE, then invalid v or invalid h */
|
|
|
|
retval = TRUE;
|
|
if ( columnp )
|
|
*columnp = 0;
|
|
if ( on_disabled )
|
|
*on_disabled = FALSE;
|
|
inv_v = FALSE;
|
|
inv_h = FALSE;
|
|
last_vis = lmp->last_vis;
|
|
delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
|
|
|
|
/* If list has no columns */
|
|
if ( lmp->nbr_columns <= 0 )
|
|
return FALSE;
|
|
|
|
/* If mouse is above the top of the first row */
|
|
if ( ep->v.mouse.where.v < lmp->pix_row1_top - RULE_WIDTH_V -
|
|
RULE_Y_OFFSET_TOP )
|
|
{
|
|
if ( rowp )
|
|
*rowp = 0;
|
|
retval = FALSE;
|
|
inv_v = TRUE;
|
|
}
|
|
|
|
/* if mouse is below the bottom of the list, or if the mouse is below the
|
|
* bottom of the last row if there are fewer rows than can be displayed in
|
|
* the list */
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
if ( ep->v.mouse.where.v >= lmp->mlr.bottom ||
|
|
delta_top > lmp->pix_offsets[idx] + lmp->pix_heights[idx] )
|
|
{
|
|
if ( rowp )
|
|
*rowp = lmp->nbr_realized_rows;
|
|
retval = FALSE;
|
|
inv_v = TRUE;
|
|
}
|
|
|
|
/* if mouse is to the right of the list, or if the mouse is to the right of
|
|
* the rightmost column */
|
|
column_data = lmp->lm_column_data[lmp->nbr_columns - 1];
|
|
if ( ( ep->v.mouse.where.h >= ( lmp->rct.right - lmp->rct.left ) ) ||
|
|
( ep->v.mouse.where.h >= ( column_data->x_pix_pos + column_data->pix_width ) ) )
|
|
{
|
|
if ( columnp )
|
|
*columnp = last_vis + 1;
|
|
retval = FALSE;
|
|
inv_h = TRUE;
|
|
}
|
|
|
|
/* if mouse has a valid y coordinate */
|
|
if ( !inv_v )
|
|
{
|
|
|
|
if ( rowp )
|
|
*rowp = 0;
|
|
retval = FALSE;
|
|
for ( row = 0; row < lmp->nbr_realized_rows; ++row )
|
|
{
|
|
int pix_offset,
|
|
pix_height;
|
|
|
|
pix_offset = lmp->pix_offsets[row];
|
|
pix_height = lmp->pix_heights[row];
|
|
if ( delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= pix_offset + SELECT_CELLS_OFFSET )
|
|
{
|
|
if ( rowp )
|
|
*rowp = row;
|
|
if ( !inv_h )
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if ( delta_top >= ( pix_offset + pix_height ) - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= ( pix_offset + pix_height ) + SELECT_CELLS_OFFSET )
|
|
{
|
|
if ( rowp )
|
|
*rowp = row + 1;
|
|
if ( !inv_h )
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if ( delta_top >= pix_offset &&
|
|
delta_top <= pix_offset + pix_height )
|
|
{
|
|
if ( rowp )
|
|
*rowp = row;
|
|
}
|
|
}
|
|
if ( rowp && !retval && *rowp < lmp->down_row )
|
|
++* rowp;
|
|
}
|
|
|
|
/* if mouse has a valid x coordinate */
|
|
if ( !inv_h )
|
|
{
|
|
column_data = lmp->lm_column_data[0];
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
if ( ( ( !( column_data->attrib & XI_ATR_ENABLED ) || lmp->down_on_disabled ) &&
|
|
( !( column_data->attrib & XI_ATR_SELECTABLE ) ) ) &&
|
|
( ( ep->v.mouse.where.h >= column_data->x_pix_pos ) &&
|
|
( ep->v.mouse.where.h < ( column_data->x_pix_pos + column_data->pix_width ) ) ) )
|
|
{
|
|
if ( columnp )
|
|
*columnp = 0;
|
|
if ( on_disabled )
|
|
*on_disabled = TRUE;
|
|
}
|
|
else if ( ( ep->v.mouse.where.h >= column_data->x_pix_pos ) &&
|
|
( ep->v.mouse.where.h < ( column_data->x_pix_pos + col_offset ) ) )
|
|
{
|
|
if ( columnp )
|
|
*columnp = 0;
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN found = FALSE;
|
|
int last_col;
|
|
|
|
last_col = -1;
|
|
for ( column = 0; column < lmp->nbr_columns; column++ )
|
|
{
|
|
int temp;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
if ( ( ( !( column_data->attrib & XI_ATR_ENABLED ) || lmp->down_on_disabled ) &&
|
|
( !( column_data->attrib & XI_ATR_SELECTABLE ) ) ) &&
|
|
( ( ep->v.mouse.where.h >= column_data->x_pix_pos ) &&
|
|
( ep->v.mouse.where.h <
|
|
( column_data->x_pix_pos + column_data->pix_width ) ) ) )
|
|
{
|
|
if ( columnp )
|
|
*columnp = column;
|
|
if ( on_disabled )
|
|
*on_disabled = TRUE;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
temp = column_data->x_pix_pos +
|
|
col_offset +
|
|
column_data->pix_width - SELECT_CELLS_OFFSET;
|
|
if ( ep->v.mouse.where.h >= temp &&
|
|
ep->v.mouse.where.h < ( temp + col_offset * 2
|
|
+ 2 * SELECT_CELLS_OFFSET
|
|
+ RULE_WIDTH_V ) )
|
|
{
|
|
if ( columnp )
|
|
*columnp = column + 1;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
if ( ep->v.mouse.where.h >= temp )
|
|
last_col = column;
|
|
}
|
|
if ( !found )
|
|
{
|
|
retval = FALSE;
|
|
if ( columnp )
|
|
{
|
|
if ( ( last_col + 1 ) < lmp->down_column )
|
|
*columnp = last_col + 2;
|
|
else
|
|
*columnp = last_col + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* If v is not invalid, and if h is not invalid, and if the column is valid,
|
|
* then if the column is enabled, then the hit test must be within a range of
|
|
* the rules. If the column is not enabled, then the hit test may be anywhere
|
|
* within the cell. */
|
|
if ( !inv_v )
|
|
{
|
|
BOOLEAN enabled_col = FALSE;
|
|
|
|
if ( columnp && !inv_h )
|
|
{
|
|
if ( *columnp >= lmp->nbr_columns )
|
|
enabled_col = FALSE;
|
|
else
|
|
enabled_col = ( lmp->lm_column_data[*columnp]->attrib & XI_ATR_ENABLED &&
|
|
!lmp->down_on_disabled );
|
|
if ( enabled_col )
|
|
{
|
|
delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
|
|
retval = FALSE;
|
|
for ( row = 0; row < lmp->nbr_realized_rows; ++row )
|
|
{
|
|
int pix_offset,
|
|
pix_height;
|
|
|
|
pix_offset = lmp->pix_offsets[row];
|
|
pix_height = lmp->pix_heights[row];
|
|
if ( delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= pix_offset + SELECT_CELLS_OFFSET )
|
|
{
|
|
if ( rowp )
|
|
*rowp = row;
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if ( delta_top >= ( pix_offset + pix_height ) - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= ( pix_offset + pix_height ) + SELECT_CELLS_OFFSET )
|
|
{
|
|
if ( rowp )
|
|
*rowp = row + 1;
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: invert_selection
|
|
lmp: current lmp
|
|
r: row
|
|
c: column
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
invert_selection( LM_DATA * lmp, int r, int c, BOOLEAN v_scrolled )
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lm_get_attrib( ( LM ) lmp, LM_CELL, r, c, v_scrolled );
|
|
if ( attrib & LM_CELL_ATR_SELECTED )
|
|
lm_set_attrib( ( LM ) lmp, LM_CELL, r, c, v_scrolled,
|
|
attrib & ~LM_CELL_ATR_SELECTED, FALSE );
|
|
else
|
|
lm_set_attrib( ( LM ) lmp, LM_CELL, r, c, v_scrolled,
|
|
attrib | LM_CELL_ATR_SELECTED, FALSE );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: in_rct
|
|
rct: rectangle
|
|
r: row
|
|
c: column
|
|
returns: TRUE if c and r are in rct
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
in_rct( XinRect * rct, int r, int c )
|
|
{
|
|
if ( c >= rct->left && c < rct->right && r >= rct->top && r < rct->bottom )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_select_cell_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_select_cell_event( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
int row,
|
|
column;
|
|
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
if ( !ep->v.mouse.shift )
|
|
{
|
|
int r,
|
|
c;
|
|
|
|
for ( r = 0; r < lmp->nbr_realized_rows; ++r )
|
|
for ( c = 0; c < lmp->nbr_columns; ++c )
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lm_get_attrib( ( LM ) lmp, LM_CELL, r, c, FALSE );
|
|
if ( attrib & LM_CELL_ATR_SELECTED )
|
|
lm_set_attrib( ( LM ) lmp, LM_CELL, r, c, FALSE,
|
|
attrib & ~LM_CELL_ATR_SELECTED, FALSE );
|
|
}
|
|
}
|
|
break;
|
|
case XinEventMouseMove:
|
|
case XinEventMouseUp:
|
|
{
|
|
int last_cur_row,
|
|
last_cur_column,
|
|
r,
|
|
c,
|
|
down_row,
|
|
down_column;
|
|
XinRect old_rct,
|
|
new_rct,
|
|
enclosing_rct;
|
|
|
|
lm_select_cells_hit_test( lmp, ep, &row, &column, NULL );
|
|
last_cur_row = lmp->cur_row;
|
|
last_cur_column = lmp->cur_column;
|
|
down_row = lmp->down_row;
|
|
down_column = lmp->down_column;
|
|
if ( lmp->down_on_disabled )
|
|
{
|
|
if ( ep->type == XinEventMouseUp )
|
|
lmp->down_on_disabled = FALSE;
|
|
if ( row >= lmp->down_row )
|
|
lmp->cur_row = row + 1;
|
|
else
|
|
lmp->cur_row = row;
|
|
if ( column >= lmp->down_column )
|
|
lmp->cur_column = column + 1;
|
|
else
|
|
lmp->cur_column = column;
|
|
}
|
|
else
|
|
{
|
|
lmp->cur_row = row;
|
|
lmp->cur_column = column;
|
|
}
|
|
if ( lmp->cur_row == last_cur_row && lmp->cur_column == last_cur_column &&
|
|
( ep->type == XinEventMouseMove || ep->type == XinEventMouseUp ) )
|
|
break;
|
|
old_rct.left = min( down_column, last_cur_column );
|
|
old_rct.right = max( down_column, last_cur_column );
|
|
old_rct.top = min( down_row, last_cur_row );
|
|
old_rct.bottom = max( down_row, last_cur_row );
|
|
new_rct.left = min( down_column, lmp->cur_column );
|
|
new_rct.right = max( down_column, lmp->cur_column );
|
|
new_rct.top = min( down_row, lmp->cur_row );
|
|
new_rct.bottom = max( down_row, lmp->cur_row );
|
|
enclosing_rct.top = min( old_rct.top, new_rct.top );
|
|
enclosing_rct.bottom = max( old_rct.bottom, new_rct.bottom );
|
|
enclosing_rct.left = min( old_rct.left, new_rct.left );
|
|
enclosing_rct.right = max( old_rct.right, new_rct.right );
|
|
for ( c = enclosing_rct.left; c <= enclosing_rct.right; ++c )
|
|
{
|
|
for ( r = enclosing_rct.top; r <= enclosing_rct.bottom; ++r )
|
|
{
|
|
if ( ( in_rct( &old_rct, r, c ) &&
|
|
in_rct( &new_rct, r, c ) ) ||
|
|
( !in_rct( &old_rct, r, c ) &&
|
|
!in_rct( &new_rct, r, c ) ) )
|
|
continue;
|
|
if ( r >= lmp->nbr_realized_rows || c >= lmp->nbr_columns ||
|
|
r < 0 || c < 0 )
|
|
continue;
|
|
invert_selection( lmp, r, c, FALSE );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_event
|
|
lm: current lm
|
|
ep: xvt event
|
|
return: TRUE if event is consumed
|
|
-------------------------------------------------------------------------*/
|
|
#define DRAG_MARGIN 5
|
|
|
|
int
|
|
lm_event( XI_OBJ * itf, LM lm, XinEvent * ep )
|
|
{
|
|
int row,
|
|
column;
|
|
LM_DATA *lmp = LMP( lm );
|
|
BOOLEAN send_event = FALSE;
|
|
int retval = 1;
|
|
XinEvent oevt;
|
|
BOOLEAN ep_needs_restore = FALSE;
|
|
|
|
oevt = *ep;
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
case XinEventMouseMove:
|
|
case XinEventMouseUp:
|
|
{
|
|
XinRect rct;
|
|
|
|
if ( lmp->attrib & XI_ATR_VISIBLE )
|
|
{
|
|
/* COORDINATE CONVERSION changes horizontal coordinates - moves mouse
|
|
* to the right - increases where.h if where.h is > lmp->vir_left, so
|
|
* that where.h is in the correct virtual horizontal space - also
|
|
* makes where.h be relative to the list, not the window. */
|
|
lm_get_rect( lm, LM_LIST, 0, &rct );
|
|
if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) ||
|
|
lmp->selecting_cells || lmp->sizing_column || lmp->moving_column ||
|
|
lmp->down_in_btn || lmp->selecting_text || lmp->sizing_row ||
|
|
lmp->dragging_row || lmp->down_in_heading )
|
|
{
|
|
if ( ep->type == XinEventMouseDown )
|
|
{
|
|
if ( ep->v.mouse.where.h >= lmp->vir_left )
|
|
lmp->down_in_hscrolling = TRUE;
|
|
else
|
|
lmp->down_in_hscrolling = FALSE;
|
|
}
|
|
if ( !lmp->sizing_column )
|
|
{
|
|
if ( ( lmp->pixel_width && ( ep->v.mouse.where.h >= lmp->vir_left ) ) )
|
|
{
|
|
ep->v.mouse.where.h += lmp->delta_x;
|
|
lmp->in_hscrolling = TRUE;
|
|
}
|
|
else
|
|
lmp->in_hscrolling = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( lmp->down_in_hscrolling )
|
|
ep->v.mouse.where.h += lmp->delta_x;
|
|
}
|
|
ep->v.mouse.where.h -= lmp->rct.left;
|
|
ep_needs_restore = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*ep = oevt;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ep = oevt;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventPaint:
|
|
/* the following code sends the event directly on to redraw_cell if text
|
|
* is being scrolled in a text object. This speeds horizontal scrolling.
|
|
* see also lm_text_scrolling. */
|
|
if ( lmp->text_scrolling )
|
|
{
|
|
int row,
|
|
col;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &row, &col, &v_scrolled );
|
|
draw_cell_range( lmp, row, row, col, col, FALSE );
|
|
if ( lm_focus_state_get( lmp ) != LM_FOCUS_VISIBLE )
|
|
send_cell_event( lm, &oevt, FALSE, TRUE );
|
|
lmp->text_scrolling = FALSE;
|
|
}
|
|
else
|
|
{
|
|
draw_lm( lm, TRUE );
|
|
/* if ( lm_focus_state_get(lmp) != LM_FOCUS_VISIBLE ) */
|
|
send_cell_event( lm, &oevt, FALSE, TRUE );
|
|
}
|
|
retval = 0;
|
|
break;
|
|
case XinEventResize:
|
|
{
|
|
int new_height,
|
|
new_width;
|
|
XinRect hr,
|
|
vr,
|
|
cr;
|
|
XI_OBJ *list_obj;
|
|
|
|
if ( lmp->resize_with_window )
|
|
{
|
|
XinRect rct,
|
|
wrct;
|
|
BOOLEAN replace_focus = FALSE;
|
|
|
|
list_obj = lmp->list_obj;
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
lm_focus_cell_invis_make( lmp );
|
|
else
|
|
{
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
XI_OBJ *focus_obj = xi_get_focus(list_obj->itf);
|
|
if (focus_obj->type == XIT_CELL && focus_obj->parent == list_obj)
|
|
replace_focus = TRUE;
|
|
if ( !xi_move_focus( list_obj->itf ) )
|
|
{
|
|
retval = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
xi_get_hsb_rect( list_obj, &hr );
|
|
xi_get_sb_rect( list_obj, &vr );
|
|
XinWindowRectGet( lmp->win, &cr );
|
|
new_height = cr.bottom - lmp->pix_top;
|
|
new_width = cr.right - lmp->rct.left;
|
|
xi_set_list_size( list_obj, new_height, new_width );
|
|
if ( ( BOOLEAN ) xi_get_pref( XI_PREF_LIMIT_MIN_WIN_SIZE ) )
|
|
{
|
|
xi_get_rect( list_obj, &rct );
|
|
if ( abs( rct.bottom - cr.bottom ) > 4 ||
|
|
abs( rct.right - cr.right ) > 4 )
|
|
{
|
|
wrct = cr;
|
|
wrct.bottom = max( rct.bottom, cr.bottom );
|
|
wrct.right = max( rct.right, cr.right );
|
|
if ( wrct.bottom != cr.bottom || wrct.right != cr.right )
|
|
{
|
|
XinWindowPointsTranslate( lmp->win, XinWindowParentGet( lmp->win ), ( XinPoint * ) & wrct, 2 );
|
|
XinWindowRectSet( lmp->win, &wrct );
|
|
}
|
|
}
|
|
}
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
else if (replace_focus)
|
|
xi_move_focus( list_obj );
|
|
}
|
|
retval = 0;
|
|
break;
|
|
}
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
{
|
|
int hit_test_value;
|
|
BOOLEAN is_vis,
|
|
is_hit,
|
|
is_part_vis;
|
|
|
|
if ( ep->v.mouse.button > 0 )
|
|
break;
|
|
|
|
if ( lmp->single_select && lmp->position_by_typing_cid > 0 && lmp->position_by_typing_buf != NULL )
|
|
lmp->position_by_typing_buf[0] = '\0';
|
|
|
|
hit_test_value = lm_hit_test( lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis );
|
|
/* The row scrolled during the XinEventMouseDown */
|
|
if ( is_part_vis && ep->type == XinEventMouseDouble )
|
|
--row;
|
|
if ( is_part_vis && ep->type != XinEventMouseDouble )
|
|
{
|
|
XinEvent lep;
|
|
LM_SCROLL_ARG lm_scroll_arg;
|
|
static BOOLEAN in_here = FALSE;
|
|
|
|
if ( in_here )
|
|
return FALSE;
|
|
MEMCLEAR( lm_scroll_arg );
|
|
lm_scroll_arg.lm = lm;
|
|
lm_scroll_arg.nbr_lines = 1;
|
|
/* lm_scroll_arg.percent = 0; lm_scroll_arg.same_cell = 0;
|
|
* lm_scroll_arg.rec = 0L; lm_scroll_arg.have_rec = FALSE;
|
|
* lm_scroll_arg.color = 0L; lm_scroll_arg.attrib = 0L;
|
|
* lm_scroll_arg.row_height = 0; lm_scroll_arg.rec_at_top = FALSE; */
|
|
|
|
lm_focus_cell_invis_make( lmp );
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
lm_make_rrr_room_pix( lmp, 0, FALSE );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
|
|
lm_scroll( &lm_scroll_arg );
|
|
lep = oevt;
|
|
lep.v.mouse.where.v -= lm_scroll_arg.pixels_scrolled;
|
|
in_here = TRUE;
|
|
lm_event( itf, lm, &lep );
|
|
in_here = FALSE;
|
|
return TRUE;
|
|
}
|
|
if ( is_hit )
|
|
{
|
|
if ( lm_vsize_hit_test( lmp, ep, &row, &column ) )
|
|
{
|
|
XI_OBJ *itf,
|
|
*list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if ( list && xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
xi_set_trap_obj( list );
|
|
lmp->row_being_sized = row;
|
|
lmp->sizing_row = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_vsize_event( lmp, ep );
|
|
}
|
|
else
|
|
{
|
|
if ( list && xi_move_focus( itf ) )
|
|
{
|
|
xi_set_trap_obj( list );
|
|
lmp->row_being_sized = row;
|
|
lmp->sizing_row = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_vsize_event( lmp, ep );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if ( lmp->select_cells )
|
|
{
|
|
int row,
|
|
column;
|
|
BOOLEAN on_disabled;
|
|
|
|
if ( lm_select_cells_hit_test( lmp, ep, &row, &column, &on_disabled ) )
|
|
{
|
|
XI_OBJ *list;
|
|
|
|
list = lmp->list_obj;
|
|
xi_set_trap_obj( list );
|
|
lmp->selecting_cells = TRUE;
|
|
lmp->down_row = row;
|
|
lmp->cur_row = row;
|
|
lmp->down_column = column;
|
|
lmp->cur_column = column;
|
|
lmp->down_on_disabled = on_disabled;
|
|
lm_select_cell_event( lmp, ep );
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
if ( on_disabled )
|
|
{
|
|
invert_selection( lmp, row, column, FALSE );
|
|
lmp->cur_row = row + 1;
|
|
lmp->cur_column = column + 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* check for cell button hit */
|
|
if ( hit_test_value == 5 )
|
|
if ( LIST_IS_ENABLED( lm ) )
|
|
lm_cell_btn_event( lmp, ep, &oevt );
|
|
|
|
/* check for focus acquisition */
|
|
if ( hit_test_value == 1 )
|
|
{
|
|
if ( row == -1 )
|
|
{
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
COLUMN_IS_SELECTABLE( lm, column ) &&
|
|
( ep->type == XinEventMouseDouble ||
|
|
( ep->type == XinEventMouseDown && !
|
|
lmp->movable_columns && !xi_get_pref( XI_PREF_SINGLE_CLICK_COL_SELECT ) )
|
|
) )
|
|
{
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
attrib = lm_get_attrib( lm, LM_COLUMN, column, 0, FALSE );
|
|
if ( ep->type == XinEventMouseDouble && !lmp->movable_columns )
|
|
attrib |= LM_COL_ATR_SELECTED;
|
|
else
|
|
{
|
|
if ( attrib & LM_COL_ATR_SELECTED )
|
|
attrib &= ~LM_COL_ATR_SELECTED;
|
|
else
|
|
attrib |= LM_COL_ATR_SELECTED;
|
|
}
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) 255;
|
|
lm_cb_data.column = ( unsigned char ) column;
|
|
lm_cb_data.v.select.selected =
|
|
( ( attrib & LM_COL_ATR_SELECTED ) != 0 );
|
|
lm_cb_data.v.select.dbl_click =
|
|
( ep->type == XinEventMouseDouble );
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
if ( !lm_cb_data.v.select.refused )
|
|
lm_set_attrib( lm, LM_COLUMN, column, 0, FALSE, attrib,
|
|
FALSE );
|
|
}
|
|
else if ( LIST_IS_ENABLED( lm ) &&
|
|
COLUMN_IS_SELECTABLE( lm, column ) &&
|
|
( ep->type == XinEventMouseDouble ||
|
|
( ep->type == XinEventMouseDown &&
|
|
!lmp->movable_columns && xi_get_pref( XI_PREF_SINGLE_CLICK_COL_SELECT ) )
|
|
) )
|
|
{ /* Select on the mouse up if the mouse is still
|
|
* in the heading. */
|
|
XinRect rct;
|
|
|
|
lmp->down_in_heading = TRUE;
|
|
lmp->column_being_moved = column;
|
|
lmp->down_pt = ep->v.mouse.where;
|
|
lmp->lm_column_data[column]->pushed = TRUE;
|
|
xi_set_trap_obj( lmp->list_obj );
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_get_rect( lm, LM_COLUMN, column, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
}
|
|
|
|
if ( LIST_IS_ENABLED( lm ) && COLUMN_IS_SELECTABLE( lm, column ) &&
|
|
ep->type == XinEventMouseDown && lmp->movable_columns &&
|
|
xi_get_pref( XI_PREF_SINGLE_CLICK_COL_SELECT ) )
|
|
{
|
|
/* If the mouse doesn't move much, we will select on the up. If
|
|
* it does move, we will do a column move. */
|
|
XinRect rct;
|
|
|
|
lmp->down_in_heading = TRUE;
|
|
lmp->column_being_moved = column;
|
|
lmp->down_pt = ep->v.mouse.where;
|
|
lmp->lm_column_data[column]->pushed = TRUE;
|
|
xi_set_trap_obj( lmp->list_obj );
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_get_rect( lm, LM_COLUMN, column, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
}
|
|
else if ( LIST_IS_ENABLED( lm ) &&
|
|
( ep->type == XinEventMouseDown ||
|
|
( ep->type == XinEventMouseDouble &&
|
|
!COLUMN_IS_SELECTABLE( lm, column ) ) ) &&
|
|
lmp->movable_columns )
|
|
{
|
|
XI_OBJ *itf,
|
|
*list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if ( list && xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
xi_set_trap_obj( list );
|
|
lmp->column_being_moved = column;
|
|
lmp->moving_column = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_move_event( lmp, ep );
|
|
}
|
|
else
|
|
{
|
|
if ( list && xi_move_focus( itf ) )
|
|
{
|
|
xi_set_trap_obj( list );
|
|
lmp->column_being_moved = column;
|
|
lmp->moving_column = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_move_event( lmp, ep );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( CELL_IS_SELECTABLE( lm, row, column ) )
|
|
{
|
|
lmp->down_pt = ep->v.mouse.where;
|
|
lmp->rec_being_moved = lmp->recs[row];
|
|
lmp->drag_row_height = lmp->pix_heights[row];
|
|
lmp->down_in_row = TRUE;
|
|
xi_set_trap_obj( lmp->list_obj );
|
|
if ( lmp->single_select )
|
|
{
|
|
lmp->list_obj->v.list->in_select_process = TRUE;
|
|
xi_move_focus( lmp->list_obj );
|
|
select_row( lm, row, column, ( BOOLEAN ) ( ep->type == XinEventMouseDouble ) );
|
|
if ( xi_is_itf( itf ) )
|
|
lmp->list_obj->v.list->in_select_process = FALSE;
|
|
}
|
|
else
|
|
{
|
|
unsigned long attrib;
|
|
attrib = lm_get_attrib( lm, LM_ROW, row, 0, FALSE );
|
|
if ( lmp->drag_and_drop_rows && ( attrib & LM_ROW_ATR_SELECTED ) != 0
|
|
&& !ep->v.mouse.shift )
|
|
{
|
|
lmp->delay_select = TRUE;
|
|
lmp->delay_row = row;
|
|
lmp->delay_column = column;
|
|
lmp->delay_dbl = (ep->type == XinEventMouseDouble);
|
|
}
|
|
else
|
|
send_select_event( lm, row, column, ep, attrib );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN gaining_focus = FALSE;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][column];
|
|
|
|
if ( !is_vis )
|
|
break;
|
|
|
|
if ( !cell_data->icon_rid && cell_data->bitmap == NULL &&
|
|
!cell_data->button_full_cell )
|
|
{
|
|
/* set this flag here, not later! */
|
|
lmp->have_mouse = TRUE;
|
|
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_NOWHERE )
|
|
{
|
|
send_event = do_lm_cb( lm, LM_CB_FOCUS, row, column,
|
|
NULL, NULL, 0 );
|
|
gaining_focus = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( !lm_focus_cell_has( lmp, row, column, FALSE ) )
|
|
{
|
|
send_event = do_lm_cb( lm, LM_CB_FOCUS, row, column, NULL, NULL, 0 );
|
|
/* send_event = FALSE if refused */
|
|
|
|
gaining_focus = send_event;
|
|
}
|
|
else
|
|
send_event = TRUE;
|
|
}
|
|
if ( send_event )
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if ( ( lmp->lm_column_data[focus_column]->attrib
|
|
& LM_COL_ATR_AUTOSELECT )
|
|
&& xi_get_pref( XI_PREF_AUTOSEL_ON_MOUSE )
|
|
&& gaining_focus )
|
|
;
|
|
else
|
|
{
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lmp->selecting_text = TRUE;
|
|
send_cell_event( lm, &oevt, gaining_focus, TRUE );
|
|
}
|
|
}
|
|
else
|
|
lmp->have_mouse = FALSE;
|
|
if ( ep->type == XinEventMouseDouble )
|
|
do_lm_cb( lm, LM_CB_DBL, row, column, NULL, NULL, 0 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
lmp->sizable_columns &&
|
|
lm_size_hit_test( lm, ep, &column ) )
|
|
{
|
|
XI_OBJ *itf,
|
|
*list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if ( list && xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
xi_set_trap_obj( list );
|
|
lmp->column_being_sized = column;
|
|
lmp->sizing_column = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_size_event( lmp, ep );
|
|
}
|
|
else
|
|
{
|
|
if ( list && xi_move_focus( itf ) )
|
|
{
|
|
xi_set_trap_obj( list );
|
|
lmp->column_being_sized = column;
|
|
lmp->sizing_column = TRUE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_size_event( lmp, ep );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
retval = 0;
|
|
}
|
|
break;
|
|
}
|
|
case XinEventMouseUp:
|
|
lmp->down_in_row = FALSE;
|
|
if ( lmp->single_select && lmp->position_by_typing_cid > 0 && lmp->position_by_typing_buf != NULL )
|
|
lmp->position_by_typing_buf[0] = '\0';
|
|
if ( lmp->selecting_cells )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_select_cell_event( lmp, ep );
|
|
XinWindowMouseRelease( );
|
|
lmp->selecting_cells = FALSE;
|
|
lmp->down_row = 0;
|
|
lmp->down_column = 0;
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) 255;
|
|
lm_cb_data.column = ( unsigned char ) 255;
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = FALSE;
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
}
|
|
if ( lmp->sizing_column )
|
|
{
|
|
lm_size_event( lmp, ep );
|
|
XinWindowMouseRelease( );
|
|
lmp->sizing_column = FALSE;
|
|
lmp->column_being_sized = 0;
|
|
break;
|
|
}
|
|
if ( lmp->sizing_row )
|
|
{
|
|
lm_vsize_event( lmp, ep );
|
|
XinWindowMouseRelease( );
|
|
lmp->sizing_row = FALSE;
|
|
lmp->row_being_sized = 0;
|
|
break;
|
|
}
|
|
if ( lmp->moving_column )
|
|
{
|
|
lm_move_event( lmp, ep );
|
|
XinWindowMouseRelease( );
|
|
lmp->moving_column = FALSE;
|
|
lmp->column_being_moved = 0;
|
|
break;
|
|
}
|
|
if ( lmp->down_in_btn )
|
|
{
|
|
lm_cell_btn_event( lmp, ep, &oevt );
|
|
XinWindowMouseRelease( );
|
|
lmp->down_in_btn = FALSE;
|
|
lmp->btn_down = FALSE;
|
|
break;
|
|
}
|
|
if ( lmp->dragging_row )
|
|
{
|
|
lm_drag_row_event( itf, lmp, ep, &oevt );
|
|
XinWindowMouseRelease( );
|
|
lmp->dragging_row = FALSE;
|
|
break;
|
|
}
|
|
if ( lmp->delay_select )
|
|
{
|
|
unsigned long attrib = lm_get_attrib( lm, LM_ROW, lmp->delay_row, 0, FALSE );
|
|
|
|
lmp->delay_select = FALSE;
|
|
if (lmp->delay_dbl)
|
|
{
|
|
XinEvent ev;
|
|
MEMCLEAR( ev );
|
|
ev.type = XinEventMouseDouble;
|
|
lmp->delay_dbl = FALSE;
|
|
send_select_event( lm, lmp->delay_row, lmp->delay_column, &ev, attrib );
|
|
}
|
|
else
|
|
send_select_event( lm, lmp->delay_row, lmp->delay_column, ep, attrib );
|
|
break;
|
|
}
|
|
if ( lmp->down_in_heading )
|
|
{
|
|
/* If the mouse is still in the heading, select the col. */
|
|
int hit_test_value;
|
|
BOOLEAN is_vis,
|
|
is_hit,
|
|
is_part_vis;
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed = FALSE;
|
|
hit_test_value = lm_hit_test( lm, ep, &oevt, &row, &column, &is_vis,
|
|
&is_hit, &is_part_vis );
|
|
if ( hit_test_value == 1 && row == -1 && column == lmp->column_being_moved )
|
|
{
|
|
attrib = lm_get_attrib( lm, LM_COLUMN, column, 0, FALSE );
|
|
if ( attrib & LM_COL_ATR_SELECTED )
|
|
attrib &= ~LM_COL_ATR_SELECTED;
|
|
else
|
|
attrib |= LM_COL_ATR_SELECTED;
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) 255;
|
|
lm_cb_data.column = ( unsigned char ) lmp->column_being_moved;
|
|
lm_cb_data.v.select.selected =
|
|
( ( attrib & LM_COL_ATR_SELECTED ) != 0 );
|
|
lm_cb_data.v.select.dbl_click = FALSE;
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
if ( !lm_cb_data.v.select.refused )
|
|
lm_set_attrib( lm, LM_COLUMN, column, 0, FALSE, attrib,
|
|
FALSE );
|
|
}
|
|
else
|
|
{
|
|
XinRect rct;
|
|
|
|
lm_get_rect( lm, LM_COLUMN, lmp->column_being_moved, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
}
|
|
XinWindowMouseRelease( );
|
|
lmp->down_in_heading = FALSE;
|
|
lmp->column_being_moved = 0;
|
|
break;
|
|
}
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
send_cell_event( lm, &oevt, FALSE, TRUE );
|
|
lmp->selecting_text = FALSE;
|
|
XinWindowMouseRelease( );
|
|
lmp->have_mouse = FALSE;
|
|
break;
|
|
}
|
|
break;
|
|
case XinEventMouseMove:
|
|
{
|
|
BOOLEAN is_vis,
|
|
is_hit,
|
|
is_part_vis;
|
|
|
|
if ( !( lmp->attrib & XI_ATR_VISIBLE ) )
|
|
{
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
if ( lmp->selecting_cells )
|
|
{
|
|
lm_select_cell_event( lmp, ep );
|
|
break;
|
|
}
|
|
if ( lmp->sizing_column )
|
|
{
|
|
lm_size_event( lmp, ep );
|
|
break;
|
|
}
|
|
if ( lmp->sizing_row )
|
|
{
|
|
lm_vsize_event( lmp, ep );
|
|
break;
|
|
}
|
|
if ( lmp->moving_column )
|
|
{
|
|
lm_move_event( lmp, ep );
|
|
break;
|
|
}
|
|
if ( lmp->down_in_btn )
|
|
{
|
|
lm_cell_btn_event( lmp, ep, &oevt );
|
|
break;
|
|
}
|
|
if ( lmp->dragging_row )
|
|
{
|
|
lm_drag_row_event( itf, lmp, ep, &oevt );
|
|
break;
|
|
}
|
|
if ( lmp->down_in_row && lmp->drag_and_drop_rows
|
|
&& ( ep->v.mouse.where.v > lmp->down_pt.v + DRAG_MARGIN
|
|
|| ep->v.mouse.where.v < lmp->down_pt.v - DRAG_MARGIN
|
|
|| ep->v.mouse.where.h > lmp->down_pt.h + DRAG_MARGIN
|
|
|| ep->v.mouse.where.h < lmp->down_pt.h - DRAG_MARGIN ) )
|
|
{ /* start row dragging */
|
|
lmp->down_in_row = FALSE;
|
|
lmp->delay_select = FALSE;
|
|
XinWindowMouseTrap( lmp->win, TRUE );
|
|
lm_drag_row_event( itf, lmp, ep, &oevt );
|
|
}
|
|
if ( lmp->down_in_heading && lmp->movable_columns
|
|
&& ( ep->v.mouse.where.v > lmp->down_pt.v + DRAG_MARGIN
|
|
|| ep->v.mouse.where.v < lmp->down_pt.v - DRAG_MARGIN
|
|
|| ep->v.mouse.where.h > lmp->down_pt.h + DRAG_MARGIN
|
|
|| ep->v.mouse.where.h < lmp->down_pt.h - DRAG_MARGIN ) )
|
|
{
|
|
/* The user moved far enough to switch to moving the column. */
|
|
XI_OBJ *itf,
|
|
*list;
|
|
XinPoint where;
|
|
XinRect rct;
|
|
|
|
lmp->down_in_heading = FALSE;
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed = FALSE;
|
|
lm_get_rect( lm, LM_COLUMN, lmp->column_being_moved, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if ( list && xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
lmp->moving_column = TRUE;
|
|
ep->type = XinEventMouseDown;
|
|
where = ep->v.mouse.where;
|
|
ep->v.mouse.where = lmp->down_pt;
|
|
lm_move_event( lmp, ep );
|
|
ep->type = XinEventMouseMove;
|
|
ep->v.mouse.where = where;
|
|
lm_move_event( lmp, ep );
|
|
}
|
|
else
|
|
{
|
|
if ( list && xi_move_focus( itf ) )
|
|
{
|
|
lmp->moving_column = TRUE;
|
|
ep->type = XinEventMouseDown;
|
|
where = ep->v.mouse.where;
|
|
ep->v.mouse.where = lmp->down_pt;
|
|
lm_move_event( lmp, ep );
|
|
ep->type = XinEventMouseMove;
|
|
ep->v.mouse.where = where;
|
|
lm_move_event( lmp, ep );
|
|
}
|
|
else
|
|
lmp->column_being_moved = 0;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
int hit_test_value;
|
|
BOOLEAN is_vis,
|
|
is_hit,
|
|
is_part_vis;
|
|
|
|
hit_test_value = lm_hit_test( lm, ep, &oevt, &row, &column, &is_vis,
|
|
&is_hit, &is_part_vis );
|
|
if ( lmp->down_in_heading && !lmp->movable_columns &&
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed == TRUE &&
|
|
( hit_test_value != 1 || row != -1 || column != lmp->column_being_moved ) )
|
|
{
|
|
XinRect rct;
|
|
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed = FALSE;
|
|
lm_get_rect( lm, LM_COLUMN, lmp->column_being_moved, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
}
|
|
else if ( lmp->down_in_heading && !lmp->movable_columns &&
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed == FALSE &&
|
|
( hit_test_value == 1 && row == -1 && column == lmp->column_being_moved ) )
|
|
{
|
|
XinRect rct;
|
|
|
|
lmp->lm_column_data[lmp->column_being_moved]->pushed = TRUE;
|
|
lm_get_rect( lm, LM_COLUMN, lmp->column_being_moved, &rct );
|
|
draw_column_headings( lmp, &rct );
|
|
}
|
|
}
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
send_cell_event( lm, &oevt, FALSE, TRUE );
|
|
retval = lm_hit_test( lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis );
|
|
if ( is_part_vis )
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lmp->lm_column_data[column]->attrib;
|
|
if ( attrib & XI_ATR_SELECTABLE )
|
|
return 0;
|
|
if ( !retval )
|
|
retval = 1;
|
|
return retval;
|
|
}
|
|
if ( is_hit )
|
|
{
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
lm_vsize_hit_test( lmp, ep, &row, &column ) )
|
|
{
|
|
*ep = oevt;
|
|
return 6;
|
|
}
|
|
}
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
lmp->select_cells &&
|
|
lm_select_cells_hit_test( lmp, ep, NULL, NULL, NULL ) )
|
|
{
|
|
*ep = oevt;
|
|
return 4;
|
|
}
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
lmp->sizable_columns &&
|
|
lm_size_hit_test( lm, ep, &column ) )
|
|
{
|
|
*ep = oevt;
|
|
return 2;
|
|
}
|
|
if ( retval )
|
|
{
|
|
if ( !is_vis )
|
|
{
|
|
*ep = oevt;
|
|
return 5;
|
|
}
|
|
if ( CELL_IS_SELECTABLE( lm, row, column ) )
|
|
retval = 5;
|
|
if ( row == -1 )
|
|
retval = 5;
|
|
if ( row >= 0 && ( lmp->cell_data[row][column].icon_rid
|
|
|| lmp->cell_data[row][column].bitmap != NULL ) )
|
|
retval = 5;
|
|
if ( row >= 0 && lmp->cell_data[row][column].button_full_cell )
|
|
retval = 5;
|
|
if ( LIST_IS_ENABLED( lm ) &&
|
|
lmp->movable_columns &&
|
|
lm_hit_test( lm, ep, &oevt, &row, &column, NULL, NULL, NULL ) )
|
|
if ( row == -1 )
|
|
retval = 3;
|
|
}
|
|
break;
|
|
}
|
|
case XinEventCharacter:
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED )
|
|
&& ep->v.character.ch != XI_KEY_NEXT
|
|
&& ep->v.character.ch != XI_KEY_PREV )
|
|
{
|
|
int row,
|
|
column;
|
|
BOOLEAN v_scrolled;
|
|
LM_FOCUS_CELL_VISIBLE_FORCE_ARGS args;
|
|
|
|
lm_focus_cell_get( lmp, &row, &column, &v_scrolled );
|
|
MEMCLEAR( args );
|
|
args.lmp = lmp;
|
|
args.row = row;
|
|
args.column = column;
|
|
args.vert_scrolled = v_scrolled;
|
|
lm_focus_cell_visible_force( &args );
|
|
}
|
|
{
|
|
long button_key;
|
|
BOOLEAN shift,
|
|
control,
|
|
alt;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN h_scrolled;
|
|
|
|
button_key = xi_get_pref( XI_PREF_BUTTON_KEY );
|
|
shift = ( BOOLEAN ) ( ( button_key & XI_MOD_SHIFT ) != 0 );
|
|
control = ( BOOLEAN ) ( ( button_key & XI_MOD_CONTROL ) != 0 );
|
|
alt = ( BOOLEAN ) ( ( button_key & XI_MOD_ALT ) != 0 );
|
|
button_key &= 0xffffffL;
|
|
if ( button_key == ep->v.character.ch &&
|
|
shift == ep->v.character.shift &&
|
|
control == ep->v.character.control &&
|
|
alt == ep->v.character.alt )
|
|
{
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &h_scrolled )
|
|
&& lmp->cell_data[focus_row][focus_column].button )
|
|
do_lm_cb( ( LM ) lmp, LM_CB_CELL_BTN, focus_row, focus_column, ep, NULL, 0 );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( lmp->single_select )
|
|
{
|
|
BOOLEAN clear_buffer = TRUE;
|
|
switch ( ep->v.character.ch )
|
|
{
|
|
case XI_KEY_UP:
|
|
{
|
|
int cur_row = find_selection( lmp );
|
|
|
|
if ( cur_row == -1 )
|
|
cur_row = 0;
|
|
else
|
|
{
|
|
if ( cur_row == 0 )
|
|
xi_scroll( lmp->list_obj, -1 );
|
|
else
|
|
cur_row--;
|
|
}
|
|
select_row( lm, cur_row, -1, FALSE );
|
|
break;
|
|
}
|
|
case XI_KEY_DOWN:
|
|
{
|
|
int cur_row = find_selection( lmp );
|
|
|
|
if ( cur_row == -1 )
|
|
cur_row = 0;
|
|
else
|
|
{
|
|
if ( cur_row == lmp->last_fully_vis )
|
|
xi_scroll( lmp->list_obj, 1 );
|
|
else
|
|
cur_row++;
|
|
}
|
|
select_row( lm, cur_row, -1, FALSE );
|
|
break;
|
|
}
|
|
case XI_KEY_PREV:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_PGUP );
|
|
select_row( lm, lmp->last_fully_vis, -1, FALSE );
|
|
break;
|
|
case XI_KEY_NEXT:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_PGDOWN );
|
|
select_row( lm, 0, -1, FALSE );
|
|
break;
|
|
case XI_KEY_HOME:
|
|
case XI_KEY_LHOME:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_FIRST );
|
|
select_row( lm, 0, -1, FALSE );
|
|
break;
|
|
case XI_KEY_END:
|
|
case XI_KEY_LEND:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_LAST );
|
|
select_row( lm, lmp->last_fully_vis, -1, FALSE );
|
|
break;
|
|
case '\r':
|
|
case ' ':
|
|
case '\n':
|
|
row = find_selection( lmp );
|
|
select_row( lm, row, -1, TRUE );
|
|
clear_buffer = FALSE;
|
|
#if 0
|
|
if ( row != -1 )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) row;
|
|
lm_cb_data.column = ( unsigned char ) get_select_column( lmp );
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = TRUE;
|
|
lm_cb_data.v.select.shift = FALSE;
|
|
lm_cb_data.v.select.control = FALSE;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
if ( lmp->position_by_typing_cid > 0 )
|
|
{
|
|
int len, old_len;
|
|
if (lmp->position_by_typing_buf == NULL)
|
|
{
|
|
lmp->position_by_typing_buf = (char *)xi_tree_malloc( 100 * sizeof(char), lmp->list_obj );
|
|
memset( lmp->position_by_typing_buf, '\0', 100 * sizeof( char ) );
|
|
}
|
|
len = old_len = strlen( lmp->position_by_typing_buf );
|
|
if (ep->v.character.ch == '\b')
|
|
{
|
|
if (len > 0)
|
|
{
|
|
lmp->position_by_typing_buf[len-1] = '\0';
|
|
len--;
|
|
}
|
|
} else {
|
|
lmp->position_by_typing_buf[len] = (char)(toupper(ep->v.character.ch));
|
|
lmp->position_by_typing_buf[len+1] = '\0';
|
|
len++;
|
|
}
|
|
/* Find the row that matches the buffer and scroll to it. */
|
|
if (len == 0)
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_FIRST );
|
|
else {
|
|
BOOLEAN use_allocate_free = FALSE;
|
|
BOOLEAN do_first = FALSE; /* Should we send an XIE_GET_FIRST the first time thru the loop? */
|
|
BOOLEAN done_first = FALSE; /* have we been thru the loop at least once? */
|
|
BOOLEAN do_get = TRUE; /* Should we send an XIE_GET_? at all? */
|
|
BOOLEAN found = FALSE;
|
|
BOOLEAN right_row = FALSE;
|
|
int comp_len;
|
|
int comp_result;
|
|
long spec_rec, data_rec = 0L, swap_rec, start_rec = 0L;
|
|
XI_EVENT xiev;
|
|
char text_buffer[200];
|
|
int col_nbr;
|
|
|
|
{
|
|
int nbr_cols;
|
|
XI_OBJ **col;
|
|
col_nbr = 0;
|
|
col = xi_get_member_list( lmp->list_obj, & nbr_cols );
|
|
while (nbr_cols)
|
|
{
|
|
if ((*col)->cid == lmp->position_by_typing_cid)
|
|
break;
|
|
col_nbr++;
|
|
nbr_cols--;
|
|
col++;
|
|
}
|
|
if (!nbr_cols)
|
|
return FALSE;
|
|
}
|
|
MEMCLEAR( xiev );
|
|
/* We need two handles, which we will alternate between spec and data_rec. */
|
|
xiev.type = XIE_REC_ALLOCATE;
|
|
xiev.v.rec_allocate.list = lmp->list_obj;
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
if ( xiev.refused )
|
|
return FALSE;
|
|
spec_rec = xiev.v.rec_allocate.record;
|
|
if (spec_rec != 0)
|
|
{
|
|
use_allocate_free = TRUE;
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
if ( xiev.refused )
|
|
return FALSE;
|
|
data_rec = xiev.v.rec_allocate.record;
|
|
}
|
|
|
|
if (old_len > len || len == 1)
|
|
do_first = TRUE;
|
|
|
|
while (!found)
|
|
{
|
|
MEMCLEAR( xiev );
|
|
xiev.v.rec_request.list = lmp->list_obj;
|
|
if (use_allocate_free)
|
|
xiev.v.rec_request.data_rec = data_rec;
|
|
if (!done_first)
|
|
{
|
|
if (do_first)
|
|
xiev.type = XIE_GET_FIRST;
|
|
else {
|
|
int row = find_selection( lmp );
|
|
if (row != -1)
|
|
{
|
|
xiev.type = XIE_GET_NEXT;
|
|
start_rec = lmp->recs[row];
|
|
do_get = FALSE; /* We have the record. Don't send an XIE_GET_? */
|
|
} else
|
|
xiev.type = XIE_GET_FIRST;
|
|
}
|
|
} else {
|
|
xiev.type = XIE_GET_NEXT;
|
|
xiev.v.rec_request.spec_rec = spec_rec;
|
|
}
|
|
if (do_get)
|
|
{
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
if ( xiev.refused )
|
|
break;
|
|
}
|
|
done_first = TRUE;
|
|
if (use_allocate_free)
|
|
{
|
|
swap_rec = data_rec;
|
|
data_rec = spec_rec;
|
|
spec_rec = swap_rec;
|
|
} else
|
|
spec_rec = xiev.v.rec_request.data_rec;
|
|
MEMCLEAR( xiev );
|
|
xiev.type = XIE_CELL_REQUEST;
|
|
xiev.v.cell_request.list = lmp->list_obj;
|
|
xiev.v.cell_request.s = text_buffer;
|
|
xiev.v.cell_request.len = 200;
|
|
if (do_get)
|
|
xiev.v.cell_request.rec = spec_rec;
|
|
else
|
|
xiev.v.cell_request.rec = start_rec;
|
|
xiev.v.cell_request.col_nbr = col_nbr;
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
comp_len = len;
|
|
if (xiev.v.cell_request.len < comp_len)
|
|
comp_len = xiev.v.cell_request.len;
|
|
{
|
|
int i = 0;
|
|
for (; i < comp_len; i++)
|
|
xiev.v.cell_request.s[i] = toupper( xiev.v.cell_request.s[i] );
|
|
}
|
|
comp_result = strncmp(lmp->position_by_typing_buf, xiev.v.cell_request.s, comp_len);
|
|
if (comp_result == 0) {
|
|
found = TRUE;
|
|
right_row = TRUE;
|
|
} else if (comp_result < 0) {
|
|
found = TRUE;
|
|
right_row = FALSE;
|
|
do_get = TRUE;
|
|
} else
|
|
do_get = TRUE;
|
|
}
|
|
if (right_row)
|
|
{
|
|
int i;
|
|
long test_rec;
|
|
if (do_get)
|
|
test_rec = spec_rec;
|
|
else
|
|
test_rec = start_rec;
|
|
|
|
for (i = 0; i < lmp->nbr_realized_rows; i++)
|
|
if (lmp->recs[i] == test_rec)
|
|
break;
|
|
if (i >= lmp->nbr_realized_rows)
|
|
{
|
|
XI_SCROLL_RECORD_ARG arg;
|
|
MEMCLEAR( arg );
|
|
arg.xi_obj = lmp->list_obj;
|
|
if (do_get)
|
|
arg.record = spec_rec;
|
|
else
|
|
arg.record = start_rec;
|
|
arg.rec_at_top = TRUE;
|
|
xi_scroll_record( &arg );
|
|
for (i = 0; i < lmp->nbr_realized_rows; i++)
|
|
if (lmp->recs[i] == test_rec)
|
|
break;
|
|
}
|
|
if (i < lmp->nbr_realized_rows)
|
|
{
|
|
long attrib;
|
|
attrib = lm_get_attrib( lm, LM_ROW, i, 0, FALSE );
|
|
if ( !(attrib & LM_ROW_ATR_SELECTED) )
|
|
select_row( lm, i, -1, FALSE );
|
|
}
|
|
} else {
|
|
XinBeep();
|
|
lmp->position_by_typing_buf[len-1] = '\0';
|
|
}
|
|
if (use_allocate_free)
|
|
{
|
|
MEMCLEAR( xiev );
|
|
xiev.type = XIE_REC_FREE;
|
|
xiev.v.rec_free.list = lmp->list_obj;
|
|
xiev.v.rec_free.record = data_rec;
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
if (!right_row || !do_get)
|
|
{
|
|
xiev.v.rec_free.record = spec_rec;
|
|
(itf->v.itf->xi_eh) ( itf, &xiev );
|
|
}
|
|
}
|
|
}
|
|
clear_buffer = FALSE;
|
|
} else
|
|
return FALSE;
|
|
}
|
|
if (clear_buffer && lmp->position_by_typing_buf != NULL)
|
|
lmp->position_by_typing_buf[0] = '\0';
|
|
return TRUE;
|
|
}
|
|
|
|
if ( !lmp->sizing_row )
|
|
{
|
|
BOOLEAN nav_ret = FALSE;
|
|
|
|
if ( !lmp->itf_obj->v.itf->pasting )
|
|
nav_ret = ( BOOLEAN ) navigate_char_event( lm, ep );
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
int ch = ep->v.character.ch;
|
|
retval = send_cell_event( lm, ep, FALSE, ( BOOLEAN ) ( !nav_ret ) );
|
|
/* If the high-level application wants to do its own autotabbing, it
|
|
* will change the character to a tab, so we need to process that
|
|
* here. */
|
|
if ( ep->v.character.ch != ch )
|
|
nav_ret = ( BOOLEAN ) navigate_char_event( lm, ep );
|
|
}
|
|
else
|
|
retval = FALSE;
|
|
}
|
|
break;
|
|
case XinEventDestroy:
|
|
retval = 0;
|
|
break;
|
|
case XinEventTimer:
|
|
case XinEventMenuCommand:
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
retval = send_cell_event( lm, ep, FALSE, TRUE );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if ( ep_needs_restore )
|
|
*ep = oevt;
|
|
return ( retval );
|
|
}
|