campo-sirio/src/xi/xilm3.c
mtollari 1b14ec9415 Spostamento cartella sorgenti
git-svn-id: svn://10.65.10.50/branches/R_10_00@23236 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016-09-09 13:59:02 +00:00

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 );
}