1b14ec9415
git-svn-id: svn://10.65.10.50/branches/R_10_00@23236 c028cbd2-c16b-5b4b-a496-9718f37d4682
5291 lines
161 KiB
C
Executable File
5291 lines
161 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 "xi_int.h"
|
|
#include <limits.h>
|
|
|
|
#define REALIZED_ROWS_GRANULE 4
|
|
#define REC_AT_TOP 1
|
|
#define REC_AT_BOTTOM 0
|
|
#define CELL_VERTICAL_MARGIN (RULE_Y_OFFSET_TOP + RULE_Y_OFFSET_BOTTOM + 2)
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_allocate_rec_info
|
|
lmp: current lmp
|
|
realized_rows_array_len: number of realized rows in the realized rows array
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_allocate_rec_info( LM_DATA * lmp, int realized_rows_array_len )
|
|
{
|
|
int old_len = lmp->realized_rows_array_len;
|
|
int i;
|
|
|
|
lmp->realized_rows_array_len = realized_rows_array_len;
|
|
|
|
/* recs */
|
|
if ( lmp->recs )
|
|
{
|
|
lmp->recs = ( long * ) xi_tree_realloc( lmp->recs, sizeof( long ) * realized_rows_array_len );
|
|
for ( i = old_len; i < realized_rows_array_len; ++i )
|
|
lmp->recs[i] = 0L;
|
|
}
|
|
else
|
|
lmp->recs = ( long * ) xi_tree_malloc( sizeof( long ) * realized_rows_array_len, lmp );
|
|
|
|
/* pix_offsets */
|
|
if ( lmp->pix_offsets )
|
|
lmp->pix_offsets = ( int * ) xi_tree_realloc( lmp->pix_offsets,
|
|
sizeof( int ) * realized_rows_array_len );
|
|
else
|
|
lmp->pix_offsets = ( int * ) xi_tree_malloc( sizeof( int ) * realized_rows_array_len, lmp );
|
|
|
|
/* pix_heights */
|
|
if ( lmp->pix_heights )
|
|
lmp->pix_heights = ( int * ) xi_tree_realloc( lmp->pix_heights,
|
|
sizeof( int ) * realized_rows_array_len );
|
|
else
|
|
lmp->pix_heights = ( int * ) xi_tree_malloc( sizeof( int ) * realized_rows_array_len, lmp );
|
|
|
|
/* set_heights */
|
|
if ( lmp->set_heights )
|
|
lmp->set_heights = ( short * ) xi_tree_realloc( lmp->set_heights,
|
|
sizeof( int ) * realized_rows_array_len );
|
|
else
|
|
lmp->set_heights = ( short * ) xi_tree_malloc( sizeof( int ) * realized_rows_array_len, lmp );
|
|
|
|
/* row_attribs */
|
|
if ( lmp->row_attribs )
|
|
{
|
|
lmp->row_attribs = ( unsigned long * ) xi_tree_realloc( lmp->row_attribs,
|
|
sizeof( unsigned long ) * realized_rows_array_len );
|
|
for ( i = old_len; i < realized_rows_array_len; ++i )
|
|
lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
|
|
}
|
|
else
|
|
lmp->row_attribs = ( unsigned long * ) xi_tree_malloc( sizeof( unsigned long ) * realized_rows_array_len,
|
|
lmp );
|
|
|
|
/* row_colors */
|
|
if ( lmp->row_colors )
|
|
{
|
|
lmp->row_colors = ( XinColor * ) xi_tree_realloc( lmp->row_colors,
|
|
sizeof( XinColor ) * realized_rows_array_len );
|
|
for ( i = old_len; i < realized_rows_array_len; ++i )
|
|
lmp->row_colors[i] = 0L;
|
|
}
|
|
else
|
|
lmp->row_colors = ( XinColor * ) xi_tree_malloc( sizeof( XinColor ) * realized_rows_array_len,
|
|
lmp );
|
|
|
|
/* cell_data */
|
|
if ( lmp->cell_data )
|
|
{
|
|
/* cell data destructor */
|
|
for ( i = realized_rows_array_len; i < old_len; ++i )
|
|
xi_tree_free( lmp->cell_data[i] );
|
|
lmp->cell_data = ( LM_CELL_DATA ** ) xi_tree_realloc( lmp->cell_data,
|
|
sizeof( LM_CELL_DATA * ) * realized_rows_array_len );
|
|
for ( i = old_len; i < realized_rows_array_len; ++i )
|
|
lmp->cell_data[i] = ( LM_CELL_DATA * ) xi_tree_malloc(
|
|
( lmp->nbr_columns + 1 ) * sizeof( LM_CELL_DATA ), lmp );
|
|
}
|
|
else
|
|
lmp->cell_data = ( LM_CELL_DATA ** ) xi_tree_malloc(
|
|
sizeof( LM_CELL_DATA * ) * realized_rows_array_len, lmp );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_create
|
|
win: window in which to put list
|
|
lm_def: list definition
|
|
parent: tree memory parent
|
|
-------------------------------------------------------------------------*/
|
|
LM
|
|
lm_create( XinWindow win, LM_DEF * lm_def, void *parent )
|
|
{
|
|
LM_DATA *lmp;
|
|
int i,
|
|
font_height,
|
|
leading,
|
|
ascent,
|
|
descent,
|
|
mch,
|
|
realized_rows_array_len;
|
|
|
|
lmp = LMP( xi_tree_malloc( sizeof( LM_DATA ), parent ) );
|
|
lmp->focus_state = ( LM_FOCUS_STATE * ) xi_tree_malloc( sizeof( LM_FOCUS_STATE ), lmp );
|
|
lmp->focus_state->where = LM_FOCUS_NOWHERE;
|
|
lmp->cid = lm_def->cid;
|
|
lmp->list_obj = lm_def->list_obj;
|
|
lmp->itf_obj = lm_def->itf_obj;
|
|
lmp->win = win;
|
|
lmp->font = lm_def->font;
|
|
lmp->is_list_font = lm_def->is_list_font;
|
|
lmp->back_color = lm_def->back_color;
|
|
lmp->enabled_color = lm_def->enabled_color;
|
|
lmp->disabled_color = lm_def->disabled_color;
|
|
lmp->disabled_back_color = lm_def->disabled_back_color;
|
|
lmp->active_color = lm_def->active_color;
|
|
lmp->active_back_color = lm_def->active_back_color;
|
|
lmp->white_space_color = lm_def->white_space_color;
|
|
lmp->rule_color = lm_def->rule_color;
|
|
lmp->attrib = lm_def->attrib;
|
|
lmp->lm_cb = lm_def->lm_cb;
|
|
lmp->no_heading = lm_def->no_heading;
|
|
lmp->sizable_columns = lm_def->sizable_columns;
|
|
lmp->movable_columns = lm_def->movable_columns;
|
|
lmp->fixed_columns = lm_def->fixed_columns;
|
|
lmp->resize_with_window = lm_def->resize_with_window;
|
|
lmp->horz_sync_list = lm_def->horz_sync_list;
|
|
lmp->vert_sync_list = lm_def->vert_sync_list;
|
|
lmp->row_focus_border = lm_def->row_focus_border;
|
|
lmp->row_focus_border_color = lm_def->row_focus_border_color;
|
|
lmp->single_select = lm_def->single_select;
|
|
lmp->pixel_width = lm_def->pixel_width;
|
|
lmp->pixel_height = lm_def->pixel_height;
|
|
#if XIWS == XIWS_WM
|
|
lmp->min_cell_height = 0;
|
|
lmp->min_heading_height = lm_def->min_heading_height;
|
|
#else
|
|
lmp->min_cell_height = lm_def->min_cell_height;
|
|
lmp->min_heading_height = lm_def->min_heading_height;
|
|
#endif
|
|
lmp->no_horz_lines = lm_def->no_horz_lines;
|
|
lmp->no_vert_lines = lm_def->no_vert_lines;
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
lmp->drop_and_delete = lm_def->drop_and_delete;
|
|
lmp->select_cells = lm_def->select_cells;
|
|
lmp->get_all_records = lm_def->get_all_records;
|
|
lmp->retain_back_color_on_select = lm_def->retain_back_color_on_select;
|
|
lmp->drag_and_drop_rows = lm_def->drag_and_drop_rows;
|
|
lmp->drag_rows_autoscroll = lm_def->drag_rows_autoscroll;
|
|
lmp->button_on_cell_focus = lm_def->button_on_cell_focus;
|
|
lmp->position_by_typing_cid = lm_def->position_by_typing_cid;
|
|
lmp->max_lines_in_cell = lm_def->max_lines_in_cell;
|
|
if ( !lmp->max_lines_in_cell )
|
|
lmp->max_lines_in_cell =
|
|
( int ) xi_get_pref( XI_PREF_DEFAULT_MAX_LINES_IN_CELL );
|
|
XinWindowFontMap( win, lm_def->font );
|
|
XinFontMetricsGet( lm_def->font, &leading, &ascent, &descent );
|
|
lmp->cur_font = lm_def->font;
|
|
lmp->leading = leading;
|
|
lmp->ascent = ascent;
|
|
lmp->descent = descent;
|
|
font_height = lmp->ascent + lmp->leading + lmp->descent;
|
|
|
|
/* we add two to the following line so that there is room in the cell for the
|
|
* row focus border */
|
|
#if XIWS == XIWS_WM
|
|
lmp->pix_cell_height = font_height;
|
|
#else
|
|
lmp->pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
|
|
#endif
|
|
#if XIWS == XIWS_WM
|
|
mch = 8;
|
|
#else
|
|
mch = lm_def->min_cell_height;
|
|
#endif
|
|
lmp->pix_cell_height = max( lmp->pix_cell_height, mch );
|
|
lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
|
|
lmp->pix_top = lm_def->pnt.v;
|
|
#if XIWS == XIWS_WM
|
|
lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH +
|
|
RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
|
|
lmp->pix_hdr_bottom = max( lmp->pix_hdr_bottom, ( lm_def->pnt.v
|
|
+ lmp->min_heading_height - BORDER_WIDTH ) );
|
|
#else
|
|
lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH + RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP + 1;
|
|
lmp->pix_hdr_bottom = max( lmp->pix_hdr_bottom, ( lm_def->pnt.v + lmp->min_heading_height ) );
|
|
#endif
|
|
if ( lmp->no_heading )
|
|
lmp->pix_row1_top = lm_def->pnt.v + BORDER_WIDTH;
|
|
else
|
|
lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
|
|
lmp->pix_char_width = lm_def->pix_char_width;
|
|
lmp->nbr_columns = 0;
|
|
lmp->lm_column_data = NULL;
|
|
|
|
/* compute number of rows */
|
|
lmp->nbr_rows = lm_def->nbr_rows;
|
|
if ( lm_def->nbr_rows )
|
|
lmp->nbr_rows = lm_def->nbr_rows;
|
|
else
|
|
lmp->nbr_rows = ( lm_def->pixel_height - ( lmp->pix_row1_top - lm_def->pnt.v )
|
|
- BORDER_WIDTH ) / lmp->pix_row_spacing;
|
|
if ( lm_def->one_row_list )
|
|
{
|
|
lmp->nbr_rows = 1;
|
|
lm_def->resize_with_window = FALSE;
|
|
}
|
|
|
|
lmp->rct.left = lm_def->pnt.h;
|
|
lmp->rct.top = lm_def->pnt.v;
|
|
#if XIWS != XIWS_WM
|
|
lmp->rct.right = lm_def->pnt.h + 2 * BORDER_WIDTH;
|
|
if ( lm_def->resize_with_window )
|
|
lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
|
|
else
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
|
|
( BORDER_WIDTH - RULE_WIDTH_H );
|
|
#else
|
|
lmp->rct.right = lm_def->pnt.h + BORDER_WIDTH;
|
|
if ( lm_def->resize_with_window )
|
|
lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
|
|
else
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
|
|
+ BORDER_WIDTH;
|
|
#endif
|
|
lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
|
|
lmp->vir_right = lmp->vir_left + lmp->pixel_width;
|
|
|
|
realized_rows_array_len = lm_def->realized_rows_array_len;
|
|
if ( !realized_rows_array_len )
|
|
realized_rows_array_len = lmp->nbr_rows + 1;
|
|
lm_allocate_rec_info( lmp, realized_rows_array_len );
|
|
|
|
/* calculate mathematical list rectangle */
|
|
lmp->mlr.top = lmp->pix_row1_top;
|
|
#if XIWS != XIWS_WM
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
lmp->mlr.left = lmp->rct.left + BORDER_WIDTH;
|
|
lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
else
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
lmp->mlr.left = lmp->rct.left;
|
|
lmp->mlr.right = lmp->rct.right;
|
|
#endif
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
|
|
for ( i = 0; i < lmp->realized_rows_array_len; ++i )
|
|
{
|
|
lmp->cell_data[i] = ( LM_CELL_DATA * ) xi_tree_malloc(
|
|
lmp->nbr_columns * sizeof( LM_CELL_DATA ), lmp );
|
|
lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
|
|
}
|
|
|
|
return ( ( LM ) ( long ) lmp );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_do_rec_event
|
|
lmp: current lmp
|
|
row: row to do event on
|
|
type: XI_EVENT_TYPE
|
|
notes: In this case, row is not really a row. It is an index into the
|
|
realized rows array.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_do_rec_event( LM_DATA * lmp, int row, XI_EVENT_TYPE type )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
int i;
|
|
|
|
if ( type == XIE_REC_FREE )
|
|
{
|
|
if ( lmp->recs[row] != lm_focus_rec_get( lmp ) )
|
|
do_lm_cb( ( LM ) lmp, LM_CB_REC_FREE, row, 0, NULL, NULL, 0 );
|
|
cell_data = lmp->cell_data[row];
|
|
/* cell_data_destruct */
|
|
for ( i = 0; i < lmp->nbr_columns; ++i, ++cell_data )
|
|
{
|
|
if ( cell_data->font )
|
|
XinFontDestroy( cell_data->font );
|
|
xi_bitmap_destroy( cell_data->bitmap );
|
|
xi_bitmap_destroy( cell_data->button_bitmap );
|
|
if ( cell_data->xi_text )
|
|
xi_text_destruct( cell_data->xi_text );
|
|
memset( ( char * ) cell_data, '\0', sizeof( LM_CELL_DATA ) );
|
|
}
|
|
lmp->recs[row] = 0L;
|
|
/* we technically do not need to do the following lines. it just keeps the
|
|
* data structures clean. */
|
|
lmp->pix_heights[row] = 0;
|
|
lmp->set_heights[row] = FALSE;
|
|
lmp->pix_offsets[row] = 0;
|
|
lmp->row_attribs[row] = 0L;
|
|
lmp->row_colors[row] = 0L;
|
|
}
|
|
/* cell_data_construct */
|
|
if ( type == XIE_REC_ALLOCATE )
|
|
{
|
|
do_lm_cb( ( LM ) lmp, LM_CB_REC_ALLOCATE, row, 0, NULL, NULL, 0 );
|
|
cell_data = lmp->cell_data[row];
|
|
for ( i = 0; i < lmp->nbr_columns; ++i, ++cell_data )
|
|
{
|
|
memset( ( char * ) cell_data, '\0', sizeof( LM_CELL_DATA ) );
|
|
lm_xi_text_construct( lmp, row, i );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_row_copy
|
|
lmp: current lmp
|
|
source_row: row from which to copy
|
|
dest_row: destination row
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_row_copy( LM_DATA * lmp, int source_row, int dest_row )
|
|
{
|
|
int idx;
|
|
LM_CELL_DATA *dest_cell_data,
|
|
*source_cell_data;
|
|
|
|
lmp->recs[dest_row] = lmp->recs[source_row];
|
|
lmp->pix_heights[dest_row] = lmp->pix_heights[source_row];
|
|
lmp->set_heights[dest_row] = lmp->set_heights[source_row];
|
|
lmp->pix_offsets[dest_row] = lmp->pix_offsets[source_row];
|
|
lmp->row_attribs[dest_row] = lmp->row_attribs[source_row];
|
|
lmp->row_colors[dest_row] = lmp->row_colors[source_row];
|
|
for ( idx = 0,
|
|
dest_cell_data = lmp->cell_data[dest_row],
|
|
source_cell_data = lmp->cell_data[source_row];
|
|
idx < lmp->nbr_columns;
|
|
++idx,
|
|
++dest_cell_data,
|
|
++source_cell_data )
|
|
{
|
|
*dest_cell_data = *source_cell_data;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: init_row
|
|
lmp: current lmp
|
|
row: row to init
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
init_row( LM_DATA * lmp, int row )
|
|
{
|
|
int idx;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
lmp->recs[row] = 0L;
|
|
lmp->pix_heights[row] = 0;
|
|
lmp->set_heights[row] = 0;
|
|
lmp->pix_offsets[row] = 0;
|
|
lmp->row_attribs[row] = LM_ROW_ATR_ENABLED;
|
|
lmp->row_colors[row] = 0;
|
|
for ( idx = 0,
|
|
cell_data = lmp->cell_data[row];
|
|
idx < lmp->nbr_columns;
|
|
++idx,
|
|
++cell_data )
|
|
{
|
|
memset( ( char * ) cell_data, '\0', sizeof( LM_CELL_DATA ) );
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rec_available
|
|
lmp: current lmp
|
|
top: record to become available is at the top of the realized_row array,
|
|
else the record to become available is at the bottom of the realized
|
|
row array.
|
|
allocate_rec: if TRUE, then send XIE_REC_ALLOCATE event
|
|
notes: if, in order to get a record at the bottom of the realized row array,
|
|
we must discard a record at the beginning of the rrr array, then
|
|
we must change lmp->rrr_offset.
|
|
whenever we make a record be available, make sure that we free
|
|
fonts in cell_data.
|
|
Also, clear cell_data.
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
make_rec_available( LM_DATA * lmp, BOOLEAN top, BOOLEAN allocate_rec,
|
|
BOOLEAN doing_scroll_first )
|
|
{
|
|
int cnt;
|
|
|
|
if ( top )
|
|
{
|
|
int idx;
|
|
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
int nbr_to_free;
|
|
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
if ( nbr_to_free > 0 )
|
|
{
|
|
/* free as many records at the end of the list as possible */
|
|
for ( idx = lmp->last_fully_vis + 2; idx < lmp->nbr_realized_rows;
|
|
++idx )
|
|
lm_do_rec_event( lmp, idx, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
|
|
if ( lmp->nbr_realized_rows >= lmp->realized_rows_array_len )
|
|
lm_allocate_rec_info( lmp, lmp->realized_rows_array_len + 1 );
|
|
|
|
/* copy all the records, making room at the beginning of the realized_row
|
|
* array */
|
|
++lmp->nbr_realized_rows;
|
|
for ( idx = lmp->nbr_realized_rows - 1;
|
|
idx > 0; --idx )
|
|
lm_row_copy( lmp, idx - 1, idx );
|
|
lm_adjust_rows( lmp, 1 );
|
|
init_row( lmp, 0 );
|
|
if ( allocate_rec )
|
|
lm_do_rec_event( lmp, 0, XIE_REC_ALLOCATE );
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !lmp->get_all_records || doing_scroll_first )
|
|
{
|
|
/* free as many records at the beginning of the list as possible */
|
|
cnt = lmp->first_fully_vis - 2;
|
|
if ( cnt > 0 )
|
|
{
|
|
int idx,
|
|
jidx;
|
|
|
|
for ( idx = 0; idx < cnt; ++idx )
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[idx];
|
|
lm_do_rec_event( lmp, idx, XIE_REC_FREE );
|
|
}
|
|
|
|
lmp->nbr_realized_rows -= cnt;
|
|
|
|
/* copy all the records, making room at the end of the realized row
|
|
* array */
|
|
for ( idx = cnt, jidx = 0;
|
|
jidx < lmp->nbr_realized_rows;
|
|
++idx, ++jidx )
|
|
lm_row_copy( lmp, idx, idx - cnt );
|
|
lm_adjust_rows( lmp, -cnt );
|
|
}
|
|
if ( lmp->nbr_realized_rows >= lmp->realized_rows_array_len )
|
|
lm_allocate_rec_info( lmp, lmp->realized_rows_array_len + 1 );
|
|
++lmp->nbr_realized_rows;
|
|
init_row( lmp, lmp->nbr_realized_rows - 1 );
|
|
if ( allocate_rec )
|
|
lm_do_rec_event( lmp, lmp->nbr_realized_rows - 1, XIE_REC_ALLOCATE );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_next_rec
|
|
lmp: current lmp
|
|
returns: TRUE if next record was available
|
|
FALSE if not
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
get_next_rec( LM_DATA * lmp, BOOLEAN doing_scroll_first )
|
|
{
|
|
int idx,
|
|
row_height;
|
|
|
|
make_rec_available( lmp, REC_AT_BOTTOM, TRUE, doing_scroll_first );
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
if ( do_lm_cb_get( ( LM ) lmp, LM_CB_GET_NEXT,
|
|
&lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height ) )
|
|
{
|
|
lm_do_rec_event( lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE );
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
|
|
if ( row_height )
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = 0;
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
|
|
lm_invalidate_rows_internal( ( LM ) lmp, idx, idx, FALSE, -1, TRUE );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_previous_rec
|
|
lmp: current lmp
|
|
returns: TRUE if previous record was available
|
|
FALSE if not
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
get_previous_rec( LM_DATA * lmp )
|
|
{
|
|
int row_height,
|
|
cnt;
|
|
|
|
make_rec_available( lmp, REC_AT_TOP, TRUE, FALSE );
|
|
if ( do_lm_cb_get( ( LM ) lmp, LM_CB_GET_PREV,
|
|
&lmp->recs[1], &lmp->recs[0], 0, &lmp->row_colors[0],
|
|
&lmp->row_attribs[0], &row_height ) )
|
|
{
|
|
lm_do_rec_event( lmp, 0, XIE_REC_FREE );
|
|
for ( cnt = 0; cnt < lmp->nbr_realized_rows - 1; ++cnt )
|
|
lm_row_copy( lmp, cnt + 1, cnt );
|
|
lm_adjust_rows( lmp, -1 );
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
if ( row_height )
|
|
{
|
|
lmp->pix_heights[0] = row_height;
|
|
lmp->set_heights[0] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[0] = 0;
|
|
lmp->set_heights[0] = FALSE;
|
|
}
|
|
lm_invalidate_rows_internal( ( LM ) lmp, 0, 0, FALSE, -1, TRUE );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_cell_height
|
|
lmp: current lmp
|
|
row: row number of cell to calculate
|
|
column: column number of cell to calculate
|
|
returns: height of cell in pixels
|
|
notes: this function does not need to take into consideration the
|
|
variable fixed_row_height. This function is only used by
|
|
lm_calculate_row_height, and will only be called if
|
|
fixed_row_height is false.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calculate_cell_height( LM_DATA * lmp, int row, int column )
|
|
{
|
|
int pix_height; /* pix_height does include the width of the
|
|
* rules */
|
|
int nbr_lines;
|
|
LM_CELL_DATA *cell_data;
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
|
|
cell_data = &lmp->cell_data[row][column];
|
|
lm_column_data = lmp->lm_column_data[column];
|
|
if ( !cell_data->font_height )
|
|
{
|
|
XinFont *font;
|
|
int leading,
|
|
ascent,
|
|
descent,
|
|
char_width;
|
|
|
|
if ( lm_column_data->wrap_text && !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, column, TRUE );
|
|
if ( cell_data->font )
|
|
font = cell_data->font;
|
|
else
|
|
font = lmp->font;
|
|
xi_get_font_metrics_font( font, &leading, &ascent, &descent, &char_width );
|
|
cell_data->font_height = leading + ascent + descent;
|
|
}
|
|
if ( lm_column_data->wrap_text )
|
|
{
|
|
int pix_spacing;
|
|
BOOLEAN is_editing;
|
|
int ip1,
|
|
ip2,
|
|
start_ip;
|
|
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, row, column, TRUE );
|
|
is_editing = xi_text_editing_is( cell_data->xi_text );
|
|
if ( is_editing )
|
|
xi_text_selection_get_internal( cell_data->xi_text, &ip1, &ip2, &start_ip );
|
|
xi_text_initialized_set( cell_data->xi_text, FALSE );
|
|
pix_spacing = lm_column_data->pix_width -
|
|
( cell_data->button ? lmp->pix_row_spacing : 0 );
|
|
xi_text_pix_width_set( cell_data->xi_text, pix_spacing );
|
|
if ( is_editing )
|
|
xi_text_selection_set_internal( cell_data->xi_text, ip1, ip2, start_ip, FALSE, FALSE );
|
|
nbr_lines = min( xi_text_nbr_lines_get( cell_data->xi_text ), lmp->max_lines_in_cell );
|
|
}
|
|
else
|
|
nbr_lines = 1;
|
|
#if XIWS != XIWS_WM
|
|
pix_height = nbr_lines * cell_data->font_height + CELL_VERTICAL_MARGIN
|
|
+ RULE_WIDTH_H;
|
|
#else
|
|
pix_height = nbr_lines * cell_data->font_height;
|
|
#endif
|
|
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VERTICALLY_SCROLLED )
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if ( focus_column == column && lmp->recs[row] == lmp->focus_state->focus_rec )
|
|
pix_height = lmp->focus_state->focus_rec_height;
|
|
}
|
|
|
|
|
|
pix_height = max( pix_height, lmp->pix_row_spacing );
|
|
return pix_height;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_calculate_row_height
|
|
lmp: current lmp
|
|
row: row number to calculate
|
|
returns: height of row in pixels
|
|
notes: if fixed_row_height is TRUE, then the calculation is easy.
|
|
if fixed_row_height is FALSE, then the calculation must take
|
|
word wrap into consideration, etc.
|
|
row height includes the height of the horizontal rule below
|
|
the row.
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_calculate_row_height( LM_DATA * lmp, int row )
|
|
{
|
|
int pix_height;
|
|
|
|
if ( lmp->fixed_row_height )
|
|
pix_height = lmp->pix_row_spacing;
|
|
else if ( lmp->set_heights[row] )
|
|
pix_height = lmp->pix_heights[row];
|
|
else
|
|
{
|
|
int cnt;
|
|
int cell_height;
|
|
|
|
pix_height = 0;
|
|
for ( cnt = 0; cnt < lmp->nbr_columns; ++cnt )
|
|
{
|
|
cell_height = calculate_cell_height( lmp, row, cnt );
|
|
pix_height = max( pix_height, cell_height );
|
|
}
|
|
}
|
|
if ( pix_height > lmp->mlr_height )
|
|
pix_height = lmp->mlr_height;
|
|
return pix_height;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_visibles
|
|
lmp: current lmp
|
|
process: calculates lmp->first_fully_vis
|
|
calculates lmp->last_fully_vis
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calculate_visibles( LM_DATA * lmp )
|
|
{
|
|
int i,
|
|
idx;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
BOOLEAN have_first;
|
|
|
|
have_first = FALSE;
|
|
lmp->first_fully_vis = 0;
|
|
lmp->last_fully_vis = 0;
|
|
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 )
|
|
{
|
|
if ( !have_first && *pix_offsetsp >= ( -lmp->rrr_offset ) )
|
|
{
|
|
have_first = TRUE;
|
|
lmp->first_fully_vis = i;
|
|
}
|
|
/* should be <, because we are dealing with mathematical rects, but we
|
|
* don't care if the rule is not on the list. pix_offsetp + *pix_heightsp
|
|
* is the mathematical rect of the row, in rrr terms. lmp->rrr_offset +
|
|
* lmp->mlr_height is the mathematical rect of the list, in rrr terms. */
|
|
#if XIWS == XIWS_WM
|
|
if ( *pix_offsetsp + *pix_heightsp + lmp->rrr_offset <= lmp->mlr_height )
|
|
lmp->last_fully_vis = i;
|
|
#else
|
|
if ( *pix_offsetsp + *pix_heightsp - 1 + lmp->rrr_offset <= lmp->mlr_height )
|
|
lmp->last_fully_vis = i;
|
|
#endif
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_pix_offsets
|
|
lmp: current lmp
|
|
process: calculates the lmp->pix_offsets array
|
|
calculates lmp->first_fully_vis
|
|
calculates lmp->last_fully_vis
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calculate_pix_offsets( LM_DATA * lmp, BOOLEAN draw_changes )
|
|
{
|
|
int i,
|
|
cur_pix,
|
|
idx;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
BOOLEAN have_first;
|
|
|
|
cur_pix = 0;
|
|
have_first = FALSE;
|
|
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 )
|
|
{
|
|
int new_height;
|
|
|
|
new_height = lm_calculate_row_height( lmp, i );
|
|
if ( draw_changes &&
|
|
( *pix_offsetsp != cur_pix || *pix_heightsp != new_height ) )
|
|
{
|
|
XinRect rect;
|
|
|
|
lm_get_row_rect( &rect, ( LM ) lmp, i );
|
|
lm_invalidate_rect( lmp, &rect, FALSE );
|
|
rect.top = cur_pix;
|
|
rect.bottom = cur_pix + new_height;
|
|
lm_invalidate_rect( lmp, &rect, FALSE );
|
|
}
|
|
*pix_offsetsp = cur_pix;
|
|
*pix_heightsp = new_height;
|
|
if ( !have_first && cur_pix >= ( -lmp->rrr_offset ) )
|
|
{
|
|
have_first = TRUE;
|
|
lmp->first_fully_vis = i;
|
|
}
|
|
cur_pix += new_height;
|
|
/* should be <=, because we are dealing with mathematical rects, but we
|
|
* don't care if the rule is not on the list. pix_offsetp + *pix_heightsp
|
|
* is the mathematical rect of the row, in rrr terms. lmp->rrr_offset +
|
|
* lmp->mlr_height is the mathematical rect of the list, in rrr terms. */
|
|
#if XIWS == XIWS_WM
|
|
if ( cur_pix + lmp->rrr_offset <= lmp->mlr_height )
|
|
lmp->last_fully_vis = i;
|
|
#else
|
|
if ( cur_pix - 1 + lmp->rrr_offset <= lmp->mlr_height )
|
|
lmp->last_fully_vis = i;
|
|
#endif
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rrr_room_pix
|
|
lmp: current lmp
|
|
pixels: number of additional pixels desired in realized row rect
|
|
pixels may be negative, in which case, the desired pixels
|
|
are above the realized row rect
|
|
pixels may be positive, in which case, the desired pixels
|
|
are below the realized row rect
|
|
returns: recs read
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_make_rrr_room_pix( LM_DATA * lmp, int pixels, BOOLEAN do_redraw )
|
|
{
|
|
int recs_read = 0;
|
|
int idx;
|
|
|
|
if ( lmp->nbr_realized_rows == 0 || lmp->nbr_columns == 0 )
|
|
{
|
|
lmp->rrr_bottom = 0;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
return 0;
|
|
}
|
|
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
|
|
|
|
if ( pixels == 0 )
|
|
return recs_read;
|
|
|
|
if ( pixels < 0 )
|
|
{
|
|
while ( TRUE )
|
|
{
|
|
if ( pixels >= lmp->rrr_offset )
|
|
return recs_read;
|
|
if ( get_previous_rec( lmp ) )
|
|
{
|
|
int row_height;
|
|
|
|
row_height = lm_calculate_row_height( lmp, 0 );
|
|
lmp->rrr_offset -= row_height;
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
calculate_visibles( lmp );
|
|
++recs_read;
|
|
}
|
|
else
|
|
return recs_read;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ( TRUE )
|
|
{
|
|
if ( lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset >= pixels )
|
|
return recs_read;
|
|
if ( lmp->get_all_records )
|
|
return recs_read;
|
|
if ( get_next_rec( lmp, FALSE ) )
|
|
{
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
calculate_visibles( lmp );
|
|
++recs_read;
|
|
}
|
|
else
|
|
return recs_read;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rrr_room_rows
|
|
lmp: current lmp
|
|
nbr_rows: nbr of rows to scroll
|
|
returns: pixels to scroll
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
make_rrr_room_rows( LM_DATA * lmp, int *rows, BOOLEAN do_redraw )
|
|
{
|
|
int nbr_rows = *rows;
|
|
|
|
if ( nbr_rows < 0 )
|
|
{
|
|
/* convert nbr_rows to positive, for ease of programming */
|
|
nbr_rows = -nbr_rows;
|
|
while ( TRUE )
|
|
{
|
|
if ( !nbr_rows )
|
|
{
|
|
*rows = 0;
|
|
return 0;
|
|
}
|
|
if ( lmp->first_fully_vis - nbr_rows >= 0 )
|
|
{
|
|
int pixels;
|
|
|
|
pixels = -( lmp->pix_offsets[lmp->first_fully_vis] -
|
|
lmp->pix_offsets[lmp->first_fully_vis - nbr_rows] );
|
|
lmp->update_rows_at_top = nbr_rows;
|
|
*rows = nbr_rows;
|
|
return pixels;
|
|
}
|
|
else
|
|
{
|
|
if ( !lmp->get_all_records && get_previous_rec( lmp ) )
|
|
{
|
|
lmp->pix_heights[0] = lm_calculate_row_height( lmp, 0 );
|
|
lmp->rrr_offset -= lmp->pix_heights[0];
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
}
|
|
else
|
|
{
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
nbr_rows = lmp->first_fully_vis;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN get_next_accepted = TRUE;
|
|
int pixels;
|
|
|
|
pixels = lmp->pix_offsets[lmp->first_fully_vis + nbr_rows] -
|
|
lmp->pix_offsets[lmp->first_fully_vis];
|
|
while ( TRUE )
|
|
{
|
|
int delta_avail;
|
|
|
|
if ( !nbr_rows )
|
|
{
|
|
*rows = 0;
|
|
return 0;
|
|
}
|
|
/* if get_all_records is true, then we never need to get more records if
|
|
* there is a row beyond the last partially visible row, then we don't
|
|
* need to get more records if a get next has been refused, then we have
|
|
* all the records that we are going to get */
|
|
if ( lmp->get_all_records ||
|
|
lmp->last_fully_vis + 1 + nbr_rows < lmp->nbr_realized_rows ||
|
|
!get_next_accepted )
|
|
{
|
|
delta_avail = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] +
|
|
lmp->rrr_offset - lmp->mlr_height;
|
|
if ( lmp->get_all_records || pixels <= delta_avail || !get_next_accepted )
|
|
{
|
|
int nrows,
|
|
cnt,
|
|
pcnt;
|
|
|
|
for ( nrows = 0, cnt = lmp->last_fully_vis + 1, pcnt = 0;
|
|
pcnt < pixels && cnt < lmp->nbr_realized_rows;
|
|
++nrows, ++cnt, pcnt += lmp->pix_heights[cnt] )
|
|
;
|
|
lmp->update_rows_at_bottom = nrows;
|
|
*rows = nbr_rows;
|
|
return pixels;
|
|
}
|
|
}
|
|
if ( !lmp->get_all_records
|
|
&& ( get_next_accepted = get_next_rec( lmp, FALSE ) ) != 0 )
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
else
|
|
{
|
|
calculate_pix_offsets( lmp, do_redraw );
|
|
nbr_rows = lmp->nbr_realized_rows - 1 - lmp->last_fully_vis;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
make_room_rows( LM_DATA * lm_data, int rows, BOOLEAN do_draw )
|
|
{
|
|
return make_rrr_room_rows( lm_data, &rows, do_draw );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_scroll_bar
|
|
itf: current itf
|
|
listdata: list_data
|
|
list: list
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
do_scroll_bar( XI_LIST_DATA * listdata )
|
|
{
|
|
LM_DATA *lmp;
|
|
|
|
if ( listdata->scroll_bar )
|
|
{
|
|
lmp = ( LM_DATA * ) listdata->lm;
|
|
if ( lmp->get_all_records )
|
|
{
|
|
int top,
|
|
prop;
|
|
|
|
if ( lmp->rrr_offset == 0 && lmp->rrr_bottom < lmp->mlr_height )
|
|
{
|
|
top = 0;
|
|
prop = 100;
|
|
}
|
|
else
|
|
{
|
|
top = ( int ) ( -lmp->rrr_offset * 100L / lmp->rrr_bottom );
|
|
if ( lmp->mlr_height - lmp->rrr_offset >= lmp->rrr_bottom - 1 )
|
|
prop = 100 - top;
|
|
else
|
|
prop = ( int ) ( lmp->mlr_height * 100L / lmp->rrr_bottom );
|
|
}
|
|
prop = max( 0, min( 100, prop ) );
|
|
XinScrollBarSet( listdata->sb_win, XinScrollBarTypeEither, 0, 100,
|
|
prop, top );
|
|
}
|
|
else
|
|
{
|
|
int percent1 = 0;
|
|
int percent2 = 100;
|
|
int prop = 100;
|
|
|
|
if ( lmp->nbr_realized_rows > 1 )
|
|
{
|
|
do_lm_cb( listdata->lm, LM_CB_GET_PERCENT, lmp->first_fully_vis,
|
|
0, NULL, &percent1, 0 );
|
|
do_lm_cb( listdata->lm, LM_CB_GET_PERCENT, lmp->last_fully_vis,
|
|
0, NULL, &percent2, 0 );
|
|
prop = min(100, max( 1, ( percent2 - percent1 ) ) );
|
|
#if XIWS == XIWS_WXGTK
|
|
const int act_pos = XinScrollBarPositionGet( listdata->sb_win, XinScrollBarTypeEither );
|
|
if (act_pos >= percent1 && act_pos <= percent2)
|
|
percent1 = -1;
|
|
#endif
|
|
}
|
|
#if XIWS != XIWS_WXGTK
|
|
else
|
|
prop = min(100, max( 1, ( percent2 - percent1 ) ) );
|
|
#endif
|
|
XinScrollBarSet( listdata->sb_win, XinScrollBarTypeEither, 0,
|
|
100, prop, percent1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_remove_all_rows
|
|
lm: current lm
|
|
-------------------------------------------------------------------------*/
|
|
|
|
void
|
|
lm_remove_all_rows( LM_DATA * lmp, BOOLEAN delete_focus )
|
|
{
|
|
int i;
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
if ( lm_focus_rec_get( lmp ) && delete_focus )
|
|
{
|
|
int idx;
|
|
BOOLEAN found = FALSE;
|
|
|
|
for ( idx = 0; idx < lmp->nbr_realized_rows; ++idx )
|
|
{
|
|
if ( lm_focus_rec_get( lmp ) == lmp->recs[idx] )
|
|
{
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if ( !found )
|
|
{
|
|
lm_cb_data.lm = ( LM ) lmp;
|
|
lm_cb_data.cb_type = LM_CB_REC_FREE;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.v.rec_free.record = lm_focus_rec_get( lmp );
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < lmp->nbr_realized_rows; ++i )
|
|
lm_do_rec_event( lmp, i, XIE_REC_FREE );
|
|
|
|
lmp->nbr_realized_rows = 0;
|
|
lmp->rrr_bottom = 0;
|
|
lmp->rrr_offset = 0;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
lm_row_has_focus( LM_DATA * lmp, int row, BOOLEAN is_vert_scrolled )
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
XI_OBJ *focus_obj;
|
|
XI_CELL_DATA *cd;
|
|
|
|
#if 0
|
|
if ( lmp->txt_is_invisible && !lmp->horizontally_scrolling_list )
|
|
return FALSE;
|
|
#endif
|
|
itf = lmp->itf_obj->v.itf;
|
|
focus_obj = itf->focus_obj;
|
|
if ( focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL )
|
|
{
|
|
cd = &focus_obj->v.cell;
|
|
return ( cd->row == row && cd->is_vert_scrolled == is_vert_scrolled );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: fill_previous
|
|
returns: # of records read
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
fill_previous( LM_DATA * lmp )
|
|
{
|
|
int *pix_heights,
|
|
*pix_offsets;
|
|
int offset,
|
|
height;
|
|
int i;
|
|
int result = 0;
|
|
|
|
while ( TRUE )
|
|
{
|
|
|
|
if ( !get_previous_rec( lmp ) )
|
|
break;
|
|
result++;
|
|
/* recalculate the heights and offsets of every row */
|
|
lmp->pix_heights[0] = lm_calculate_row_height( lmp, 0 );
|
|
offset = 0;
|
|
for ( i = 0, pix_heights = &lmp->pix_heights[0],
|
|
pix_offsets = &lmp->pix_offsets[0];
|
|
i < lmp->nbr_realized_rows;
|
|
++i, ++pix_heights, ++pix_offsets )
|
|
{
|
|
*pix_offsets = offset;
|
|
offset += *pix_heights;
|
|
}
|
|
|
|
calculate_visibles( lmp );
|
|
|
|
/* if we finally have enough rows to display the entire list
|
|
*
|
|
* note: we subtract 1 from the space necessary because it is not necessary to
|
|
* create space for the pixel at the bottom of the last row. */
|
|
height = lmp->pix_heights[lmp->nbr_realized_rows - 1];
|
|
if ( !height )
|
|
height = lmp->pix_row_spacing;
|
|
if ( !lmp->get_all_records &&
|
|
( lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
height - 1
|
|
>= lmp->mlr_height ) )
|
|
break;
|
|
}
|
|
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
|
|
lmp->rrr_bottom = lmp->pix_offsets[lmp->nbr_realized_rows - 1]
|
|
+ lmp->pix_heights[lmp->nbr_realized_rows - 1];
|
|
/* subtract 1 from rrr_bottom because of the pixel at the bottom of the last
|
|
* row. */
|
|
lmp->rrr_offset = lmp->mlr_height - ( lmp->rrr_bottom - 1 );
|
|
lmp->rrr_offset = min( 0, lmp->rrr_offset );
|
|
|
|
/* although we have adjusted pix_offsets, and pix_heights, it is still
|
|
* necessary to calculate the first and last fully visible rows */
|
|
calculate_visibles( lmp );
|
|
|
|
/* if the page down does not make the first row editable, then scroll the
|
|
* exact amount to make it editable */
|
|
if ( -lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis] )
|
|
{
|
|
lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
|
|
calculate_visibles( lmp );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* data structure for passing around lm_scroll functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
int nbr_lines;
|
|
int percent;
|
|
long rec;
|
|
BOOLEAN have_rec;
|
|
XinColor color;
|
|
unsigned long attrib;
|
|
int row_height_arg;
|
|
int scroll_type;
|
|
int pix_overlap;
|
|
int nbr_pixels;
|
|
XinRect focus_cell_rct;
|
|
BOOLEAN have_pixels;
|
|
BOOLEAN list_had_focus;
|
|
BOOLEAN is_first_or_last;
|
|
int focus_row;
|
|
int focus_column;
|
|
BOOLEAN v_scrolled;
|
|
int pixels_scrolled;
|
|
} lm_scroll_data;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_scroll_data_construct */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
lm_scroll_data_construct( LM_DATA * lmp, lm_scroll_data * data,
|
|
LM_SCROLL_ARG * arg )
|
|
{
|
|
int pref_overlap;
|
|
|
|
data->nbr_lines = arg->nbr_lines;
|
|
data->percent = arg->percent;
|
|
data->rec = arg->rec;
|
|
data->have_rec = arg->have_rec;
|
|
data->color = arg->color;
|
|
data->attrib = arg->attrib;
|
|
data->row_height_arg = arg->row_height;
|
|
data->have_pixels = FALSE;
|
|
data->list_had_focus = FALSE;
|
|
data->is_first_or_last = FALSE;
|
|
if ( arg->nbr_lines == XI_SCROLL_FIRST && arg->percent == 100 )
|
|
data->nbr_lines = XI_SCROLL_LAST;
|
|
if ( !lmp->nbr_realized_rows )
|
|
data->nbr_lines = XI_SCROLL_FIRST;
|
|
if ( arg->have_rec )
|
|
{
|
|
if ( arg->rec_at_top )
|
|
data->nbr_lines = XI_SCROLL_FIRST;
|
|
else
|
|
data->nbr_lines = XI_SCROLL_LAST;
|
|
}
|
|
data->scroll_type = data->nbr_lines;
|
|
pref_overlap = ( int ) xi_get_pref( XI_PREF_OVERLAP );
|
|
data->pix_overlap = pref_overlap * lmp->pix_row_spacing;
|
|
data->pixels_scrolled = 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_scroll_remove focus */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static BOOLEAN
|
|
lm_scroll_remove_focus( LM_DATA * lmp, lm_scroll_data * data,
|
|
XI_OBJ * old_focus_obj )
|
|
{
|
|
/* remove the focus from the list being scrolled */
|
|
if ( lm_focus_list_has( lmp ) )
|
|
{
|
|
data->list_had_focus = TRUE;
|
|
lm_focus_cell_get( lmp, &data->focus_row, &data->focus_column,
|
|
&data->v_scrolled );
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
switch ( data->nbr_lines )
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
lm_focus_rec_is_above_set( lmp, FALSE );
|
|
case XI_SCROLL_LAST:
|
|
lm_focus_rec_is_above_set( lmp, TRUE );
|
|
break;
|
|
case XI_SCROLL_PGUP:
|
|
lm_focus_rec_is_above_set( lmp, FALSE );
|
|
break;
|
|
case XI_SCROLL_PGDOWN:
|
|
lm_focus_rec_is_above_set( lmp, TRUE );
|
|
break;
|
|
default:
|
|
lm_focus_rec_is_above_set( lmp, ( BOOLEAN ) ( data->nbr_lines > 0 ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xi_get_rect( old_focus_obj, &data->focus_cell_rct );
|
|
if ( !xi_move_focus( lmp->itf_obj ) )
|
|
return FALSE;
|
|
if (data->nbr_lines == XI_SCROLL_FIRST || data->nbr_lines == XI_SCROLL_LAST)
|
|
{ /* The old data went away, so the old focus location is no longer valid. */
|
|
lmp->list_obj->v.list->focus_cell->v.cell.row = 0;
|
|
lmp->list_obj->v.list->focus_cell->v.cell.column = 0;
|
|
lmp->list_obj->v.list->focus_cell->v.cell.is_vert_scrolled = FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_calc_lines */
|
|
/* if nbr_lines is not an integral, and instead is one of XI_SCROLL_FIRST, */
|
|
/* XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDOWN, then calculate */
|
|
/* the number of lines. */
|
|
/*------------------------------------------------------------------------- */
|
|
static void
|
|
lm_scroll_calc_lines( LM_DATA * lmp, lm_scroll_data * data )
|
|
{
|
|
switch ( data->nbr_lines )
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
case XI_SCROLL_LAST:
|
|
data->is_first_or_last = TRUE;
|
|
break;
|
|
case XI_SCROLL_PGUP:
|
|
#if XIWS == XIWS_WM
|
|
data->nbr_pixels = -( lmp->mlr_height - data->pix_overlap );
|
|
#else
|
|
data->nbr_pixels = -( lmp->mlr_height - data->pix_overlap + 1 );
|
|
#endif
|
|
data->have_pixels = TRUE;
|
|
break;
|
|
case XI_SCROLL_PGDOWN:
|
|
#if XIWS == XIWS_WM
|
|
data->nbr_pixels = lmp->mlr_height - data->pix_overlap;
|
|
#else
|
|
data->nbr_pixels = lmp->mlr_height - data->pix_overlap + 1;
|
|
#endif
|
|
data->have_pixels = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_get_initial_rec */
|
|
/*------------------------------------------------------------------------- */
|
|
static BOOLEAN
|
|
lm_scroll_get_initial_rec( LM_DATA * lmp, lm_scroll_data * data,
|
|
int record_location, LM_CB_TYPE event_type )
|
|
{
|
|
int row_height;
|
|
BOOLEAN refused;
|
|
|
|
/* first, get rid of all rows, except the focus row */
|
|
lm_remove_all_rows( lmp, FALSE );
|
|
make_rec_available( lmp, ( BOOLEAN ) record_location, ( BOOLEAN ) ! data->have_rec, TRUE );
|
|
if ( data->have_rec )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
int i;
|
|
|
|
lmp->recs[0] = data->rec;
|
|
lmp->row_colors[0] = data->color;
|
|
lmp->row_attribs[0] = data->attrib;
|
|
row_height = data->row_height_arg;
|
|
refused = FALSE;
|
|
/* cell_data_construct */
|
|
cell_data = lmp->cell_data[0];
|
|
for ( i = 0; i < lmp->nbr_columns; ++i, ++cell_data )
|
|
{
|
|
memset( ( char * ) cell_data, '\0', sizeof( LM_CELL_DATA ) );
|
|
lm_xi_text_construct( lmp, 0, i );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
refused = do_lm_cb_get( ( LM ) lmp, event_type, &lmp->recs[0], &lmp->recs[0],
|
|
data->percent, &lmp->row_colors[0],
|
|
&lmp->row_attribs[0], &row_height );
|
|
if ( refused )
|
|
{
|
|
lm_do_rec_event( lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE );
|
|
--lmp->nbr_realized_rows;
|
|
calculate_visibles( lmp );
|
|
}
|
|
}
|
|
if ( !refused )
|
|
{
|
|
if ( row_height )
|
|
{
|
|
lmp->pix_heights[0] = row_height;
|
|
lmp->set_heights[0] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[0] = 0;
|
|
lmp->set_heights[0] = FALSE;
|
|
}
|
|
lmp->pix_offsets[0] = 0;
|
|
lmp->pix_heights[0] = lm_calculate_row_height( lmp, 0 );
|
|
lm_invalidate_rows_internal( ( LM ) lmp, 0, 0, FALSE, -1, TRUE );
|
|
}
|
|
return !refused;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_fill_forward */
|
|
/* returns # of records read if fill previous called, otherwise 0 */
|
|
/*------------------------------------------------------------------------- */
|
|
|
|
static int
|
|
lm_scroll_fill_forward( LM_DATA * lmp, BOOLEAN have_rec )
|
|
{
|
|
BOOLEAN refused;
|
|
|
|
while ( TRUE )
|
|
{
|
|
int idx;
|
|
|
|
refused = !get_next_rec( lmp, TRUE );
|
|
if ( refused )
|
|
break;
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->pix_heights[idx] = lm_calculate_row_height( lmp, idx );
|
|
if ( idx > 0 )
|
|
lmp->pix_offsets[idx] = lmp->pix_offsets[idx - 1]
|
|
+ lmp->pix_heights[idx - 1];
|
|
else
|
|
lmp->pix_offsets[idx] = 0;
|
|
|
|
/* if we finally have enough rows to display the entire list */
|
|
if ( !lmp->get_all_records && ( lmp->pix_offsets[idx] + lmp->pix_heights[idx]
|
|
>= lmp->mlr_height ) )
|
|
break;
|
|
}
|
|
|
|
/* although we have adjusted pix_offsets, and pix_heights, it is still
|
|
* necessary to calculate the first and last fully visible rows */
|
|
calculate_visibles( lmp );
|
|
|
|
/* If we have the first record and the list is not full, try getting previous
|
|
* records. */
|
|
if ( have_rec && refused )
|
|
return fill_previous( lmp );
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_first */
|
|
/* returns row # of first record requested - i.e. for xi_scroll_rec, the */
|
|
/* row # of the new record. for scroll first with a percentage, the */
|
|
/* row # of that percentage. Normally 0, but with back-fill, can be */
|
|
/* a positive number. */
|
|
/*------------------------------------------------------------------------- */
|
|
static int
|
|
lm_scroll_first( LM_DATA * lmp, lm_scroll_data * data )
|
|
{
|
|
int result = 0;
|
|
|
|
if ( lmp->get_all_records && lmp->nbr_realized_rows > 0 )
|
|
{
|
|
/* have_rec */
|
|
lmp->rrr_offset = -( int ) ( ( long ) lmp->rrr_bottom * data->percent / 100 );
|
|
calculate_visibles( lmp );
|
|
lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
|
|
}
|
|
else
|
|
{
|
|
if ( lm_scroll_get_initial_rec( lmp, data, REC_AT_BOTTOM, LM_CB_GET_FIRST ) )
|
|
result = lm_scroll_fill_forward( lmp, data->have_rec );
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
int nbr_to_free,
|
|
cnt,
|
|
idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis - 1;
|
|
if ( nbr_to_free > 0 )
|
|
{
|
|
for ( cnt = 0; cnt < nbr_to_free; cnt++ )
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
lm_do_rec_event( lmp, cnt, XIE_REC_FREE );
|
|
}
|
|
|
|
for ( idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx )
|
|
lm_row_copy( lmp, idx, idx - nbr_to_free );
|
|
result -= nbr_to_free;
|
|
lm_adjust_rows( lmp, -nbr_to_free );
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
for ( idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free; idx++, cnt++ )
|
|
lm_do_rec_event( lmp, idx, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
{
|
|
XI_OBJ *focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
if ( focus_obj && focus_obj->cid == lmp->cid )
|
|
{
|
|
if ( focus_obj && focus_obj->type == XIT_CELL )
|
|
{
|
|
focus_obj->v.cell.is_vert_scrolled = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_last */
|
|
/* returns row # of requested row */
|
|
/*------------------------------------------------------------------------- */
|
|
static int
|
|
lm_scroll_last( LM_DATA * lmp, lm_scroll_data * data )
|
|
{ /* scroll last */
|
|
int result = 0;
|
|
|
|
if ( lmp->get_all_records )
|
|
{
|
|
if ( lmp->rrr_bottom < lmp->mlr_height )
|
|
lmp->rrr_offset = 0;
|
|
else
|
|
#if XIWS == XIWS_WM
|
|
lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom;
|
|
#else
|
|
lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom + 1;
|
|
#endif
|
|
calculate_visibles( lmp );
|
|
|
|
/* if the page up does not make the first row editable, then scroll the
|
|
* exact amount to make it editable */
|
|
if ( -lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis] )
|
|
{
|
|
int p;
|
|
|
|
p = lmp->pix_offsets[lmp->first_fully_vis] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles( lmp );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data->percent = 0;
|
|
if ( lm_scroll_get_initial_rec( lmp, data, REC_AT_TOP, LM_CB_GET_LAST ) )
|
|
{
|
|
result = fill_previous( lmp );
|
|
/* get one record after the last record, so that there will not be a gray
|
|
* space below the last record, unless there are no more records. */
|
|
get_next_rec( lmp, FALSE );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_calc_pixels */
|
|
/*------------------------------------------------------------------------- */
|
|
static void
|
|
lm_scroll_calc_pixels( LM_DATA * lmp, lm_scroll_data * data )
|
|
{
|
|
/* calculate the max number of pixels that we should scroll */
|
|
if ( data->nbr_pixels < 0 )
|
|
{
|
|
int p;
|
|
|
|
data->nbr_pixels = max( data->nbr_pixels, lmp->rrr_offset );
|
|
lmp->rrr_offset -= data->nbr_pixels;
|
|
calculate_visibles( lmp );
|
|
|
|
/* if the page up does not make the first row editable, then scroll the
|
|
* exact amount to make it editable */
|
|
if ( -lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis] )
|
|
{
|
|
p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles( lmp );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int p;
|
|
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
|
|
/* following line puts row coming onto the list at the bottom of the list
|
|
* completly on the list. new behavior is to have the row at the top of
|
|
* the list to always be completely on the list. nbr_pixels =
|
|
* min(nbr_pixels, lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset); */
|
|
data->nbr_pixels = max( data->nbr_pixels, 0 );
|
|
lmp->rrr_offset -= data->nbr_pixels;
|
|
calculate_visibles( lmp );
|
|
|
|
/* if the page down does not make the first row editable, then scroll the
|
|
* exact amount to make it editable */
|
|
if ( -lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis] )
|
|
{
|
|
p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles( lmp );
|
|
}
|
|
|
|
/* if the page down leaves too much room at the bottom, then make more rows
|
|
* visible. */
|
|
while ( TRUE )
|
|
{
|
|
int h,
|
|
pix_left;
|
|
|
|
if ( lmp->first_fully_vis == 0 )
|
|
break;
|
|
h = lmp->pix_heights[lmp->first_fully_vis - 1];
|
|
/* Add 1 to pix_left (pixels left in mlr), because it is ok for the pixel
|
|
* required for the rule at the bottom of the row to fall below the
|
|
* visible portion of the list. */
|
|
pix_left = -( lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] +
|
|
lmp->rrr_offset - lmp->mlr_height ) + 1;
|
|
if ( pix_left < h )
|
|
break;
|
|
data->nbr_pixels -= h;
|
|
lmp->rrr_offset += h;
|
|
calculate_visibles( lmp );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_scroll_rct
|
|
lmp: current lmp
|
|
r: pointer to rectangle to be filled in
|
|
returns: r
|
|
-------------------------------------------------------------------------*/
|
|
XinRect *
|
|
lm_get_scroll_rct( LM_DATA * lmp, XinRect * r )
|
|
{
|
|
*r = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
r->right = r->left + lmp->pixel_width + BORDER_WIDTH - 1;
|
|
return r;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_middle */
|
|
/*------------------------------------------------------------------------- */
|
|
static int
|
|
lm_scroll_middle( LM_DATA * lmp, lm_scroll_data * data,
|
|
BOOLEAN invalidate )
|
|
{
|
|
int recs_read;
|
|
|
|
recs_read = 0;
|
|
if ( data->have_pixels )
|
|
recs_read = lm_make_rrr_room_pix( lmp, data->nbr_pixels, FALSE );
|
|
else if ( data->nbr_lines )
|
|
{
|
|
recs_read = data->nbr_lines;
|
|
data->nbr_pixels = make_rrr_room_rows( lmp, &recs_read, FALSE );
|
|
}
|
|
lm_scroll_calc_pixels( lmp, data );
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
int nbr_to_free,
|
|
cnt,
|
|
idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis;
|
|
if ( nbr_to_free )
|
|
{
|
|
for ( cnt = 0; cnt < nbr_to_free; cnt++ )
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
lm_do_rec_event( lmp, cnt, XIE_REC_FREE );
|
|
}
|
|
|
|
for ( cnt = nbr_to_free; cnt < lmp->nbr_realized_rows; ++cnt )
|
|
lm_row_copy( lmp, cnt, cnt - nbr_to_free );
|
|
lm_adjust_rows( lmp, -nbr_to_free );
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
for ( idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free;
|
|
idx++, cnt++ )
|
|
lm_do_rec_event( lmp, idx, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
|
|
for ( idx = lmp->nbr_realized_rows;
|
|
idx < lmp->realized_rows_array_len;
|
|
++idx )
|
|
init_row( lmp, idx );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
}
|
|
|
|
if ( invalidate )
|
|
{
|
|
XinRect r;
|
|
|
|
lm_get_scroll_rct( lmp, &r );
|
|
xi_set_clip( lmp->win, NULL );
|
|
if ( data->nbr_pixels )
|
|
{
|
|
XinWindowPaintForce( lmp->win );
|
|
xi_set_update_obj( lmp->list_obj );
|
|
lmp->update_cells_only = TRUE;
|
|
xi_scroll_rect( lmp->win, &r, 0, -data->nbr_pixels );
|
|
data->pixels_scrolled = data->nbr_pixels;
|
|
}
|
|
}
|
|
return recs_read;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_replace_focus */
|
|
/*------------------------------------------------------------------------- */
|
|
static void
|
|
lm_scroll_replace_focus( LM_DATA * lmp, lm_scroll_data * data,
|
|
XI_OBJ * old_focus_obj, BOOLEAN same_cell )
|
|
{
|
|
/* put the focus back */
|
|
if ( data->list_had_focus )
|
|
{
|
|
if ( old_focus_obj->type == XIT_CELL )
|
|
{
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
else
|
|
{
|
|
if ( same_cell )
|
|
{
|
|
int col = old_focus_obj->v.cell.column;
|
|
int row,
|
|
t,
|
|
b;
|
|
int max_intersect,
|
|
intersect_row;
|
|
XI_OBJ cell;
|
|
XinRect cell_rct;
|
|
int tr;
|
|
|
|
max_intersect = 0;
|
|
intersect_row = -1;
|
|
tr = min( lmp->nbr_realized_rows, lmp->last_fully_vis + 1 );
|
|
for ( row = lmp->first_fully_vis; row < tr; ++row )
|
|
{
|
|
XI_MAKE_CELL( &cell, lmp->list_obj, ( unsigned char ) row,
|
|
( unsigned char ) col );
|
|
xi_get_rect( &cell, &cell_rct );
|
|
t = max( cell_rct.top, data->focus_cell_rct.top );
|
|
b = min( cell_rct.bottom, data->focus_cell_rct.bottom );
|
|
if ( ( b - t ) > max_intersect )
|
|
{
|
|
max_intersect = b - t;
|
|
intersect_row = row;
|
|
}
|
|
}
|
|
if ( intersect_row != -1 )
|
|
{
|
|
XI_MAKE_CELL( &cell, lmp->list_obj, ( unsigned char ) intersect_row,
|
|
( unsigned char ) col );
|
|
xi_move_focus( &cell );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ( data->scroll_type )
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
case XI_SCROLL_PGUP:
|
|
data->focus_row = lmp->first_fully_vis;
|
|
break;
|
|
case XI_SCROLL_LAST:
|
|
case XI_SCROLL_PGDOWN:
|
|
data->focus_row = lmp->last_fully_vis;
|
|
break;
|
|
default:
|
|
data->focus_row = clip( data->focus_row, lmp->first_fully_vis,
|
|
lmp->last_fully_vis );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
xi_move_focus( old_focus_obj );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_scroll
|
|
lm: current lm
|
|
nbr_lines: nbr of lines to scroll, may be positive or negative, may be set
|
|
to XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDN
|
|
percent: passed with XI_SCROLL_FIRST event
|
|
same_cell: sometimes the focus goes back onto the same cell. In other cases,
|
|
for instance, XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, and
|
|
XI_SCROLL_PGDN, we don't want to put the focus back on the same cell,
|
|
but instead, want to put the focus on the first or last fully visible
|
|
row.
|
|
invalidate: indicates whether to invalidate the list. This is only set to FALSE when
|
|
xi_scroll_internal is called when the interface is created.
|
|
rec: if have_rec is TRUE, then use rec for the first record, and don't do get first
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_scroll( LM_SCROLL_ARG * arg )
|
|
{
|
|
lm_scroll_data data;
|
|
int result = 0;
|
|
XI_OBJ *old_focus_obj;
|
|
LM_DATA *lmp = ( LM_DATA * ) arg->lm;
|
|
XI_OBJ *itf = lmp->itf_obj;
|
|
BOOLEAN invalidate = !itf->v.itf->half_baked;
|
|
BOOLEAN v_scrolled,
|
|
focus;
|
|
int new_row_height;
|
|
int row,
|
|
column;
|
|
|
|
if ( ( xi_get_attrib( lmp->list_obj ) & XI_ATR_VISIBLE ) == 0 )
|
|
invalidate = FALSE;
|
|
lm_scroll_data_construct( lmp, &data, arg );
|
|
/* If the focus is on the first row, and scrolling up, or the focus is on the
|
|
* last row and scrolling down, return 0. */
|
|
if ( lmp->get_all_records )
|
|
{
|
|
if ( lmp->first_fully_vis == 0 && data.nbr_lines < 0 )
|
|
return 0;
|
|
if ( lmp->last_fully_vis == lmp->nbr_realized_rows &&
|
|
data.nbr_lines > 0 && data.nbr_lines < XI_SCROLL_PGUP )
|
|
return 0;
|
|
}
|
|
if ( !lmp->itf_obj->v.itf->half_baked && invalidate )
|
|
XinWindowPaintForce( lmp->win );
|
|
old_focus_obj = itf->v.itf->focus_obj;
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
focus = lm_focus_cell_get( lmp, &row, &column, &v_scrolled );
|
|
if ( focus && !v_scrolled )
|
|
{
|
|
new_row_height = lm_calculate_row_height( lmp, row );
|
|
if ( new_row_height != lmp->pix_heights[row] )
|
|
lm_set_row_height( ( LM ) lmp, row, new_row_height, FALSE, 0, FALSE );
|
|
}
|
|
}
|
|
if ( !lm_scroll_remove_focus( lmp, &data, old_focus_obj ) )
|
|
return 0;
|
|
lm_scroll_calc_lines( lmp, &data );
|
|
if ( data.is_first_or_last )
|
|
{
|
|
if ( data.nbr_lines == XI_SCROLL_FIRST )
|
|
result = lm_scroll_first( lmp, &data );
|
|
else
|
|
result = lm_scroll_last( lmp, &data );
|
|
if ( invalidate )
|
|
{
|
|
XinRect r;
|
|
|
|
xi_invalidate_rect( lmp->win, lm_get_scroll_rct( lmp, &r ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = lm_scroll_middle( lmp, &data, invalidate );
|
|
arg->pixels_scrolled = data.pixels_scrolled;
|
|
}
|
|
|
|
lm_scroll_replace_focus( lmp, &data, old_focus_obj, arg->same_cell );
|
|
if ( lmp->row_focus_border && lmp->nbr_realized_rows > 0 )
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
BOOLEAN is_hscrolled;
|
|
BOOLEAN is_vis;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &is_vert_scrolled );
|
|
is_vis = lm_focus_cell_is_visible( lmp, &is_hscrolled );
|
|
if ( ( is_vis || is_hscrolled ) && !is_vert_scrolled )
|
|
{
|
|
lm_redraw_row( lmp, focus_row, FALSE );
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
set_focus_cell_rct( lmp, focus_row, focus_column, FALSE );
|
|
} /* is vis */
|
|
} /* focus border */
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
if ( invalidate )
|
|
XinWindowPaintForce( lmp->win );
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_text
|
|
lm: current lm
|
|
s: string to set
|
|
row:
|
|
column:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_text( LM lm, const char *s, int row, int column, BOOLEAN v_scrolled )
|
|
{
|
|
BOOLEAN was_suspended = FALSE;
|
|
BOOLEAN preserve_focus_text;
|
|
LM_COLUMN_DATA *lmcd;
|
|
XinRect rct;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
lmcd = lmp->lm_column_data[column];
|
|
if ( row == LM_HEADING_TEXT )
|
|
{
|
|
lmcd->heading_text = ( char * ) xi_tree_realloc( lmcd->heading_text, strlen( s ) + 1 );
|
|
strcpy( lmcd->heading_text, s );
|
|
lm_get_cell_rect( &rct, lm, 1, column, FALSE, TRUE );
|
|
rct.top = lmp->pix_hdr_bottom -
|
|
max( lmp->pix_cell_height, lmp->min_heading_height + 2 * BORDER_WIDTH );
|
|
rct.bottom = lmp->pix_hdr_bottom;
|
|
if ( ( lmp->attrib & LM_ATR_VISIBLE ) != 0 )
|
|
xi_invalidate_rect( lmp->win, &rct );
|
|
}
|
|
else
|
|
{
|
|
int new_row_height;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[row][column];
|
|
preserve_focus_text = FALSE;
|
|
if ( lm_focus_cell_has( lmp, row, column, v_scrolled ) && lmp->itf_obj->v.itf->chg_flag )
|
|
{
|
|
was_suspended = TRUE;
|
|
lm_focus_cell_invis_make( lmp );
|
|
preserve_focus_text = TRUE;
|
|
}
|
|
/* If the cell has focus the XI_TEXT string needs updated */
|
|
if ( lm_focus_cell_has( lmp, row, column, v_scrolled ) )
|
|
{
|
|
xi_text_set( cell_data->xi_text, s );
|
|
}
|
|
else if ( !v_scrolled )
|
|
xi_text_set( cell_data->xi_text, s );
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
lm_focus_cell_text_set( lmp, preserve_focus_text, s, row, column, v_scrolled );
|
|
if ( !v_scrolled )
|
|
{
|
|
new_row_height = lm_calculate_row_height( lmp, row );
|
|
if ( new_row_height != lmp->pix_heights[row] )
|
|
lm_set_row_height( lm, row, new_row_height, FALSE, 0, FALSE );
|
|
if ( LMP( lm )->attrib & XI_ATR_VISIBLE && LMP( lm )->cell_data[row][column].valid_data )
|
|
redraw_cell( lm, row, column, FALSE );
|
|
}
|
|
if ( was_suspended )
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: next cell
|
|
lm: current lm
|
|
c: character causing the focus to change
|
|
next_row: int pointer to be filled in with next row
|
|
next_col: int pointer to be filled in with next column
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
next_cell( LM lm, int c, int *next_row, int *next_col, BOOLEAN v_scrolled )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
switch ( c )
|
|
{
|
|
case XI_KEY_BTAB:
|
|
--*next_col;
|
|
if ( *next_col < 0 )
|
|
{
|
|
*next_col = lmp->nbr_columns - 1;
|
|
if ( ( lmp->attrib & LM_ATR_TABWRAP ) )
|
|
--* next_row;
|
|
}
|
|
break;
|
|
case '\t':
|
|
++*next_col;
|
|
if ( *next_col >= lmp->nbr_columns )
|
|
{
|
|
*next_col = 0;
|
|
if ( ( lmp->attrib & LM_ATR_TABWRAP ) )
|
|
{
|
|
if ( *next_row == 255 && v_scrolled )
|
|
*next_row = 0;
|
|
else
|
|
++* next_row;
|
|
}
|
|
}
|
|
break;
|
|
case XI_KEY_UP:
|
|
--*next_row;
|
|
break;
|
|
case XI_KEY_DOWN:
|
|
if ( *next_row == 255 && v_scrolled )
|
|
*next_row = 0;
|
|
else
|
|
++* next_row;
|
|
break;
|
|
case XI_KEY_WLEFT:
|
|
case XI_KEY_LEFT:
|
|
--*next_col;
|
|
if ( *next_col < 0 )
|
|
*next_col = lmp->nbr_columns - 1;
|
|
break;
|
|
case XI_KEY_WRIGHT:
|
|
case XI_KEY_RIGHT:
|
|
++*next_col;
|
|
if ( *next_col >= lmp->nbr_columns )
|
|
*next_col = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_CHAR, LM_CB_CHANGE, LM_CB_FOCUS, LM_CB_REC_ALLOCATE,
|
|
LM_CB_REC_FREE
|
|
row: relevent row
|
|
column: relevent column
|
|
ep: xvt event that caused the LM event, used to pass on shift and control
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
do_lm_cb( LM lm, LM_CB_TYPE cb_reason, int row, int column, XinEvent * ep, int *percent, int pixels )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
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;
|
|
switch ( cb_reason )
|
|
{
|
|
case LM_CB_REC_ALLOCATE:
|
|
lm_cb_data.v.rec_allocate.record = lmp->recs[row];
|
|
if ( lm_cb_data.v.rec_allocate.record )
|
|
return FALSE;
|
|
break;
|
|
case LM_CB_REC_FREE:
|
|
lm_cb_data.v.rec_free.record = lmp->recs[row];
|
|
if ( lmp->have_last_rec && lm_cb_data.v.rec_free.record == lmp->last_rec )
|
|
lmp->have_last_rec = FALSE;
|
|
if ( !lm_cb_data.v.rec_allocate.record )
|
|
return FALSE;
|
|
break;
|
|
case LM_CB_CHAR:
|
|
lm_cb_data.v.chr.ch = ep->v.character.ch;
|
|
lm_cb_data.v.chr.shift = ep->v.character.shift;
|
|
lm_cb_data.v.chr.control = ep->v.character.control;
|
|
lm_cb_data.v.chr.alt = ep->v.character.alt;
|
|
lm_cb_data.v.chr.is_paste = FALSE;
|
|
lm_cb_data.v.chr.refused = FALSE;
|
|
break;
|
|
case LM_CB_CELL_BTN:
|
|
if ( ep->type == XinEventCharacter )
|
|
{
|
|
lm_cb_data.v.cell_btn.shift = ep->v.character.shift;
|
|
lm_cb_data.v.cell_btn.control = ep->v.character.control;
|
|
}
|
|
else
|
|
{
|
|
lm_cb_data.v.cell_btn.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.cell_btn.control = ep->v.mouse.control;
|
|
}
|
|
break;
|
|
case LM_CB_GET_PERCENT:
|
|
lm_cb_data.v.get_percent.record = lmp->recs[row];
|
|
break;
|
|
case LM_CB_ROW_SIZE:
|
|
lm_cb_data.v.row_size.new_row_height = pixels;
|
|
break;
|
|
default:
|
|
lm_cb_data.v.refused = FALSE;
|
|
break;
|
|
}
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
/* retval = FALSE if event refused */
|
|
switch ( cb_reason )
|
|
{
|
|
case LM_CB_REC_ALLOCATE:
|
|
lmp->recs[row] = lm_cb_data.v.rec_allocate.record;
|
|
return FALSE;
|
|
case LM_CB_REC_FREE:
|
|
lmp->recs[row] = 0L;
|
|
return FALSE;
|
|
case LM_CB_CHAR:
|
|
if ( !lm_cb_data.v.chr.refused )
|
|
ep->v.character.ch = lm_cb_data.v.chr.ch;
|
|
return ( !lm_cb_data.v.chr.refused );
|
|
case LM_CB_GET_PERCENT:
|
|
*percent = lm_cb_data.v.get_percent.percent;
|
|
return FALSE;
|
|
case LM_CB_ROW_SIZE:
|
|
return ( !lm_cb_data.v.row_size.refused );
|
|
default:
|
|
return ( !lm_cb_data.v.refused );
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_get
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_GET_FIRST, LM_CB_GET_LAST, LM_CB_GET_NEXT,
|
|
LM_CB_GET_PREV
|
|
spec_rec:
|
|
data_rec:
|
|
percent:
|
|
returns: TRUE if event refused
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
do_lm_cb_get( LM lm, LM_CB_TYPE cb_reason, long *spec_rec,
|
|
long *data_rec, int percent, XinColor * color,
|
|
unsigned long *attrib, int *row_height )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.v.rec_request.spec_rec = *spec_rec;
|
|
lm_cb_data.v.rec_request.data_rec = *data_rec;
|
|
lm_cb_data.v.rec_request.percent = percent;
|
|
lm_cb_data.v.rec_request.color = *color;
|
|
lm_cb_data.v.rec_request.attrib = *attrib;
|
|
lm_cb_data.v.rec_request.refused = FALSE;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
if ( cb_reason == LM_CB_GET_NEXT && lm_cb_data.v.rec_request.refused )
|
|
{
|
|
lmp->have_last_rec = TRUE;
|
|
lmp->last_rec = lm_cb_data.v.rec_request.spec_rec;
|
|
}
|
|
if ( !lm_cb_data.v.rec_request.refused )
|
|
{
|
|
if ( cb_reason == LM_CB_GET_LAST )
|
|
{
|
|
lmp->have_last_rec = TRUE;
|
|
lmp->last_rec = lm_cb_data.v.rec_request.data_rec;
|
|
}
|
|
*data_rec = lm_cb_data.v.rec_request.data_rec;
|
|
*color = lm_cb_data.v.rec_request.color;
|
|
*attrib = lm_cb_data.v.rec_request.attrib;
|
|
#if XIWS != XIWS_WM
|
|
*row_height = lm_cb_data.v.rec_request.row_height;
|
|
#else
|
|
*row_height = 0;
|
|
#endif
|
|
if ( lm_cb_data.v.rec_request.has_focus
|
|
&& xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
if ( lm_focus_rec_get( lmp ) )
|
|
{
|
|
lm_cb_data.lm = ( LM ) lmp;
|
|
lm_cb_data.cb_type = LM_CB_REC_FREE;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.v.rec_free.record = lm_focus_rec_get( lmp );
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
}
|
|
lm_focus_rec_set( lmp, *data_rec );
|
|
}
|
|
}
|
|
return lm_cb_data.v.rec_request.refused;
|
|
}
|
|
|
|
|
|
static void
|
|
calculate_next_cell( LM_DATA * lmp, int *next_row, int *next_col,
|
|
BOOLEAN * use_key, int ch, BOOLEAN * off_top,
|
|
BOOLEAN * off_bottom )
|
|
{
|
|
BOOLEAN keep_looking;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
keep_looking = *use_key;
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
*next_row = focus_row;
|
|
*next_col = focus_column;
|
|
while ( keep_looking )
|
|
{
|
|
next_cell( ( LM ) lmp, ch, next_row, next_col, v_scrolled );
|
|
if ( *next_row < 0 )
|
|
{
|
|
/* off top logic */
|
|
if ( lmp->get_all_records )
|
|
{
|
|
*use_key = FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
keep_looking = FALSE;
|
|
*off_top = TRUE;
|
|
}
|
|
}
|
|
else if ( *next_row >= lmp->nbr_realized_rows )
|
|
{
|
|
/* off bottom logic */
|
|
if ( lmp->get_all_records )
|
|
{
|
|
*use_key = FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
keep_looking = FALSE;
|
|
*off_bottom = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[*next_row][*next_col];
|
|
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, *next_row, *next_col, TRUE );
|
|
if ( CELL_IS_ENABLED( lmp, *next_row, *next_col )
|
|
&& !CELL_IS_SELECTABLE( lmp, *next_row, *next_col )
|
|
&& lmp->cell_data[*next_row][*next_col].icon_rid == 0
|
|
&& lmp->cell_data[*next_row][*next_col].bitmap == NULL )
|
|
|
|
/* found a valid cell */
|
|
keep_looking = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
lm_adjust_rows( LM_DATA * lmp, int delta )
|
|
{
|
|
XI_OBJ *focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
if ( focus_obj && focus_obj->cid == lmp->cid )
|
|
{
|
|
if ( focus_obj && focus_obj->type == XIT_CELL )
|
|
{
|
|
if ( (int)focus_obj->v.cell.row + delta < 0 )
|
|
{
|
|
focus_obj->v.cell.is_vert_scrolled = TRUE;
|
|
focus_obj->v.cell.row += delta;
|
|
return;
|
|
}
|
|
focus_obj->v.cell.row += delta;
|
|
if ( !focus_obj->v.cell.is_vert_scrolled
|
|
&& ( long ) focus_obj->v.cell.row >= ( long ) lmp->nbr_realized_rows )
|
|
focus_obj->v.cell.is_vert_scrolled = TRUE;
|
|
}
|
|
if ( focus_obj && focus_obj->type == XIT_ROW )
|
|
focus_obj->v.row += delta;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: navigate_char_event
|
|
lm: current lm
|
|
ep: xvt event
|
|
returns: TRUE if key was used.
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
navigate_char_event( LM lm, XinEvent * ep )
|
|
{
|
|
BOOLEAN use_key = FALSE;
|
|
BOOLEAN off_top = FALSE;
|
|
BOOLEAN off_bottom = FALSE;
|
|
BOOLEAN should_redraw = TRUE;
|
|
int next_row,
|
|
next_col,
|
|
row_inc,
|
|
col_inc;
|
|
LM_DATA *lmp = LMP( lm );
|
|
short c = ep->v.character.ch;
|
|
|
|
if ( !lm_focus_list_has( lmp ) )
|
|
return FALSE;
|
|
if ( ( c == '\r' || c == '\n' ) && lmp->itf_obj->v.itf->tab_on_enter)
|
|
{
|
|
int row, col;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &row, &col, &is_vert_scrolled );
|
|
if (!lmp->lm_column_data[col]->cr_ok)
|
|
{
|
|
c = (short)xi_get_pref( XI_PREF_FORM_TAB_CHAR );
|
|
ep->v.character.ch = c;
|
|
}
|
|
}
|
|
switch ( c )
|
|
{
|
|
case '\t':
|
|
case XI_KEY_BTAB:
|
|
case XI_KEY_UP:
|
|
case XI_KEY_DOWN:
|
|
case XI_KEY_PREV:
|
|
case XI_KEY_NEXT:
|
|
use_key = TRUE;
|
|
break;
|
|
case XI_KEY_WRIGHT:
|
|
case XI_KEY_WLEFT:
|
|
case XI_KEY_LEFT:
|
|
case XI_KEY_RIGHT:
|
|
if ( ( lmp->attrib & LM_ATR_NAVIGATE ) || ep->v.character.control )
|
|
use_key = TRUE;
|
|
break;
|
|
}
|
|
switch ( c )
|
|
{
|
|
case XI_KEY_UP:
|
|
case XI_KEY_DOWN:
|
|
case XI_KEY_PREV:
|
|
case XI_KEY_NEXT:
|
|
{
|
|
if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE )
|
|
{
|
|
XI_TEXT *text = xi_text_focus_get( lmp->win );
|
|
|
|
if ( text != 0 && text->multi_line && !ep->v.character.control
|
|
&& !( lmp->attrib & LM_ATR_NAVIGATE ) )
|
|
return FALSE;
|
|
}
|
|
switch ( c )
|
|
{
|
|
case XI_KEY_PREV:
|
|
xi_control_event_scroll( lmp->list_obj, XI_SCROLL_PGUP, 0, TRUE );
|
|
return TRUE;
|
|
case XI_KEY_NEXT:
|
|
xi_control_event_scroll( lmp->list_obj, XI_SCROLL_PGDOWN, 0, TRUE );
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
case XI_KEY_WRIGHT:
|
|
case XI_KEY_WLEFT:
|
|
case XI_KEY_LEFT:
|
|
case XI_KEY_RIGHT:
|
|
if ( !use_key )
|
|
return FALSE;
|
|
}
|
|
calculate_next_cell( lmp, &next_row, &next_col,
|
|
&use_key, c, &off_top, &off_bottom );
|
|
if ( use_key )
|
|
{
|
|
XI_LIST_DATA *list_data;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
if ( off_top || off_bottom )
|
|
{
|
|
int old_row_height,
|
|
focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
BOOLEAN do_redraw;
|
|
|
|
lm_focus_cell_invis_make( lmp );
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
old_row_height = lmp->pix_heights[focus_row];
|
|
do_redraw = ( lm_calculate_row_height( lmp, focus_row ) != old_row_height );
|
|
if ( off_top )
|
|
make_room_rows( lmp, -1, do_redraw );
|
|
else
|
|
make_room_rows( lmp, 1, do_redraw );
|
|
/* calculate next cell again, because the desired next cell may have
|
|
* changed. */
|
|
calculate_next_cell( lmp, &next_row, &next_col, &use_key, c,
|
|
&off_top, &off_bottom );
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
row_inc = next_row - focus_row;
|
|
col_inc = next_col - focus_column;
|
|
next_row = focus_row + row_inc;
|
|
if ( next_row >= lmp->nbr_realized_rows )
|
|
next_row = lmp->nbr_realized_rows - 1;
|
|
if ( next_row < 0 )
|
|
next_row = 0;
|
|
next_col = focus_column + col_inc;
|
|
|
|
while ( TRUE )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[next_row][next_col];
|
|
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, next_row, next_col, TRUE );
|
|
if ( CELL_IS_ENABLED( lmp, next_row, next_col )
|
|
&& !CELL_IS_SELECTABLE( lmp, next_row, next_col )
|
|
&& lmp->cell_data[next_row][next_col].icon_rid == 0
|
|
&& lmp->cell_data[next_row][next_col].bitmap == NULL )
|
|
break;
|
|
next_cell( lm, off_bottom ? '\t' :
|
|
XI_KEY_BTAB, &next_row, &next_col, v_scrolled );
|
|
}
|
|
if ( list_data->vert_sync_list &&
|
|
!list_data->scrolling_in_progress )
|
|
{
|
|
XI_OBJ *other_list;
|
|
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj( lmp->itf_obj,
|
|
list_data->vert_sync_list );
|
|
if ( other_list )
|
|
xi_scroll( other_list, off_top ? -1 : 1 );
|
|
XinWindowPaintForce( lmp->win );
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if ( focus_row > lmp->last_fully_vis )
|
|
{
|
|
LM_FOCUS_CELL_VISIBLE_FORCE_ARGS args;
|
|
|
|
MEMCLEAR( args );
|
|
args.lmp = lmp;
|
|
args.row = focus_row;
|
|
args.column = focus_column;
|
|
args.vert_scrolled = v_scrolled;
|
|
lm_focus_cell_visible_force( &args );
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
next_row = focus_row;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
}
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
}
|
|
|
|
else if ( next_row < lmp->first_fully_vis || next_row > lmp->last_fully_vis )
|
|
{
|
|
if ( list_data->vert_sync_list &&
|
|
!list_data->scrolling_in_progress )
|
|
{
|
|
XI_OBJ *other_list;
|
|
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj( lmp->itf_obj,
|
|
list_data->vert_sync_list );
|
|
if ( other_list )
|
|
xi_scroll( other_list,
|
|
next_row < lmp->first_fully_vis ? -1 : 1 );
|
|
XinWindowPaintForce( lmp->win );
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( next_row < lmp->first_fully_vis )
|
|
{
|
|
int delta,
|
|
idx2,
|
|
pix2,
|
|
old_pix,
|
|
cnt,
|
|
height;
|
|
XinRect tmp_rct;
|
|
|
|
if ( lmp->first_fully_vis == 0 )
|
|
return use_key;
|
|
lm_focus_cell_invis_make( lmp );
|
|
idx2 = lmp->first_fully_vis - 1;
|
|
pix2 = lmp->pix_offsets[idx2];
|
|
old_pix = -lmp->rrr_offset;
|
|
delta = old_pix - pix2;
|
|
lmp->rrr_offset += delta;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
if ( !lmp->itf_obj->v.itf->half_baked )
|
|
XinWindowPaintForce( lmp->win );
|
|
xi_set_update_obj( lmp->list_obj );
|
|
lm_get_scroll_rct( lmp, &tmp_rct );
|
|
|
|
/* calculate lmp->update_rows_at_top to speed up scrolling the list */
|
|
height = delta;
|
|
for ( cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt )
|
|
height -= lmp->pix_heights[cnt];
|
|
lmp->update_rows_at_top = cnt;
|
|
|
|
xi_scroll_rect( lmp->win, &tmp_rct, 0, delta );
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
should_redraw = FALSE;
|
|
}
|
|
|
|
if ( next_row > lmp->last_fully_vis )
|
|
{
|
|
int delta,
|
|
delta2,
|
|
diff,
|
|
cnt,
|
|
height,
|
|
first,
|
|
old_row_height,
|
|
focus_row;
|
|
int idx,
|
|
missing;
|
|
int focus_column,
|
|
new_row_height;
|
|
BOOLEAN v_scrolled;
|
|
XinRect tmp_rct;
|
|
|
|
if ( lmp->last_fully_vis >= lmp->nbr_realized_rows )
|
|
return use_key;
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
old_row_height = lmp->pix_heights[focus_row];
|
|
lm_focus_cell_invis_make( lmp );
|
|
delta = lmp->pix_heights[lmp->first_fully_vis];
|
|
lm_make_rrr_room_pix( lmp, delta, TRUE );
|
|
idx = lmp->last_fully_vis + 1;
|
|
missing = lmp->mlr_height - ( lmp->pix_offsets[idx] + lmp->pix_heights[idx] );
|
|
if ( lmp->last_fully_vis + 1 < lmp->nbr_realized_rows )
|
|
delta = max( delta, missing );
|
|
lmp->rrr_offset -= delta;
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
calculate_visibles( lmp );
|
|
if ( -lmp->rrr_offset != lmp->pix_offsets[lmp->first_fully_vis] )
|
|
{
|
|
delta2 = lmp->pix_offsets[lmp->first_fully_vis] +
|
|
lmp->rrr_offset;
|
|
lmp->rrr_offset -= delta2;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
calculate_visibles( lmp );
|
|
delta += delta2;
|
|
}
|
|
diff = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] -
|
|
lmp->mlr_height + lmp->rrr_offset;
|
|
if ( !lmp->itf_obj->v.itf->half_baked )
|
|
XinWindowPaintForce( lmp->win );
|
|
if ( diff < 0 )
|
|
lm_make_rrr_room_pix( lmp, -diff, FALSE );
|
|
xi_set_update_obj( lmp->list_obj );
|
|
lm_get_scroll_rct( lmp, &tmp_rct );
|
|
|
|
/* calculate lmp->update_rows_at_bottom to speed up scrolling the list */
|
|
height = lmp->mlr.bottom - lmp->mlr.top - delta;
|
|
for ( cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt )
|
|
height -= lmp->pix_heights[cnt];
|
|
first = cnt - 1;
|
|
height += delta;
|
|
for ( ; height > 0; ++cnt )
|
|
height -= lmp->pix_heights[cnt];
|
|
lmp->update_rows_at_bottom = cnt - first;
|
|
|
|
/* scroll the list */
|
|
xi_scroll_rect( lmp->win, &tmp_rct, 0, -delta );
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
|
|
/* if the row height changed, then we need to redraw the row */
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
new_row_height = lmp->pix_heights[focus_row];
|
|
if ( new_row_height != old_row_height )
|
|
{
|
|
lm_redraw_row( lmp, focus_row, FALSE );
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
}
|
|
should_redraw = FALSE;
|
|
}
|
|
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
int nbr_to_free,
|
|
cnt,
|
|
i,
|
|
idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis;
|
|
if ( nbr_to_free > 0 )
|
|
{
|
|
int rheight;
|
|
|
|
rheight = 0;
|
|
for ( cnt = 0; cnt < nbr_to_free; cnt++ )
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
rheight += lmp->pix_heights[cnt];
|
|
lm_do_rec_event( lmp, cnt, XIE_REC_FREE );
|
|
}
|
|
|
|
for ( idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx )
|
|
lm_row_copy( lmp, idx, idx - nbr_to_free );
|
|
lm_adjust_rows( lmp, -nbr_to_free );
|
|
|
|
/* calculate next cell again, because the desired next cell may have
|
|
* changed. */
|
|
calculate_next_cell( lmp, &next_row, &next_col,
|
|
&use_key, c, &off_top, &off_bottom );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_pix_offsets( lmp, should_redraw );
|
|
calculate_visibles( lmp );
|
|
lm_make_rrr_room_pix( lmp, rheight, TRUE );
|
|
calculate_pix_offsets( lmp, should_redraw );
|
|
calculate_visibles( lmp );
|
|
}
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
if ( nbr_to_free > 0 )
|
|
{
|
|
for ( i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
|
|
i++, cnt++ )
|
|
lm_do_rec_event( lmp, i, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
}
|
|
|
|
calculate_pix_offsets( lmp, should_redraw );
|
|
|
|
lm_make_rrr_room_pix( lmp, 0, FALSE );
|
|
}
|
|
do_lm_cb( lm, LM_CB_FOCUS, next_row, next_col, NULL, NULL, 0 );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
}
|
|
return use_key;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_insert_row
|
|
lm: current lm
|
|
row: row to insert
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_insert_row( LM lm, int row )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( lmp->get_all_records )
|
|
XinError( 20919, XinSeverityFatal, 0L );
|
|
if ( xi_move_focus( lmp->itf_obj ) )
|
|
{
|
|
if ( row > 0 && lmp->nbr_realized_rows )
|
|
{
|
|
int idx = 0,
|
|
row_height,
|
|
pix;
|
|
XinRect r,
|
|
row_rect;
|
|
BOOLEAN is_visible;
|
|
|
|
row = min( row, lmp->nbr_realized_rows );
|
|
|
|
pix = lmp->pix_offsets[row - 1] + lmp->pix_heights[row - 1]
|
|
+ 1;
|
|
is_visible = ( pix <= lmp->mlr_height - lmp->rrr_offset );
|
|
|
|
if ( is_visible || lmp->get_all_records )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
int i;
|
|
|
|
make_rec_available( lmp, REC_AT_BOTTOM, FALSE, FALSE );
|
|
for ( i = lmp->nbr_realized_rows - 2; i >= row; i-- )
|
|
lm_row_copy( lmp, i, i + 1 );
|
|
idx = row;
|
|
/* cell_data_construct */
|
|
cell_data = lmp->cell_data[idx];
|
|
for ( i = 0; i < lmp->nbr_columns; ++i, ++cell_data )
|
|
{
|
|
memset( ( char * ) cell_data, '\0', sizeof( LM_CELL_DATA ) );
|
|
lm_xi_text_construct( lmp, idx, i );
|
|
}
|
|
lmp->recs[idx] = 0L;
|
|
lm_do_rec_event( lmp, idx, XIE_REC_ALLOCATE );
|
|
if ( do_lm_cb_get( ( LM ) lmp, LM_CB_GET_NEXT,
|
|
&lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height ) )
|
|
{
|
|
lm_do_rec_event( lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE );
|
|
for ( i = row; i < lmp->nbr_realized_rows - 2; ++i )
|
|
lm_row_copy( lmp, i + 1, i );
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
if ( row_height )
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = lm_calculate_row_height( lmp, idx );
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
|
|
lm_invalidate_rows_internal( ( LM ) lmp, idx, idx, FALSE, -1, TRUE );
|
|
}
|
|
|
|
if ( is_visible )
|
|
{
|
|
lm_get_scroll_rct( lmp, &r );
|
|
row_height = lm_calculate_row_height( lmp, idx );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
lm_get_rect( lm, LM_ROW, idx, &row_rect );
|
|
r.top = row_rect.top;
|
|
xi_scroll_rect( lmp->win, &r, 0, row_height );
|
|
}
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
int idx,
|
|
row_height,
|
|
cnt;
|
|
XinRect r;
|
|
BOOLEAN need_first = !lmp->nbr_realized_rows;
|
|
|
|
make_rec_available( lmp, REC_AT_TOP, TRUE, FALSE );
|
|
idx = 0;
|
|
if ( do_lm_cb_get( ( LM ) lmp, need_first ? LM_CB_GET_FIRST : LM_CB_GET_PREV,
|
|
&lmp->recs[idx + 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height ) )
|
|
{
|
|
lm_do_rec_event( lmp, 0, XIE_REC_FREE );
|
|
for ( cnt = 1; cnt < lmp->nbr_realized_rows; ++cnt )
|
|
lm_row_copy( lmp, cnt, cnt - 1 );
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
|
|
if ( row_height )
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = lm_calculate_row_height( lmp, idx );
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
lm_invalidate_rows_internal( ( LM ) lmp, idx, idx, FALSE, -1, TRUE );
|
|
lm_get_scroll_rct( lmp, &r );
|
|
row_height = lm_calculate_row_height( lmp, idx );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
xi_scroll_rect( lmp->win, &r, 0, row_height );
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete_row
|
|
lm: current lm
|
|
row: row to delete
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_delete_row( LM lm, int row )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( lmp->get_all_records )
|
|
XinError( 20920, XinSeverityFatal, 0L );
|
|
if ( xi_move_focus( lmp->itf_obj ) )
|
|
{
|
|
int pix_height,
|
|
i;
|
|
int recs_read;
|
|
XinRect r,
|
|
row_rct;
|
|
|
|
pix_height = lmp->pix_heights[row];
|
|
lm_get_rect( lm, LM_ROW, row, &row_rct );
|
|
lm_do_rec_event( lmp, row, XIE_REC_FREE );
|
|
for ( i = row + 1; i < lmp->nbr_realized_rows; i++ )
|
|
lm_row_copy( lmp, i, i - 1 );
|
|
lmp->recs[--lmp->nbr_realized_rows] = 0;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
recs_read = lm_make_rrr_room_pix( lmp, pix_height, FALSE );
|
|
pix_height = max( pix_height, 0 );
|
|
lm_get_scroll_rct( lmp, &r );
|
|
r.top = max( r.top, row_rct.top );
|
|
if ( recs_read )
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
else
|
|
xi_scroll_rect( lmp->win, &r, 0, -pix_height );
|
|
XinWindowPaintForce( lmp->win );
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_row_height
|
|
lm: current lm
|
|
row: row to set
|
|
height: height
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_row_height( LM lm, int row, int height, BOOLEAN set_height,
|
|
int old_height, BOOLEAN only_update )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
int idx = row;
|
|
int old_row_height,
|
|
delta;
|
|
XinRect r,
|
|
r2;
|
|
|
|
if ( !lmp->itf_obj->v.itf->half_baked )
|
|
XinWindowPaintForce( lmp->win );
|
|
if ( only_update )
|
|
old_row_height = old_height;
|
|
else
|
|
{
|
|
old_row_height = lmp->pix_heights[idx];
|
|
lmp->pix_heights[idx] = height;
|
|
lmp->set_heights[idx] = set_height;
|
|
}
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
|
|
/* Adjust row information */
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
if ( height < old_row_height )
|
|
lm_make_rrr_room_pix( lmp, 0, FALSE );
|
|
else
|
|
{ /* Free rows at bottom */
|
|
int i,
|
|
cnt;
|
|
int nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
|
|
for ( i = lmp->nbr_realized_rows - nbr_to_free,
|
|
cnt = 0; cnt < nbr_to_free; i++, cnt++ )
|
|
lm_do_rec_event( lmp, i, XIE_REC_FREE );
|
|
if ( nbr_to_free > 0 )
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
}
|
|
lm_get_scroll_rct( lmp, &r );
|
|
if ( row < lmp->nbr_realized_rows - 1 )
|
|
{
|
|
r.top = lmp->pix_offsets[idx + 1] + lmp->rrr_offset + lmp->mlr.top;
|
|
delta = height - old_row_height;
|
|
if ( r.top < r.bottom )
|
|
xi_scroll_rect( lmp->win, &r, 0, delta );
|
|
}
|
|
lm_get_rect( lm, LM_ROW, row, &r );
|
|
if ( row == lmp->nbr_realized_rows - 1 )
|
|
{
|
|
r2 = r;
|
|
r2.top = r2.bottom;
|
|
r2.bottom = lmp->mlr.bottom;
|
|
if ( r2.top < r2.bottom )
|
|
xi_invalidate_rect( lmp->win, &r2 );
|
|
}
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_list_size
|
|
lm: current lm
|
|
height: new height
|
|
width: new width
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_list_size( LM lm, int height, int width )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
XinRect vert_scrollbar_rect;
|
|
XinRect horz_scrollbar_rect;
|
|
XinRect ir,
|
|
old_rct;
|
|
int old_height;
|
|
int col_offset;
|
|
int max_row_height;
|
|
int row_height;
|
|
int heading_height;
|
|
int i;
|
|
int row,
|
|
col;
|
|
XI_LIST_DATA *list_data;
|
|
int nbr_to_free,
|
|
cnt;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
xi_get_rect( lmp->list_obj, &old_rct );
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
xi_get_hsb_rect( lmp->list_obj, &horz_scrollbar_rect );
|
|
xi_get_sb_rect( lmp->list_obj, &vert_scrollbar_rect );
|
|
|
|
/* calculate minumum height */
|
|
if ( !list_data->one_row_list )
|
|
{
|
|
{
|
|
int leading;
|
|
int ascent;
|
|
int descent;
|
|
int char_width;
|
|
int font_height;
|
|
|
|
xi_get_font_metrics_font( lmp->font, &leading, &ascent, &descent,
|
|
&char_width );
|
|
font_height = leading + ascent + descent;
|
|
max_row_height = lmp->max_lines_in_cell * font_height + RULE_Y_OFFSET_TOP
|
|
+ RULE_Y_OFFSET_BOTTOM + RULE_WIDTH_H;
|
|
}
|
|
for ( i = 0; i < lmp->nbr_realized_rows; ++i )
|
|
{
|
|
row_height = lmp->pix_heights[i];
|
|
max_row_height = max( row_height, max_row_height );
|
|
}
|
|
heading_height = ( lmp->pix_row1_top - lmp->rct.top ) + BORDER_WIDTH;
|
|
i = max_row_height + heading_height + ( horz_scrollbar_rect.bottom
|
|
- horz_scrollbar_rect.top );
|
|
height = max( height, i );
|
|
|
|
/* calculate new list metrics */
|
|
lmp->pixel_height = height;
|
|
lmp->rct.bottom = lmp->rct.top + height
|
|
- ( ( list_data->hsb_win ) ? ( horz_scrollbar_rect.bottom
|
|
- horz_scrollbar_rect.top - 1 )
|
|
: 0 );
|
|
#if XIWS == XIWS_WM
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
#else
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
#endif
|
|
old_height = lmp->mlr_height;
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
/* fill in with more records */
|
|
if ( old_height < lmp->mlr_height )
|
|
lm_make_rrr_room_pix( lmp, lmp->mlr_height - old_height, FALSE );
|
|
}
|
|
|
|
calculate_visibles( lmp );
|
|
}
|
|
|
|
if ( width && lmp->pixel_width )
|
|
{
|
|
int i,
|
|
min_width,
|
|
max_col_width;
|
|
|
|
max_col_width = 0;
|
|
for ( i = lmp->fixed_columns; i < lmp->nbr_columns; ++i )
|
|
max_col_width = max( lmp->lm_column_data[i]->pix_width, max_col_width );
|
|
max_col_width += BORDER_WIDTH;
|
|
min_width = ( lmp->vir_left - lmp->rct.left ) + max_col_width
|
|
+ ( vert_scrollbar_rect.right - vert_scrollbar_rect.left )
|
|
+ BORDER_WIDTH + 2 * col_offset;
|
|
if ( list_data->sb_win )
|
|
min_width += ( vert_scrollbar_rect.right
|
|
- vert_scrollbar_rect.left );
|
|
width = max( min_width, width );
|
|
|
|
lmp->pixel_width = width - ( 2 * BORDER_WIDTH );
|
|
if ( list_data->sb_win )
|
|
lmp->pixel_width -= ( vert_scrollbar_rect.right
|
|
- vert_scrollbar_rect.left - 1 );
|
|
lmp->vir_right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
}
|
|
|
|
/* move scroll bars */
|
|
list_data->have_sb_rct = FALSE;
|
|
list_data->have_hsb_rct = FALSE;
|
|
xi_move_list_scroll_bar( lmp->list_obj );
|
|
xi_move_list_hscroll_bar( lmp->list_obj );
|
|
lm_set_hscroll_range( lm );
|
|
lm_set_hscroll_bar( lm );
|
|
|
|
ir = lmp->rct;
|
|
xi_get_hsb_rect( lmp->list_obj, &horz_scrollbar_rect );
|
|
ir.bottom = horz_scrollbar_rect.bottom + BORDER_WIDTH;
|
|
xi_get_sb_rect( lmp->list_obj, &vert_scrollbar_rect );
|
|
ir.right = vert_scrollbar_rect.right + BORDER_WIDTH;
|
|
ir.right = max( ir.right, old_rct.right );
|
|
ir.bottom = max( ir.bottom, old_rct.bottom );
|
|
xi_invalidate_rect( lmp->win, &ir );
|
|
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
|
|
if ( width && lmp->pixel_width )
|
|
{
|
|
/* calculate visible columns */
|
|
i = lm_get_left_most_far_right_col( lmp, lmp->nbr_columns );
|
|
if ( i < lmp->first_vis )
|
|
{
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_hscroll( lm, lmp->first_vis - i, 0 );
|
|
}
|
|
else
|
|
{
|
|
lm_calc_last_vis( lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
}
|
|
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
for ( i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
|
|
i++, cnt++ )
|
|
lm_do_rec_event( lmp, i, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_visibles( lmp );
|
|
}
|
|
|
|
for ( col = 0; col < lmp->nbr_columns; ++col )
|
|
{
|
|
for ( row = 0; row < lmp->nbr_realized_rows; ++row )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( cell_data->xi_text )
|
|
{
|
|
XinRect r;
|
|
|
|
r = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
r.right = r.left + lmp->pixel_width;
|
|
xi_text_clip_set( cell_data->xi_text, &r );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
calc_lmp_rct_right( LM_DATA * lmp )
|
|
{
|
|
/* TODO for XINCH mode, need to duplicate algorythm in lm_create */
|
|
/* single-column lists do not have a vertical rule seperating columns */
|
|
if ( lmp->nbr_columns == 0 )
|
|
lmp->rct.right = lmp->rct.left + 2 * BORDER_WIDTH;
|
|
else
|
|
{
|
|
LM_COLUMN_DATA *cell_data = lmp->lm_column_data[lmp->nbr_columns - 1];
|
|
|
|
lmp->rct.right = lmp->rct.left + cell_data->x_pix_pos + cell_data->pix_width + 2 * BORDER_WIDTH +
|
|
( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
}
|
|
lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
|
|
}
|
|
|
|
void
|
|
lm_recalc_metrics( LM lm )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
int leading,
|
|
ascent,
|
|
descent,
|
|
font_height,
|
|
mch,
|
|
i;
|
|
XinWindow win;
|
|
LM_COLUMN_DATA **cell_data;
|
|
int old_char_width;
|
|
XI_LIST_DATA *list_data;
|
|
XinPoint pnt;
|
|
XinRect rct;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
pnt = list_data->xi_pnt;
|
|
xi_fu_to_pu( lmp->itf_obj, &pnt, 1 );
|
|
lmp->rct.top = pnt.v;
|
|
lmp->rct.left = pnt.h;
|
|
|
|
if ( !lmp->resize_with_window )
|
|
{
|
|
lmp->pixel_width = list_data->width *
|
|
xi_get_fu_width( lmp->itf_obj ) / XI_FU_MULTIPLE;
|
|
}
|
|
|
|
if ( !lmp->is_list_font )
|
|
lmp->font = lmp->itf_obj->v.itf->font;
|
|
if (!lmp->font)
|
|
lmp->font = xi_get_system_font();
|
|
win = lmp->win;
|
|
XinWindowFontMap( win, lmp->font );
|
|
XinFontMetricsGet( lmp->font, &leading, &ascent, &descent );
|
|
lmp->leading = leading;
|
|
lmp->ascent = ascent;
|
|
lmp->descent = descent;
|
|
font_height = lmp->ascent + lmp->leading + lmp->descent;
|
|
lmp->pix_cell_height = font_height + ( RULE_Y_OFFSET_TOP +
|
|
RULE_Y_OFFSET_BOTTOM );
|
|
#if XIWS == XIWS_WM
|
|
mch = 8;
|
|
#else
|
|
mch = lmp->min_cell_height;
|
|
#endif
|
|
lmp->pix_cell_height = max( lmp->pix_cell_height, mch );
|
|
lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
|
|
lmp->pix_top = lmp->rct.top;
|
|
lmp->pix_hdr_bottom = lmp->rct.top + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH +
|
|
RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP + 1;
|
|
lmp->pix_hdr_bottom = max( lmp->pix_hdr_bottom,
|
|
( lmp->rct.top + lmp->min_heading_height + 2 * BORDER_WIDTH ) );
|
|
if ( lmp->no_heading )
|
|
lmp->pix_row1_top = lmp->rct.top + BORDER_WIDTH;
|
|
else
|
|
lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
|
|
|
|
old_char_width = lmp->pix_char_width;
|
|
lmp->pix_char_width = xi_get_fu_width( lmp->itf_obj );
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
|
|
for ( i = 0, cell_data = lmp->lm_column_data; i < lmp->nbr_columns; ++i, ++cell_data )
|
|
( *cell_data )->pix_width = ( *cell_data )->pix_width * lmp->pix_char_width /
|
|
old_char_width;
|
|
|
|
for ( i = 0; i < lmp->nbr_columns; ++i )
|
|
calc_x_pix_pos( lm, lmp->lm_column_data[i], i );
|
|
|
|
calc_lmp_rct_right( lmp );
|
|
|
|
if ( !lmp->resize_with_window )
|
|
{
|
|
#if XIWS != XIWS_WM
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
|
|
( BORDER_WIDTH - RULE_WIDTH_H );
|
|
#else
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
|
|
+ BORDER_WIDTH;
|
|
#endif
|
|
}
|
|
|
|
if ( lmp->fixed_columns >= lmp->nbr_columns )
|
|
lmp->delta_x = 0;
|
|
else
|
|
lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
|
|
lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
|
|
|
|
lmp->mlr.top = lmp->pix_row1_top;
|
|
#if XIWS != XIWS_WM
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
#else
|
|
if ( lmp->pixel_width )
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
else
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
#endif
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
|
|
if ( lmp->rrr_bottom < lmp->mlr_height )
|
|
lm_make_rrr_room_pix( lmp, lmp->mlr_height - lmp->rrr_bottom, FALSE );
|
|
|
|
{
|
|
XinRect vert_scrollbar_rect;
|
|
xi_get_sb_rect( lmp->list_obj, &vert_scrollbar_rect );
|
|
if ( list_data->sb_win )
|
|
lmp->pixel_width -= ( vert_scrollbar_rect.right
|
|
- vert_scrollbar_rect.left - 1 );
|
|
lmp->pixel_width = max( lmp->pixel_width, 0 );
|
|
lmp->vir_right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
}
|
|
|
|
list_data->have_sb_rct = FALSE;
|
|
list_data->have_hsb_rct = FALSE;
|
|
|
|
xi_get_sb_rect( lmp->list_obj, &rct );
|
|
xi_offset_rect( &rct, -lmp->list_obj->itf->v.itf->delta_x,
|
|
-lmp->list_obj->itf->v.itf->delta_y );
|
|
if ( list_data->sb_win )
|
|
XinWindowRectSet( list_data->sb_win, &rct );
|
|
|
|
xi_get_hsb_rect( lmp->list_obj, &rct );
|
|
xi_offset_rect( &rct, -lmp->list_obj->itf->v.itf->delta_x,
|
|
-lmp->list_obj->itf->v.itf->delta_y );
|
|
if ( list_data->hsb_win )
|
|
XinWindowRectSet( list_data->hsb_win, &rct );
|
|
|
|
lm_calc_last_vis( lmp );
|
|
}
|
|
|
|
void
|
|
lm_text_scrolling( XI_OBJ * xi_obj )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) xi_obj->v.list->lm;
|
|
|
|
lmp->text_scrolling = TRUE;
|
|
}
|
|
|
|
void
|
|
lm_set_hscroll_range( LM lm )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
int hscroll_width,
|
|
fixed_width,
|
|
cnt;
|
|
XinRect mlr;
|
|
XI_LIST_DATA *listdata;
|
|
|
|
if ( lmp->list_obj->nbr_children <= 0 )
|
|
return;
|
|
|
|
listdata = lmp->list_obj->v.list;
|
|
lm_get_scroll_rct( lmp, &mlr );
|
|
if ( lmp->pixel_width )
|
|
{
|
|
int prop;
|
|
|
|
hscroll_width = 0;
|
|
fixed_width = 0;
|
|
for ( cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt )
|
|
hscroll_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing( );
|
|
for ( cnt = 0; cnt < lmp->fixed_columns; ++cnt )
|
|
fixed_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing( );
|
|
prop = mlr.right - mlr.left - fixed_width - BORDER_WIDTH;
|
|
prop = min( prop, hscroll_width );
|
|
prop = max( prop, 0 );
|
|
XinScrollBarSet( listdata->hsb_win, XinScrollBarTypeEither, 0,
|
|
hscroll_width, prop, 0 );
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_column_set_pixel_width
|
|
lm: current lm
|
|
idx: column number
|
|
width: in pixels
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_column_set_pixel_width( LM lm, int idx, int width )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
LM_COLUMN_DATA *column;
|
|
XinRect invalid_rct,
|
|
old_rct;
|
|
int i,
|
|
old_width,
|
|
new_row_height,
|
|
cnt;
|
|
|
|
old_rct = lmp->rct;
|
|
column = lmp->lm_column_data[idx];
|
|
old_width = column->pix_width;
|
|
column->width = width / lmp->pix_char_width;
|
|
column->pix_width = width;
|
|
for ( i = idx + 1; i < lmp->nbr_columns; ++i )
|
|
calc_x_pix_pos( lm, lmp->lm_column_data[i], i );
|
|
|
|
/* adjust bounding rectangle */
|
|
calc_lmp_rct_right( lmp );
|
|
if ( idx < lmp->fixed_columns )
|
|
lmp->vir_left += column->pix_width - old_width;
|
|
|
|
/* The x_pix_pos of the first visible column may have changed so recalculate
|
|
* delta_x */
|
|
if ( lmp->fixed_columns >= lmp->nbr_columns )
|
|
lmp->delta_x = 0;
|
|
else
|
|
lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
|
|
lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
|
|
|
|
invalid_rct = lmp->rct;
|
|
invalid_rct.left = column->x_pix_pos;
|
|
invalid_rct.right = max( invalid_rct.right, old_rct.right );
|
|
if ( lmp->pixel_width )
|
|
invalid_rct.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
lm_calc_last_vis( lmp );
|
|
|
|
if ( column->wrap_text )
|
|
{
|
|
int first_fully_vis = lmp->first_fully_vis;
|
|
int last_row = lmp->nbr_realized_rows - 1;
|
|
int height;
|
|
|
|
for ( cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt )
|
|
{
|
|
int old_row_height;
|
|
|
|
old_row_height = lmp->pix_heights[cnt];
|
|
new_row_height = lm_calculate_row_height( lmp, cnt );
|
|
lmp->pix_heights[cnt] = new_row_height;
|
|
if ( old_row_height != new_row_height )
|
|
invalid_rct.left = lmp->rct.left;
|
|
}
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
height = lmp->pix_offsets[last_row] + lmp->pix_heights[last_row] -
|
|
lmp->pix_offsets[first_fully_vis];
|
|
if ( height < lmp->mlr_height )
|
|
lm_make_rrr_room_pix( lmp, lmp->mlr_height - height, FALSE );
|
|
if ( !lmp->get_all_records )
|
|
{
|
|
int nbr_to_free;
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - ( lmp->last_fully_vis + 2 );
|
|
for ( i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free;
|
|
i++, cnt++ )
|
|
lm_do_rec_event( lmp, i, XIE_REC_FREE );
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_visibles( lmp );
|
|
}
|
|
}
|
|
lm_invalidate_rect2( lmp, &invalid_rct, TRUE );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_column_width
|
|
lm: current lm
|
|
idx: column number
|
|
width: in characters
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_column_width( LM lm, int idx, int width )
|
|
{
|
|
lm_column_set_pixel_width( lm, idx,
|
|
width * ( ( LM_DATA * ) lm )->pix_char_width );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_visible_columns
|
|
lm: current lm
|
|
first_vis:
|
|
last_vis:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_visible_columns( LM lm, int *first_vis, int *last_vis )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
|
|
*first_vis = lmp->first_vis;
|
|
*last_vis = lmp->last_vis;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_info
|
|
lm: current lm
|
|
nbr_recs: number of records
|
|
returns: array of record handles
|
|
-------------------------------------------------------------------------*/
|
|
long *
|
|
lm_get_list_info( LM lm, int *nbr_recs )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
|
|
*nbr_recs = lmp->nbr_realized_rows;
|
|
return &lmp->recs[0];
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_cell_request
|
|
lm: current lm
|
|
lm_part: may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL ??
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_cell_request( LM lm, LM_PART lm_part, int idx1, int idx2 )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
BOOLEAN redraw;
|
|
|
|
redraw = ( BOOLEAN ) ( lmp->attrib & ( LM_ATR_VISIBLE ) );
|
|
lm_focus_cell_invis_make( lmp );
|
|
switch ( lm_part )
|
|
{
|
|
case LM_LIST:
|
|
lm_invalidate_rows_internal( lm, 0, lmp->nbr_realized_rows - 1, redraw, -1,
|
|
FALSE );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
case LM_ROW:
|
|
lm_invalidate_rows_internal( lm, idx1, idx1, redraw, -1, FALSE );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
case LM_COLUMN:
|
|
lm_invalidate_rows_internal( lm, 0, lmp->nbr_realized_rows - 1, redraw, idx1,
|
|
FALSE );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
case LM_CELL:
|
|
lm_invalidate_rows_internal( lm, idx1, idx1, redraw, idx2, FALSE );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
}
|
|
XinError( 20918, XinSeverityFatal, 0L );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_visible_rows
|
|
------------------------------------------------------------------------- */
|
|
int
|
|
lm_get_visible_rows( LM lm, int *first_vis, int *last_vis )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
|
|
if ( first_vis )
|
|
*first_vis = lmp->first_fully_vis;
|
|
if ( last_vis )
|
|
*last_vis = lmp->last_fully_vis;
|
|
if ( !lmp->nbr_realized_rows )
|
|
return 0;
|
|
else
|
|
return lmp->last_fully_vis - lmp->first_fully_vis + 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_obj
|
|
lm: current lm
|
|
returns: XI_OBJ * for list
|
|
-------------------------------------------------------------------------*/
|
|
XI_OBJ *
|
|
lm_get_list_obj( LM lm )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
return ( lmp->list_obj );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_buf_size_internal
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
size: the new buffer size
|
|
redraw: if TRUE, then redraw the cell
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_set_buf_size_internal( LM lm, LM_PART part, int idx, int size, BOOLEAN redraw )
|
|
{
|
|
int i;
|
|
LM_COLUMN_DATA *lmcd;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( part != LM_COLUMN )
|
|
XinError( 20917, XinSeverityFatal, 0L );
|
|
lmcd = lmp->lm_column_data[idx];
|
|
lmcd->text_size = size;
|
|
|
|
if ( ! lmcd->var_len_text )
|
|
{
|
|
for ( i = 0; i < lmp->nbr_realized_rows; i++ )
|
|
{
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[i][idx];
|
|
|
|
xi_text_buffer_size_set( cell_data->xi_text, size );
|
|
if ( redraw && i < lmp->nbr_realized_rows )
|
|
redraw_cell( lm, i, idx, FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_buf_size
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
size: the new buffer size
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_buf_size( LM lm, LM_PART part, int idx, int size )
|
|
{
|
|
lm_set_buf_size_internal( lm, part, idx, size, TRUE );
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* adjust_focus_for_column_delete */
|
|
/* if the focus is on a column after the deleted column, adjust the focus */
|
|
/* objects. */
|
|
/* if the focus is on the deleted column, move the focus to the next */
|
|
/* column, previous column, or interface. */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static BOOLEAN
|
|
adjust_focus_for_column_delete( LM_DATA * lmp, int column_nbr,
|
|
BOOLEAN adjust_focus_column )
|
|
{
|
|
XI_OBJ *focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
if ( focus_obj == NULL || focus_obj->parent != lmp->list_obj
|
|
|| focus_obj->type != XIT_CELL )
|
|
return TRUE;
|
|
|
|
if ( focus_obj->v.cell.column == column_nbr )
|
|
{
|
|
XI_OBJ new_cell;
|
|
int row, col;
|
|
BOOLEAN temp;
|
|
|
|
temp = TRUE;
|
|
calculate_next_cell( lmp, &row, &col, &temp, '\t', &temp, &temp );
|
|
if ( row != focus_obj->v.cell.row )
|
|
{
|
|
temp = TRUE;
|
|
calculate_next_cell( lmp, &row, &col, &temp, XI_KEY_BTAB, &temp, &temp );
|
|
}
|
|
if ( row == focus_obj->v.cell.row )
|
|
{
|
|
XI_MAKE_CELL( &new_cell, lmp->list_obj, row, col );
|
|
if ( !xi_move_focus( &new_cell ) )
|
|
return FALSE;
|
|
if ( adjust_focus_column &&
|
|
( int ) focus_obj->v.cell.column > ( int ) column_nbr )
|
|
{
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
focus_obj->v.cell.column--;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return xi_move_focus( lmp->itf_obj );
|
|
}
|
|
if ( adjust_focus_column &&
|
|
( int ) focus_obj->v.cell.column > ( int ) column_nbr )
|
|
focus_obj->v.cell.column--;
|
|
return TRUE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete_column
|
|
lm: current lm
|
|
column_nbr: column to delete
|
|
adjust_hscrolling: if TRUE, then make more horizontal columns visible
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_delete_column( LM lm, int column_nbr, BOOLEAN adjust_hscrolling )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
LM_COLUMN_DATA *lmcd;
|
|
XinRect invalid_rct,
|
|
old_rct;
|
|
int i,
|
|
old_width,
|
|
old_left,
|
|
col_spacing;
|
|
int old_x_pix_pos;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if ( !adjust_focus_for_column_delete( lmp, column_nbr, TRUE ) )
|
|
return;
|
|
col_spacing = lm_get_col_spacing( );
|
|
if ( column_nbr >= lmp->nbr_columns )
|
|
XinError( 20915, XinSeverityFatal, 0L );
|
|
old_rct = lmp->rct;
|
|
lmcd = lmp->lm_column_data[column_nbr];
|
|
if ( lmcd->font )
|
|
XinFontDestroy( lmcd->font );
|
|
xi_bitmap_destroy( lmcd->bitmap );
|
|
old_left = lmcd->x_pix_pos - lmp->delta_x;
|
|
old_x_pix_pos = lmcd->x_pix_pos;
|
|
old_width = lmcd->pix_width;
|
|
xi_tree_free( lmp->lm_column_data[column_nbr] );
|
|
|
|
/* cell_data_destruct */
|
|
for ( i = 0; i < lmp->nbr_realized_rows; ++i )
|
|
{
|
|
cell_data = &( lmp->cell_data[i][column_nbr] );
|
|
if ( cell_data->font )
|
|
XinFontDestroy( cell_data->font );
|
|
xi_bitmap_destroy( cell_data->bitmap );
|
|
xi_bitmap_destroy( cell_data->button_bitmap );
|
|
if ( cell_data->xi_text )
|
|
xi_text_destruct( cell_data->xi_text );
|
|
}
|
|
|
|
for ( i = 0; i < lmp->realized_rows_array_len; ++i )
|
|
{
|
|
int j;
|
|
|
|
for ( j = column_nbr; j < lmp->nbr_columns - 1; ++j )
|
|
lmp->cell_data[i][j] = lmp->cell_data[i][j + 1];
|
|
lmp->cell_data[i] = ( LM_CELL_DATA * ) xi_tree_realloc( lmp->cell_data[i],
|
|
( lmp->nbr_columns - 1 ) * sizeof( LM_CELL_DATA ) );
|
|
}
|
|
|
|
for ( i = column_nbr; i < lmp->nbr_columns - 1; ++i )
|
|
lmp->lm_column_data[i] = lmp->lm_column_data[i + 1];
|
|
--lmp->nbr_columns;
|
|
{ /* Check focus cell, to see if it is now out of range */
|
|
XI_OBJ* focus_cell;
|
|
|
|
focus_cell = lmp->list_obj->v.list->focus_cell;
|
|
if ( (int)focus_cell->v.cell.column >= lmp->nbr_columns )
|
|
focus_cell->v.cell.column = lmp->nbr_columns - 1;
|
|
}
|
|
|
|
for ( i = column_nbr; i < lmp->nbr_columns; ++i )
|
|
calc_x_pix_pos( lm, lmp->lm_column_data[i], i );
|
|
|
|
calc_lmp_rct_right( lmp );
|
|
|
|
/* adjust left border of horizontal virtual space */
|
|
if ( column_nbr < lmp->fixed_columns )
|
|
lmp->vir_left -= ( old_width + col_spacing );
|
|
|
|
|
|
/* if the column is invisible */
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
if ( column_nbr >= lmp->fixed_columns && old_x_pix_pos < lmp->delta_x )
|
|
{
|
|
lmp->delta_x -= ( old_width + lm_get_col_spacing( ) );
|
|
--lmp->first_vis;
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
else
|
|
{
|
|
if ( column_nbr < lmp->fixed_columns )
|
|
{
|
|
--lmp->first_vis;
|
|
--lmp->fixed_columns;
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
|
|
invalid_rct = lmp->rct;
|
|
invalid_rct.left = old_left;
|
|
invalid_rct.right = max( invalid_rct.right, old_rct.right );
|
|
if ( lmp->pixel_width )
|
|
invalid_rct.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
|
|
/* if we add the following two lines in, it prevents flashing of the top
|
|
* and bottom borders when moving columns, however, the top and bottom
|
|
* borders need to get invalidated invalid_rct.top += BORDER_WIDTH;
|
|
* invalid_rct.bottom -= BORDER_WIDTH; */
|
|
|
|
lm_invalidate_rect2( lmp, &invalid_rct, FALSE );
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
|
|
i = lm_get_left_most_far_right_col( lmp, lmp->nbr_columns );
|
|
/* All columns have been deleted */
|
|
if ( i == 0 )
|
|
{
|
|
lmp->delta_x = 0;
|
|
lmp->last_vis = lmp->first_vis = i;
|
|
lm_calc_last_vis( lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
return;
|
|
}
|
|
if ( lmp->first_vis >= lmp->nbr_columns )
|
|
{
|
|
XinRect r;
|
|
|
|
XinWindowPaintForce( lmp->win );
|
|
if ( i < lmp->nbr_columns )
|
|
lmp->delta_x = lmp->lm_column_data[i]->x_pix_pos - lmp->vir_left;
|
|
else
|
|
lmp->delta_x = 0;
|
|
xi_set_update_obj( lmp->list_obj );
|
|
lmp->last_vis = lmp->first_vis = i;
|
|
lm_calc_last_vis( lmp );
|
|
r.left = lmp->vir_left;
|
|
r.right = lmp->vir_right;
|
|
#if XIWS != XIWS_WM
|
|
r.top = lmp->rct.top + BORDER_WIDTH;
|
|
r.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
#else
|
|
r.top = lmp->rct.top;
|
|
r.bottom = lmp->rct.bottom;
|
|
#endif
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
else
|
|
{
|
|
if ( i < lmp->first_vis && adjust_hscrolling )
|
|
{
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_hscroll( lm, i - lmp->first_vis, 0 );
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
else
|
|
{
|
|
lm_calc_last_vis( lmp );
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
TODO this function will change. pix_row_spacing will no longer be used.
|
|
instead, min_row_height, and absolute_height will be used.
|
|
*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
lm_get_vertical_metrics
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_vertical_metrics( XI_OBJ_DEF * obj_def, int *first_row_y,
|
|
int *row_spacing, int *client_height,
|
|
int *title_height )
|
|
{
|
|
XI_LIST_DEF *list_def;
|
|
XI_OBJ_DEF *itf_def;
|
|
int leading,
|
|
ascent,
|
|
descent,
|
|
char_width,
|
|
font_height,
|
|
pix_cell_height,
|
|
pix_hdr_bottom,
|
|
min_cell_height;
|
|
XinPoint p;
|
|
XinFont *fontp = NULL;
|
|
|
|
list_def = obj_def->v.list;
|
|
|
|
#if XIWS != XIWS_WM
|
|
itf_def = obj_def->parent;
|
|
if ( itf_def && itf_def->v.itf->font )
|
|
fontp = itf_def->v.itf->font;
|
|
if ( list_def->font )
|
|
xi_get_font_metrics_font( list_def->font, &leading, &ascent,
|
|
&descent, &char_width );
|
|
else if ( fontp )
|
|
xi_get_font_metrics_font( fontp, &leading, &ascent, &descent,
|
|
&char_width );
|
|
else
|
|
xi_get_font_metrics_font( xi_get_system_font( ), &leading,
|
|
&ascent, &descent, &char_width );
|
|
#else
|
|
leading = 0;
|
|
ascent = 8;
|
|
descent = 0;
|
|
#endif
|
|
font_height = ascent + leading + descent;
|
|
#if XIWS == XIWS_WM
|
|
min_cell_height = 8;
|
|
pix_cell_height = font_height;
|
|
#else
|
|
min_cell_height = list_def->min_cell_height;
|
|
pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
|
|
#endif
|
|
pix_cell_height = max( pix_cell_height, min_cell_height );
|
|
#if XIWS == XIWS_WM
|
|
*row_spacing = pix_cell_height;
|
|
#else
|
|
*row_spacing = pix_cell_height + RULE_WIDTH_H;
|
|
#endif
|
|
itf_def = obj_def->parent;
|
|
if ( itf_def && itf_def->v.itf->font )
|
|
fontp = itf_def->v.itf->font;
|
|
if ( xi_def_get_xil_pref( itf_def ) )
|
|
{
|
|
p = list_def->xi_pnt;
|
|
}
|
|
else
|
|
{
|
|
p = list_def->pixel_origin;
|
|
if ( !p.v && !p.h )
|
|
{
|
|
p = list_def->xi_pnt;
|
|
if ( list_def->font )
|
|
xi_fu_to_pu_font( list_def->font, &p, 1 );
|
|
else if ( fontp )
|
|
xi_fu_to_pu_font( fontp, &p, 1 );
|
|
else
|
|
xi_fu_to_pu_font( xi_get_system_font( ), &p, 1 );
|
|
}
|
|
}
|
|
#if XIWS != XIWS_WM
|
|
pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH
|
|
+ RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP + 1;
|
|
pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height
|
|
+ BORDER_WIDTH );
|
|
#else
|
|
pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH;
|
|
pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height );
|
|
#endif
|
|
if ( list_def->no_heading )
|
|
{
|
|
int first_row_y_pos = p.v + BORDER_WIDTH;
|
|
|
|
*first_row_y = first_row_y_pos;
|
|
}
|
|
else
|
|
{
|
|
*first_row_y = pix_hdr_bottom + BORDER_WIDTH;
|
|
}
|
|
if ( xi_def_get_xil_pref( itf_def ) )
|
|
{
|
|
*client_height = list_def->height;
|
|
}
|
|
else
|
|
{
|
|
if ( list_def->pixel_height )
|
|
*client_height = list_def->pixel_height;
|
|
else
|
|
{
|
|
int height;
|
|
|
|
if ( list_def->font )
|
|
height = xi_get_fu_height_font( list_def->font );
|
|
else if ( fontp )
|
|
height = xi_get_fu_height_font( fontp );
|
|
else
|
|
height = xi_get_fu_height_font( xi_get_system_font( ) );
|
|
*client_height = list_def->height * height / XI_FU_MULTIPLE;
|
|
}
|
|
}
|
|
*title_height = *first_row_y - p.v;
|
|
*client_height -= *title_height + BORDER_WIDTH;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_metrics
|
|
lm_def: definition of a list
|
|
hborder: to be filled in with the horizontal border width
|
|
column_div: to be filled in with the column spacing in pixels
|
|
list_bottom: bottom of the list, in pixels
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_metrics( XI_OBJ_DEF * obj_def, int *hborder, int *column_div,
|
|
int *list_bottom )
|
|
{
|
|
if ( hborder != NULL )
|
|
*hborder = BORDER_WIDTH;
|
|
if ( column_div != NULL )
|
|
*column_div = lm_get_col_spacing( );
|
|
if ( obj_def->v.list )
|
|
{
|
|
int pix_row_spacing,
|
|
nbr_rows,
|
|
height,
|
|
pix_row1_top,
|
|
title_height;
|
|
|
|
lm_get_vertical_metrics( obj_def, &pix_row1_top, &pix_row_spacing,
|
|
&height, &title_height );
|
|
if ( obj_def->v.list->one_row_list )
|
|
nbr_rows = 1;
|
|
else
|
|
nbr_rows = height / pix_row_spacing;
|
|
#if XIWS == XIWS_WM
|
|
*list_bottom = pix_row1_top + nbr_rows * pix_row_spacing + BORDER_WIDTH;
|
|
#else
|
|
*list_bottom = pix_row1_top + nbr_rows * pix_row_spacing
|
|
+ ( BORDER_WIDTH - RULE_WIDTH_H );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_hscroll_bar
|
|
lm: current lm
|
|
notes: Calculate the percentage for the horizontal scroll bar, and set the
|
|
thumb position on the horizontal scroll bar.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_hscroll_bar( LM lm )
|
|
{
|
|
XI_OBJ *list_obj;
|
|
int p;
|
|
LM_DATA *lmp;
|
|
int rng1,
|
|
rng2;
|
|
int prop;
|
|
|
|
lmp = ( LM_DATA * ) lm;
|
|
list_obj = lmp->list_obj;
|
|
if ( list_obj->v.list->hsb_win )
|
|
{
|
|
XinScrollBarRangeGet( list_obj->v.list->hsb_win, XinScrollBarTypeEither,
|
|
&rng1, &rng2 );
|
|
prop = XinScrollBarProportionGet( list_obj->v.list->hsb_win, XinScrollBarTypeEither );
|
|
p = lmp->delta_x;
|
|
if ( p > rng2 - prop )
|
|
p = rng2 - prop;
|
|
XinScrollBarPositionSet( list_obj->v.list->hsb_win, XinScrollBarTypeEither,
|
|
p );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_create_column
|
|
lcdef: column definition
|
|
not_creating_list: if TRUE, do all of the cell requests for the column
|
|
in_hscrolling: if TRUE, and if on border between fixed and scrolling columns
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_create_column( LM lm, LM_COLUMN_DEF * lcdef, BOOLEAN not_creating_list,
|
|
BOOLEAN in_hscrolling )
|
|
{
|
|
LM_COLUMN_DATA *lcdata;
|
|
LM_COLUMN_DATA **column_data;
|
|
LM_DATA *lmp = LMP( lm );
|
|
XinRect rct_to_invalidate;
|
|
int i;
|
|
int position,
|
|
col_spacing;
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN made_invis = FALSE;
|
|
|
|
col_spacing = lm_get_col_spacing( );
|
|
position = min( lcdef->position, lmp->nbr_columns );
|
|
if ( lm_focus_list_has( lmp ) )
|
|
{
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if ( focus_column >= position )
|
|
++focus_column;
|
|
lm_focus_cell_set( lmp, focus_row, focus_column, v_scrolled );
|
|
if ( lm_focus_state_get( lmp ) != LM_FOCUS_VISIBLE )
|
|
{
|
|
lm_focus_cell_invis_make( lmp );
|
|
made_invis = TRUE;
|
|
}
|
|
}
|
|
lcdata = ( LM_COLUMN_DATA * ) xi_tree_malloc( sizeof( LM_COLUMN_DATA ),
|
|
( char * ) lm );
|
|
lcdata->attrib = lcdef->attrib;
|
|
/*
|
|
lcdata->pix_width = lcdef->width * lmp->pix_char_width;
|
|
lcdata->width = lcdef->width;
|
|
*/
|
|
lcdata->pix_width = lcdef->pix_width;
|
|
lcdata->width = lcdef->pix_width / lmp->pix_char_width;
|
|
calc_x_pix_pos( lm, lcdata, position );
|
|
lcdata->text_size = lcdef->text_size;
|
|
lcdata->center_heading = lcdef->center_heading;
|
|
lcdata->heading_well = lcdef->heading_well;
|
|
lcdata->heading_platform = lcdef->heading_platform;
|
|
lcdata->column_well = lcdef->column_well;
|
|
lcdata->column_platform = lcdef->column_platform;
|
|
lcdata->heading_text = ( char * ) xi_tree_malloc(
|
|
strlen( lcdef->heading_text ) + 1, ( char * ) lm );
|
|
strcpy( lcdata->heading_text, lcdef->heading_text );
|
|
if ( lcdef->font )
|
|
lcdata->font = lcdef->font;
|
|
lcdata->icon_rid = lcdef->icon_rid;
|
|
lcdata->icon_x = lcdef->icon_x;
|
|
lcdata->icon_y = lcdef->icon_y;
|
|
lcdata->bitmap = lcdef->bitmap;
|
|
lcdata->size_rows = lcdef->size_rows;
|
|
lcdata->suppress_update_heading = lcdef->suppress_update_heading;
|
|
lcdata->suppress_update_cells = lcdef->suppress_update_cells;
|
|
lcdata->vertical_align_center = lcdef->vertical_align_center;
|
|
lcdata->vertical_align_bottom = lcdef->vertical_align_bottom;
|
|
lcdata->wrap_text = lcdef->wrap_text;
|
|
lcdata->wrap_text_scrollbar = lcdef->wrap_text_scrollbar;
|
|
lcdata->cr_ok = lcdef->cr_ok;
|
|
lcdata->var_len_text = lcdef->var_len_text;
|
|
lcdata->auto_tab = lcdef->auto_tab;
|
|
lcdata->icon_mode = lcdef->icon_mode;
|
|
|
|
/* allocate new columns */
|
|
column_data = lmp->lm_column_data =
|
|
( LM_COLUMN_DATA * * ) xi_tree_realloc2(
|
|
( char * ) lmp->lm_column_data,
|
|
sizeof( LM_COLUMN_DATA * ) * ( lmp->nbr_columns + 1 ),
|
|
( char * ) lm );
|
|
|
|
/* move column pointers around in the column list */
|
|
for ( i = lmp->nbr_columns; i > position; i-- )
|
|
{
|
|
column_data[i] = column_data[i - 1];
|
|
column_data[i]->x_pix_pos += lcdata->pix_width + col_spacing;
|
|
}
|
|
column_data[position] = lcdata;
|
|
|
|
lmp->nbr_columns++;
|
|
|
|
/* create space for cell data */
|
|
/* cell_data_construct */
|
|
for ( i = 0; i < lmp->realized_rows_array_len; i++ )
|
|
{
|
|
int j;
|
|
|
|
lmp->cell_data[i] = ( LM_CELL_DATA * ) xi_tree_realloc( lmp->cell_data[i],
|
|
( lmp->nbr_columns + 1 ) * sizeof( LM_CELL_DATA ) );
|
|
for ( j = lmp->nbr_columns; j > position; j-- )
|
|
lmp->cell_data[i][j] = lmp->cell_data[i][j - 1];
|
|
memset( ( char * ) &lmp->cell_data[i][position], '\0',
|
|
sizeof( LM_CELL_DATA ) );
|
|
}
|
|
|
|
if ( not_creating_list )
|
|
{
|
|
for ( i = 0; i < lmp->nbr_realized_rows; ++i )
|
|
lm_xi_text_construct( lmp, i, position );
|
|
}
|
|
|
|
if ( ( not_creating_list ) && ( position < lmp->fixed_columns ) )
|
|
{
|
|
lmp->first_vis++;
|
|
lmp->fixed_columns++;
|
|
}
|
|
|
|
if ( not_creating_list && ( !in_hscrolling ) && position == lmp->fixed_columns )
|
|
{
|
|
lmp->first_vis++;
|
|
lmp->fixed_columns++;
|
|
}
|
|
|
|
if ( lmp->first_vis < lmp->fixed_columns &&
|
|
lmp->nbr_columns > lmp->fixed_columns )
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
|
|
/* adjust bounding rectangle */
|
|
calc_lmp_rct_right( lmp );
|
|
|
|
/* calculate the left boundary of the virtual space for the list */
|
|
lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
|
|
for ( i = 0; i < min( lmp->nbr_columns, lmp->fixed_columns ); ++i )
|
|
{
|
|
lmp->vir_left += lmp->lm_column_data[i]->pix_width;
|
|
lmp->vir_left += col_spacing;
|
|
}
|
|
if ( not_creating_list )
|
|
{
|
|
lm_invalidate_rows_internal( lm, 0, INT_MAX, FALSE, position, TRUE );
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
}
|
|
if ( position >= lmp->fixed_columns && column_data[position]->x_pix_pos < lmp->delta_x )
|
|
{
|
|
lmp->delta_x += ( column_data[position]->pix_width + lm_get_col_spacing( ) );
|
|
++lmp->first_vis;
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
else
|
|
{
|
|
/* invalidate changed rectangle */
|
|
lm_get_list_rct( lmp, &rct_to_invalidate );
|
|
|
|
/* if we add the following two lines in, it prevents flashing of the top
|
|
* and bottom borders when moving columns, however, the top and bottom
|
|
* borders need to get invalidated rct_to_invalidate.top += BORDER_WIDTH;
|
|
* rct_to_invalidate.bottom -= BORDER_WIDTH; */
|
|
|
|
rct_to_invalidate.left = lcdata->x_pix_pos;
|
|
lm_adj_h( lmp, &rct_to_invalidate.left );
|
|
if ( rct_to_invalidate.bottom > rct_to_invalidate.top &&
|
|
rct_to_invalidate.right > rct_to_invalidate.left )
|
|
lm_invalidate_rect2( lmp, &rct_to_invalidate, FALSE );
|
|
}
|
|
lm_calc_last_vis( lmp );
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
if ( not_creating_list && lmp->list_obj->v.list->hsb_win )
|
|
{
|
|
XinRect rct;
|
|
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
xi_get_hsb_rect( lmp->list_obj, &rct );
|
|
xi_offset_rect( &rct, -lmp->list_obj->itf->v.itf->delta_x,
|
|
-lmp->list_obj->itf->v.itf->delta_y );
|
|
XinWindowRectSet( lmp->list_obj->v.list->hsb_win, &rct );
|
|
}
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
{
|
|
if ( not_creating_list && made_invis )
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_column
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_COL_DELETE, LM_CB_COL_MOVE, LM_CB_COL_SIZE
|
|
col_nbr: column being deleted, moved, or re-sized
|
|
new_col_nbr: new column number on LM_CB_COL_MOVE
|
|
new_col_width: new column width on LM_CB_COL_SIZE
|
|
new_col_pixel_width: new column pixel width on LM_CB_COL_SIZE
|
|
in_fixed: if TRUE, then column is being moved to fixed portion of list
|
|
returns: TRUE if event refused
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
do_lm_cb_column( LM lm, LM_CB_TYPE cb_reason, int col_nbr,
|
|
int new_col_nbr, int new_col_width, int new_col_pixel_width,
|
|
BOOLEAN in_fixed )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
lm_cb_data.cid = LMP( lm )->cid;
|
|
lm_cb_data.win = LMP( lm )->win;
|
|
lm_cb_data.column = ( unsigned char ) col_nbr;
|
|
lm_cb_data.v.column.new_col_nbr = new_col_nbr;
|
|
lm_cb_data.v.column.in_fixed = in_fixed;
|
|
lm_cb_data.v.column.new_col_width = new_col_width;
|
|
lm_cb_data.v.column.new_col_pixel_width = new_col_pixel_width;
|
|
lm_cb_data.v.column.refused = FALSE;
|
|
( *LMP( lm )->lm_cb ) ( &lm_cb_data );
|
|
return ( lm_cb_data.v.column.refused );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_rubber_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to be filled in
|
|
x: current mouse x position
|
|
y: current mouse y position
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
get_rubber_rect( LM_DATA * lmp, XinRect * rctp, int x, int y,
|
|
BOOLEAN last_in_hscrolling )
|
|
{
|
|
XinRect rct;
|
|
|
|
if ( lmp->moving_column )
|
|
{
|
|
int col,
|
|
delta_x,
|
|
delta_y;
|
|
|
|
col = lmp->column_being_moved;
|
|
/* lm_get_cell_rect returns the exact physical rectangle of the cell - not
|
|
* shifted to the right or to the left. */
|
|
lm_get_cell_rect( &rct, ( LM ) lmp, 1, col, FALSE, TRUE );
|
|
rct.top = lmp->pix_top + BORDER_WIDTH;
|
|
rct.bottom = lmp->pix_hdr_bottom;
|
|
delta_x = x - lmp->org_x;
|
|
if ( lmp->down_in_hscrolling && !last_in_hscrolling )
|
|
delta_x += lmp->delta_x;
|
|
if ( !lmp->down_in_hscrolling && last_in_hscrolling )
|
|
delta_x -= lmp->delta_x;
|
|
delta_y = y - lmp->org_y;
|
|
rct.left += delta_x;
|
|
rct.right += delta_x;
|
|
rct.top += delta_y;
|
|
rct.bottom += delta_y;
|
|
}
|
|
else
|
|
{
|
|
lm_get_rect( ( LM ) lmp, LM_LIST, 0, &rct );
|
|
rct.top = y;
|
|
rct.bottom = rct.top + lmp->drag_row_height;
|
|
rct.right += x - rct.left;
|
|
rct.left = x;
|
|
}
|
|
*rctp = rct;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_rect
|
|
lmp: current lmp
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_rect( LM_DATA * lmp )
|
|
{
|
|
#if XIWS != XIWS_WM
|
|
XinRect rct;
|
|
XinDrawTools new_ctools;
|
|
XinWindow win = lmp->win;
|
|
|
|
if ( lmp->last_itf )
|
|
win = xi_get_window( lmp->last_itf );
|
|
|
|
XinWindowDrawToolsNormalGet( &new_ctools );
|
|
XinWindowDrawToolsSet( win, &new_ctools );
|
|
XinWindowPenSet( win, &rubber_cpen );
|
|
XinWindowBrushSet( win, &hollow_cbrush );
|
|
XinWindowDrawModeSet( win, XinDrawModeXor );
|
|
xi_set_clip( win, NULL );
|
|
get_rubber_rect( lmp, &rct, lmp->last_x, lmp->last_y, lmp->last_in_hscrolling );
|
|
xi_draw_rect( win, &rct );
|
|
#else
|
|
NOREF( lmp );
|
|
#endif
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_move_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
#define XI_AUTOSCROLL_COUNT 8 /* Number of move events before autoscroll
|
|
* occurs */
|
|
#define XI_AUTOSCROLL_FAST 50 /* Number of pixels to get to fast autoscroll */
|
|
|
|
void
|
|
lm_move_event( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
XinPoint where;
|
|
int col_offset;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
where = ep->v.mouse.where;
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
lmp->last_x = where.h;
|
|
lmp->org_x = lmp->last_x;
|
|
lmp->last_y = where.v;
|
|
lmp->org_y = lmp->last_y;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
rubber_rect( lmp );
|
|
break;
|
|
case XinEventMouseMove:
|
|
{
|
|
static int autoscroll_count = 0;
|
|
BOOLEAN scrolled = FALSE;
|
|
|
|
if ( lmp->pixel_width != 0 )
|
|
{ /* Check for autoscroll */
|
|
if ( where.h - lmp->delta_x > lmp->vir_right )
|
|
{
|
|
if ( where.h - lmp->delta_x > lmp->vir_right + XI_AUTOSCROLL_FAST
|
|
|| ++autoscroll_count >= XI_AUTOSCROLL_COUNT )
|
|
{
|
|
autoscroll_count = 0;
|
|
rubber_rect( lmp );
|
|
lm_hscroll( ( LM ) lmp, 1, 0 );
|
|
scrolled = TRUE;
|
|
}
|
|
}
|
|
else if ( where.h < lmp->vir_left )
|
|
{
|
|
if ( where.h < lmp->vir_left - XI_AUTOSCROLL_FAST
|
|
|| ++autoscroll_count >= XI_AUTOSCROLL_COUNT )
|
|
{
|
|
autoscroll_count = 0;
|
|
rubber_rect( lmp );
|
|
lm_hscroll( ( LM ) lmp, -1, 0 );
|
|
scrolled = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
autoscroll_count = 0;
|
|
if ( scrolled || where.h != lmp->last_x || where.v != lmp->last_y )
|
|
{
|
|
if ( !scrolled )
|
|
rubber_rect( lmp );
|
|
lmp->last_x = where.h;
|
|
lmp->last_y = where.v;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
rubber_rect( lmp );
|
|
}
|
|
break;
|
|
}
|
|
case XinEventMouseUp:
|
|
{
|
|
int column;
|
|
XI_OBJ *list_obj,
|
|
**members;
|
|
int nbr_members,
|
|
col_cnt,
|
|
temp1,
|
|
temp2,
|
|
dist1,
|
|
dist2,
|
|
min_dist,
|
|
position;
|
|
XinRect rct;
|
|
XinPoint where;
|
|
|
|
where = ep->v.mouse.where;
|
|
rubber_rect( lmp );
|
|
column = lmp->column_being_moved;
|
|
list_obj = lmp->list_obj;
|
|
if ( list_obj )
|
|
get_rubber_rect( lmp, &rct, where.h, where.v, lmp->in_hscrolling );
|
|
if ( lmp->drop_and_delete &&
|
|
( rct.bottom < ( lmp->pix_top - 8 ) ||
|
|
rct.top > ( lmp->pix_row1_top + 8 ) ) )
|
|
{
|
|
/* If the focus is in the column to be deleted, we will move focus as if
|
|
the tab key had been pressed before deleting the col. This is so the
|
|
Bridge doesn't try to reference a deleted column object in the
|
|
OFF_CELL event. */
|
|
XI_OBJ *old_focus;
|
|
BOOLEAN deleteable = TRUE;
|
|
BOOLEAN return_focus = FALSE;
|
|
|
|
old_focus = lmp->itf_obj->v.itf->focus_obj;
|
|
if (old_focus->type == XIT_CELL && old_focus->parent == lmp->list_obj
|
|
&& old_focus->v.cell.column == column)
|
|
{
|
|
if (adjust_focus_for_column_delete( lmp, column, FALSE ))
|
|
return_focus = TRUE;
|
|
else
|
|
deleteable = FALSE;
|
|
}
|
|
if (deleteable && do_lm_cb_column( ( long ) lmp, LM_CB_COL_DELETE, column,
|
|
0, 0, 0, FALSE ) == FALSE )
|
|
{
|
|
members = xi_get_member_list( list_obj, &nbr_members );
|
|
xi_delete( members[column] );
|
|
lm_set_hscroll_range( ( LM ) lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
} else if (return_focus)
|
|
xi_move_focus( old_focus );
|
|
}
|
|
if ( where.v > lmp->pix_top && where.v < lmp->pix_row1_top &&
|
|
where.h >= lmp->rct.left )
|
|
{
|
|
BOOLEAN in_hscrolling,
|
|
old_in_hscrolling;
|
|
|
|
/* determine where to move the column, if anywhere */
|
|
in_hscrolling = FALSE;
|
|
old_in_hscrolling = ( column >= lmp->fixed_columns );
|
|
min_dist = INT_MAX;
|
|
position = 0;
|
|
for ( col_cnt = 0; col_cnt < lmp->nbr_columns; col_cnt++ )
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
if ( col_cnt >= lmp->fixed_columns &&
|
|
col_cnt < lmp->first_vis )
|
|
continue;
|
|
column_data = lmp->lm_column_data[col_cnt];
|
|
temp1 = column_data->x_pix_pos;
|
|
temp2 = temp1 + 2 * col_offset + column_data->pix_width;
|
|
dist1 = abs( temp1 - where.h );
|
|
dist2 = abs( temp2 - where.h );
|
|
if ( dist1 < min_dist )
|
|
{
|
|
position = col_cnt;
|
|
min_dist = dist1;
|
|
}
|
|
if ( dist2 < min_dist )
|
|
{
|
|
position = col_cnt + 1;
|
|
min_dist = dist2;
|
|
}
|
|
if ( col_cnt == lmp->fixed_columns )
|
|
{
|
|
if ( where.h < column_data->x_pix_pos )
|
|
in_hscrolling = FALSE;
|
|
else
|
|
in_hscrolling = TRUE;
|
|
}
|
|
}
|
|
|
|
/* if we need to move the column, then move it */
|
|
if ( position < column || position > column + 1 ||
|
|
position == lmp->fixed_columns )
|
|
{
|
|
if ( column == position && position == lmp->fixed_columns &&
|
|
in_hscrolling && ( !old_in_hscrolling ) )
|
|
position -= 1;
|
|
else if ( position > column )
|
|
position -= 1;
|
|
|
|
/* if there is only one fixed column left, then don't move it */
|
|
if ( column != 0 || lmp->fixed_columns != 1 )
|
|
{
|
|
int widest_remaining,
|
|
col_width,
|
|
width_remaining,
|
|
new_fixed_width,
|
|
cnt;
|
|
BOOLEAN do_move = TRUE;
|
|
LM_COLUMN_DATA *column_data,
|
|
*cell_data2;
|
|
XinRect r;
|
|
|
|
if ( lmp->fixed_columns < lmp->nbr_columns )
|
|
{
|
|
/* if there is not room in the horizontal scrolling portion of
|
|
* the list for the widest column remaining in the horizontal
|
|
* scrolling portion of the list, then don't move the column */
|
|
widest_remaining = 0;
|
|
for ( cnt = lmp->fixed_columns; cnt < lmp->nbr_columns;
|
|
++cnt )
|
|
{
|
|
if ( cnt == column )
|
|
continue;
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
if ( col_width > widest_remaining )
|
|
widest_remaining = col_width;
|
|
}
|
|
column_data = lmp->lm_column_data[lmp->fixed_columns];
|
|
cell_data2 = lmp->lm_column_data[column];
|
|
new_fixed_width = column_data->x_pix_pos;
|
|
if ( position < lmp->fixed_columns || !in_hscrolling )
|
|
new_fixed_width += cell_data2->pix_width + 2 * col_offset;
|
|
if ( column < lmp->fixed_columns )
|
|
new_fixed_width -= cell_data2->pix_width + 2 * col_offset;
|
|
lm_get_list_rct( lmp, &r );
|
|
width_remaining = r.right - r.left - new_fixed_width;
|
|
if ( widest_remaining > width_remaining )
|
|
do_move = FALSE;
|
|
}
|
|
|
|
if ( do_move )
|
|
{
|
|
BOOLEAN in_fixed = !in_hscrolling;
|
|
|
|
if ( position > lmp->fixed_columns )
|
|
in_fixed = FALSE;
|
|
if ( do_lm_cb_column( ( long ) lmp, LM_CB_COL_MOVE, column,
|
|
position, 0, 0, in_fixed ) == FALSE )
|
|
{
|
|
members = xi_get_member_list( list_obj, &nbr_members );
|
|
xi_move_column_internal( members[column], position,
|
|
in_hscrolling );
|
|
lm_calc_last_vis( lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_drag_rect
|
|
lmp: current lmp
|
|
prct: returns rectangle where row or "after-all" events will be
|
|
generated
|
|
-------------------------------------------------------------------------*/
|
|
#define DROP_AFTER_MARGIN 10
|
|
|
|
static void
|
|
lm_get_drag_rect( LM_DATA * lmp, XinRect * prct )
|
|
{
|
|
lm_get_rect( ( LM ) lmp, LM_LIST, 0, prct );
|
|
if ( lmp->nbr_rows == 0 || ( lmp->have_last_rec
|
|
&& lmp->recs[lmp->last_fully_vis] == lmp->last_rec ) )
|
|
{
|
|
if ( lmp->pixel_width != 0 )
|
|
{
|
|
XinRect hsb_rct;
|
|
|
|
xi_get_hsb_rect( lmp->list_obj, &hsb_rct );
|
|
prct->bottom = hsb_rct.bottom;
|
|
}
|
|
else
|
|
prct->bottom += DROP_AFTER_MARGIN;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_no_event_rect
|
|
lmp: current lmp
|
|
prct: returns rectangle where no drag event will be generated
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_get_no_event_rect( LM_DATA * lmp, XinRect * prct )
|
|
{
|
|
lm_get_rect( ( LM ) lmp, LM_LIST, 0, prct );
|
|
if ( lmp->list_obj->v.list->sb_win )
|
|
{
|
|
XinRect rct;
|
|
|
|
xi_get_sb_rect( lmp->list_obj, &rct );
|
|
prct->right = rct.right;
|
|
}
|
|
if ( lmp->pixel_width != 0 && ( !lmp->have_last_rec
|
|
|| lmp->recs[lmp->last_fully_vis] != lmp->last_rec ) )
|
|
{
|
|
XinRect rct;
|
|
|
|
xi_get_hsb_rect( lmp->list_obj, &rct );
|
|
prct->bottom = rct.bottom;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_check_interface
|
|
itf: current interface
|
|
where: current mouse position, will be translated if new interface
|
|
is returned
|
|
returns: new interface, or NULL if no change
|
|
-------------------------------------------------------------------------*/
|
|
static XI_OBJ *
|
|
lm_check_interface( XI_OBJ * itf, XinPoint * where )
|
|
{
|
|
XinRect rct;
|
|
XinWindow win;
|
|
|
|
win = xi_get_window( itf );
|
|
XinWindowRectGet( win, &rct );
|
|
if ( !XinRectPointContained( &rct, where ) )
|
|
{
|
|
XinRect temp;
|
|
XinPoint pt;
|
|
XI_OBJ *new_itf;
|
|
|
|
temp.top = temp.bottom = where->v;
|
|
temp.left = temp.right = where->h;
|
|
XinWindowRectTranslate( win, XinWindowTaskGet( ), &temp );
|
|
pt.v = temp.top;
|
|
pt.h = temp.left;
|
|
new_itf = xi_get_itf_containing( &pt );
|
|
if ( new_itf == itf )
|
|
itf = NULL;
|
|
else
|
|
itf = new_itf;
|
|
if ( itf != NULL )
|
|
{
|
|
win = xi_get_window( itf );
|
|
XinWindowRectTranslate( XinWindowTaskGet( ), win, &temp );
|
|
where->v = temp.top;
|
|
where->h = temp.left;
|
|
XinWindowMouseRelease( );
|
|
XinWindowFrontSet( win );
|
|
XinWindowPaintForce( win );
|
|
XinWindowMouseTrap( win, TRUE );
|
|
}
|
|
return itf;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_drag_row_hit_test
|
|
lmp: current lmp
|
|
itf: current interface
|
|
where: current mouse position, will be translated if new interface
|
|
is returned
|
|
returns: new interface, or NULL if no change
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_drag_row_hit_test( LM_DATA * lmp, XinPoint * where, int *rowp )
|
|
{
|
|
int tmp_v,
|
|
i,
|
|
first,
|
|
last;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
|
|
/* figure out what row the mouse is in */
|
|
tmp_v = where->v - lmp->mlr.top - lmp->rrr_offset;
|
|
first = max( lmp->first_fully_vis - 1, 0 );
|
|
last = min( lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1 );
|
|
for ( i = first,
|
|
pix_offsetsp = &lmp->pix_offsets[i],
|
|
pix_heightsp = &lmp->pix_heights[i];
|
|
i <= last; ++i, ++pix_offsetsp, ++pix_heightsp )
|
|
{
|
|
if ( tmp_v >= *pix_offsetsp && tmp_v < ( *pix_offsetsp + *pix_heightsp ) )
|
|
{
|
|
*rowp = i;
|
|
break;
|
|
}
|
|
}
|
|
return ( i <= last );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_drag_row_event
|
|
itf: interface where event actually occured
|
|
lmp: current lmp
|
|
ep: xin event
|
|
oevp: orginal xin event
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_drag_row_event( XI_OBJ * itf, LM_DATA * lmp, XinEvent * ep, XinEvent * oevp )
|
|
{
|
|
XinPoint where;
|
|
|
|
where = oevp->v.mouse.where;
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseMove:
|
|
{
|
|
static int autoscroll_count = 0;
|
|
BOOLEAN scrolled = FALSE;
|
|
XI_OBJ *new_itf;
|
|
|
|
if ( !lmp->dragging_row )
|
|
{
|
|
lmp->dragging_row = TRUE;
|
|
lmp->last_itf = itf;
|
|
lmp->last_x = where.h;
|
|
lmp->org_x = lmp->last_x;
|
|
lmp->last_y = where.v;
|
|
lmp->org_y = lmp->last_y;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
xi_set_drag_list_obj( lmp->list_obj );
|
|
rubber_rect( lmp );
|
|
break;
|
|
}
|
|
new_itf = lm_check_interface( itf, &where );
|
|
|
|
if ( new_itf == NULL && lmp->itf_obj == itf && lmp->drag_rows_autoscroll )
|
|
{ /* Test for autoscroll */
|
|
XinRect list_rct;
|
|
|
|
lm_get_rect( ( LM ) lmp, LM_LIST, 0, &list_rct );
|
|
list_rct.top = lmp->pix_row1_top;
|
|
if ( where.v > list_rct.bottom )
|
|
{
|
|
if ( where.v > list_rct.bottom + XI_AUTOSCROLL_FAST
|
|
|| ++autoscroll_count >= XI_AUTOSCROLL_COUNT )
|
|
{
|
|
LM_SCROLL_ARG arg;
|
|
|
|
autoscroll_count = 0;
|
|
rubber_rect( lmp );
|
|
MEMCLEAR( arg );
|
|
arg.lm = ( LM ) lmp;
|
|
arg.nbr_lines = 1;
|
|
arg.percent = 0;
|
|
arg.same_cell = TRUE;
|
|
arg.rec_at_top = TRUE;
|
|
lm_scroll( &arg );
|
|
scrolled = TRUE;
|
|
}
|
|
}
|
|
else if ( where.v < list_rct.top )
|
|
{
|
|
if ( where.v < list_rct.top - XI_AUTOSCROLL_FAST
|
|
|| ++autoscroll_count >= XI_AUTOSCROLL_COUNT )
|
|
{
|
|
LM_SCROLL_ARG arg;
|
|
|
|
autoscroll_count = 0;
|
|
rubber_rect( lmp );
|
|
MEMCLEAR( arg );
|
|
arg.lm = ( LM ) lmp;
|
|
arg.nbr_lines = -1;
|
|
arg.percent = 0;
|
|
arg.same_cell = TRUE;
|
|
arg.rec_at_top = TRUE;
|
|
lm_scroll( &arg );
|
|
scrolled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
autoscroll_count = 0;
|
|
}
|
|
|
|
if ( scrolled || where.h != lmp->last_x || where.v != lmp->last_y )
|
|
{
|
|
if ( !scrolled )
|
|
rubber_rect( lmp );
|
|
if ( new_itf != NULL )
|
|
lmp->last_itf = new_itf;
|
|
lmp->last_x = where.h;
|
|
lmp->last_y = where.v;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
rubber_rect( lmp );
|
|
}
|
|
break;
|
|
}
|
|
case XinEventMouseUp:
|
|
{
|
|
int obj_num;
|
|
XI_OBJ **objlist;
|
|
XI_OBJ *dest_list;
|
|
LM_DATA *dest_lmp;
|
|
|
|
rubber_rect( lmp );
|
|
lmp->last_itf = NULL;
|
|
lmp->dragging_row = FALSE;
|
|
xi_set_drag_list_obj( NULL );
|
|
|
|
/* Check to see if window changed */
|
|
{
|
|
XI_OBJ *new_itf;
|
|
|
|
new_itf = lm_check_interface( itf, &where );
|
|
if ( new_itf != NULL )
|
|
itf = new_itf;
|
|
}
|
|
|
|
/* Find list object in current position */
|
|
dest_list = lmp->list_obj;
|
|
objlist = xi_get_member_list( itf, &obj_num );
|
|
for ( ; obj_num > 0; obj_num--, objlist++ )
|
|
if ( ( *objlist )->type == XIT_LIST )
|
|
{
|
|
XinRect rct;
|
|
|
|
lm_get_drag_rect( ( LM_DATA * ) ( *objlist )->v.list->lm, &rct );
|
|
if ( XinRectPointContained( &rct, &where ) )
|
|
{
|
|
dest_list = *objlist;
|
|
break;
|
|
}
|
|
}
|
|
dest_lmp = ( LM_DATA * ) dest_list->v.list->lm;
|
|
|
|
/* Match coordinates to window */
|
|
if ( dest_lmp->itf_obj != itf )
|
|
{
|
|
XinRect temp;
|
|
|
|
temp.top = temp.bottom = where.v;
|
|
temp.left = temp.right = where.h;
|
|
XinWindowRectTranslate( xi_get_window( itf ), xi_get_window( lmp->itf_obj ), &temp );
|
|
where.v = temp.top;
|
|
where.h = temp.left;
|
|
}
|
|
|
|
{ /* Generate drop rows event */
|
|
int row;
|
|
int column = 0;
|
|
LM_CB_DATA lm_cb_data;
|
|
XinRect list_rct;
|
|
|
|
lm_cb_data.v.drop_row.src_rec = lmp->rec_being_moved;
|
|
lm_cb_data.v.drop_row.after_all_rows = FALSE;
|
|
lm_cb_data.v.drop_row.delete_row = FALSE;
|
|
lm_cb_data.rec = 0;
|
|
lm_get_drag_rect( dest_lmp, &list_rct );
|
|
if ( !XinRectPointContained( &list_rct, &where ) )
|
|
{
|
|
lm_get_no_event_rect( dest_lmp, &list_rct );
|
|
if ( XinRectPointContained( &list_rct, &where ) )
|
|
break;
|
|
row = column = 0;
|
|
lm_cb_data.v.drop_row.delete_row = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( where.v < dest_lmp->pix_row1_top )
|
|
break;
|
|
if ( lm_drag_row_hit_test( dest_lmp, &where, &row ) )
|
|
lm_cb_data.rec = dest_lmp->recs[row];
|
|
else
|
|
lm_cb_data.v.drop_row.after_all_rows = TRUE;
|
|
}
|
|
lm_cb_data.lm = ( LM ) dest_lmp;
|
|
lm_cb_data.cb_type = LM_CB_DROP_ROW;
|
|
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.drop_row.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.drop_row.control = ep->v.mouse.control;
|
|
lm_cb_data.v.drop_row.src_list = lmp->list_obj;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_x
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
returns: Calculates and returns the X pixel position of the rubber band line.
|
|
Used only when sizing columns.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calc_x( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
int column = lmp->column_being_sized;
|
|
int temp,
|
|
temp2,
|
|
widest_remaining;
|
|
int min_width_in_pix = 16;
|
|
int col_offset;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
|
|
/* temp is the min width position of the column, relative to the left edge of
|
|
* the list. */
|
|
temp = lmp->lm_column_data[column]->x_pix_pos + col_offset +
|
|
min_width_in_pix;
|
|
if ( lmp->lm_column_data[column]->wrap_text_scrollbar )
|
|
temp += (int)XinMetricGet( XinMetricVerticalScrollBarWidth );
|
|
temp = max( ep->v.mouse.where.h, temp );
|
|
widest_remaining = 0;
|
|
if ( lmp->pixel_width )
|
|
{
|
|
int col_offset,
|
|
col_width,
|
|
cnt;
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
if ( column < lmp->fixed_columns )
|
|
{
|
|
/* figure out the widest column in the horizontal scrolling portion of
|
|
* the list */
|
|
for ( cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt )
|
|
{
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
if ( col_width > widest_remaining )
|
|
widest_remaining = col_width;
|
|
}
|
|
/* add the widths of all of the columns to the right of this column in
|
|
* the fixed portion of the list */
|
|
temp2 = 0;
|
|
for ( cnt = column + 1; cnt < lmp->fixed_columns; ++cnt )
|
|
{
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
temp2 += col_width;
|
|
}
|
|
temp = min( ( lmp->pixel_width - widest_remaining - temp2 ) - BORDER_WIDTH,
|
|
temp );
|
|
}
|
|
else
|
|
temp = min( ( lmp->pixel_width + lmp->delta_x ) - BORDER_WIDTH, temp );
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_x
|
|
lmp: current lmp
|
|
x: draw a rubber line at position x
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_x( LM_DATA * lmp, int x )
|
|
{
|
|
#if XIWS != XIWS_WM
|
|
int top,
|
|
bottom;
|
|
XinDrawTools new_ctools;
|
|
XinPoint pnt;
|
|
XinWindow win = lmp->win;
|
|
|
|
top = lmp->pix_top;
|
|
bottom = lmp->mlr.bottom;
|
|
XinWindowDrawToolsNormalGet( &new_ctools );
|
|
XinWindowDrawToolsSet( win, &new_ctools );
|
|
XinWindowPenSet( win, &rubber_cpen );
|
|
XinWindowDrawModeSet( win, XinDrawModeXor );
|
|
xi_set_clip( win, NULL );
|
|
pnt.h = x;
|
|
pnt.v = top;
|
|
if ( !lmp->down_in_hscrolling )
|
|
pnt.h += lmp->rct.left;
|
|
lm_move_to( lmp, pnt, FALSE, lmp->down_in_hscrolling );
|
|
pnt.v = bottom;
|
|
lm_draw_line( lmp, pnt, FALSE, lmp->down_in_hscrolling );
|
|
#else
|
|
NOREF( lmp );
|
|
NOREF( x );
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_size_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_size_event( LM_DATA * lmp, XinEvent * ep )
|
|
{
|
|
int x;
|
|
|
|
switch ( ep->type )
|
|
{
|
|
case XinEventMouseDown:
|
|
case XinEventMouseDouble:
|
|
x = calc_x( lmp, ep );
|
|
lmp->last_x = x;
|
|
rubber_x( lmp, x );
|
|
break;
|
|
case XinEventMouseMove:
|
|
x = calc_x( lmp, ep );
|
|
rubber_x( lmp, lmp->last_x );
|
|
lmp->last_x = x;
|
|
rubber_x( lmp, x );
|
|
break;
|
|
case XinEventMouseUp:
|
|
{
|
|
int col_offset;
|
|
int column;
|
|
int temp;
|
|
int width_in_chars;
|
|
int pixel_width;
|
|
XI_OBJ *list_obj,
|
|
**members;
|
|
int nbr_members;
|
|
int char_width;
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
x = calc_x( lmp, ep );
|
|
rubber_x( lmp, lmp->last_x );
|
|
column = lmp->column_being_sized;
|
|
lm_column_data = lmp->lm_column_data[column];
|
|
temp = lm_column_data->x_pix_pos + col_offset;
|
|
pixel_width = ( x - temp ) - col_offset;
|
|
width_in_chars = ( int ) ( pixel_width / ( long ) xi_get_fu_width( lmp->itf_obj ) );
|
|
list_obj = lmp->list_obj;
|
|
|
|
char_width = width_in_chars * XI_FU_MULTIPLE;
|
|
if ( xi_get_xil_pref( list_obj->itf ) )
|
|
char_width = width_in_chars;
|
|
|
|
if ( do_lm_cb_column( ( long ) lmp, LM_CB_COL_SIZE, column,
|
|
0, char_width, pixel_width, FALSE ) == FALSE )
|
|
{
|
|
int i;
|
|
|
|
members = xi_get_member_list( list_obj, &nbr_members );
|
|
xi_column_set_pixel_width( members[column], pixel_width );
|
|
i = lm_get_left_most_far_right_col( lmp, lmp->nbr_columns );
|
|
if ( i < lmp->first_vis )
|
|
{
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_hscroll( ( LM ) lmp, lmp->first_vis - i, 0 );
|
|
}
|
|
else
|
|
{
|
|
lm_calc_last_vis( lmp );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
}
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_bitmap
|
|
lm: current lm
|
|
bitmap: bitmap object
|
|
row:
|
|
column:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_bitmap( LM lm, XI_BITMAP* bitmap, int row, int column )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
lmp->cell_data[row][column].bitmap = xi_bitmap_copy( bitmap );
|
|
if ( LMP( lm )->attrib & XI_ATR_VISIBLE )
|
|
redraw_cell( lm, row, column, FALSE );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_icon
|
|
lm: current lm
|
|
icon_rid: icon resource id
|
|
row:
|
|
column:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_icon( LM lm, int icon_rid, int row, int column )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
lmp->cell_data[row][column].icon_rid = icon_rid;
|
|
if ( LMP( lm )->attrib & XI_ATR_VISIBLE )
|
|
redraw_cell( lm, row, column, FALSE );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_column_bitmap
|
|
lm: current lm
|
|
bitmap: bitmap object
|
|
cid: cid of the column to set
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_column_bitmap( LM lm, XI_BITMAP* bitmap, int cid )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
XI_OBJ *list = lmp->list_obj;
|
|
int column;
|
|
|
|
for ( column = 0; column < list->nbr_children; column++ )
|
|
{
|
|
if ( list->children[column]->cid == cid )
|
|
{
|
|
XinRect rect;
|
|
|
|
lmp->lm_column_data[column]->bitmap = xi_bitmap_copy( bitmap );
|
|
lm_get_rect( lm, LM_COLUMN, column, &rect );
|
|
xi_invalidate_rect( lmp->win, &rect );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_column_icon
|
|
lm: current lm
|
|
icon_rid: icon resource id
|
|
cid: cid of the column to set
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_column_icon( LM lm, int icon_rid, int cid )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
XI_OBJ *list = lmp->list_obj;
|
|
int column;
|
|
|
|
for ( column = 0; column < list->nbr_children; column++ )
|
|
{
|
|
if ( list->children[column]->cid == cid )
|
|
{
|
|
XinRect rect;
|
|
|
|
lmp->lm_column_data[column]->icon_rid = icon_rid;
|
|
lm_get_rect( lm, LM_COLUMN, column, &rect );
|
|
xi_invalidate_rect( lmp->win, &rect );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_sel
|
|
lm: current lm
|
|
row: row
|
|
column: column
|
|
c1: starting position in selection
|
|
c2: ending position
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_sel( LM lm, int row, int column, BOOLEAN v_scrolled, int c1, int c2 )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
if ( !lm_focus_list_has( lmp ) )
|
|
{
|
|
lm_focus_cell_set( lmp, row, column, FALSE );
|
|
}
|
|
else
|
|
{
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN is_v_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &focus_row, &focus_column, &is_v_scrolled );
|
|
if ( focus_row != row || focus_column != column || v_scrolled != is_v_scrolled )
|
|
lm_focus_cell_set( lmp, row, column, FALSE );
|
|
}
|
|
if ( v_scrolled )
|
|
{
|
|
lm_focus_cell_selection_set( lmp, c1, c2 );
|
|
}
|
|
else
|
|
{
|
|
XI_TEXT *text;
|
|
|
|
text = xi_text_focus_get( lmp->win );
|
|
if ( text )
|
|
xi_text_selection_set( text, c1, c2 );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: scroll_list
|
|
lmp: current lmp
|
|
left_col:
|
|
right_col:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
scroll_list( LM_DATA * lmp, int new_first_col )
|
|
{
|
|
XinRect r;
|
|
int new_pos;
|
|
int dist;
|
|
|
|
new_pos = lmp->lm_column_data[new_first_col]->x_pix_pos
|
|
- lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
|
|
if ( new_pos == lmp->delta_x )
|
|
{
|
|
if ( lmp->nbr_columns == lmp->fixed_columns )
|
|
lmp->delta_x = 0;
|
|
return;
|
|
}
|
|
dist = new_pos - lmp->delta_x;
|
|
lmp->delta_x += dist;
|
|
r.left = lmp->vir_left;
|
|
r.right = lmp->vir_right;
|
|
#if XIWS != XIWS_WM
|
|
r.top = lmp->rct.top + BORDER_WIDTH;
|
|
r.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
#else
|
|
r.top = lmp->rct.top;
|
|
r.bottom = lmp->rct.bottom;
|
|
#endif
|
|
if ( !lmp->itf_obj->v.itf->half_baked )
|
|
XinWindowPaintForce( lmp->win );
|
|
xi_set_update_obj( lmp->list_obj );
|
|
lmp->last_vis = lmp->first_vis;
|
|
lm_calc_last_vis( lmp );
|
|
xi_scroll_rect( lmp->win, &r, -dist, 0 );
|
|
|
|
if ( !lmp->itf_obj->v.itf->half_baked )
|
|
XinWindowPaintForce( lmp->win );
|
|
lm_set_hscroll_bar( ( LM ) lmp );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_hscroll
|
|
lm: current lm
|
|
nbr_columns: number of columns to scroll
|
|
pos: if set, pos is a percentage based on where the thumb was dropped.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_hscroll( LM lm, int nbr_columns, int pos )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
int last_vis,
|
|
lmfrc,
|
|
starting_column;
|
|
|
|
XinWindowPaintForce( lmp->win );
|
|
if ( lmp->nbr_columns == 0 )
|
|
return;
|
|
lmfrc = lm_get_left_most_far_right_col( LMP( lm ), lmp->nbr_columns );
|
|
last_vis = min( lmp->last_vis, lmp->nbr_columns - 1 );
|
|
if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) )
|
|
lm_focus_cell_invis_make( lmp );
|
|
else
|
|
{
|
|
if ( !lmp->itf_obj->v.itf->moving_focus )
|
|
if ( !xi_move_focus( lmp->itf_obj ) )
|
|
return;
|
|
}
|
|
if ( nbr_columns == XI_SCROLL_FIRST )
|
|
{
|
|
starting_column = lmfrc;
|
|
if ( starting_column )
|
|
{
|
|
starting_column = starting_column - lmp->fixed_columns;
|
|
starting_column = ( int ) ( ( ( long ) pos * ( long ) starting_column ) /
|
|
( long ) 100 );
|
|
}
|
|
starting_column += lmp->fixed_columns;
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min( lmp->first_vis, lmp->nbr_columns - 1 );
|
|
scroll_list( lmp, lmp->first_vis );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
}
|
|
if ( nbr_columns == XI_SCROLL_PGDOWN )
|
|
{
|
|
starting_column = min( last_vis + 1, lmfrc );
|
|
starting_column = min( starting_column, lmp->nbr_columns - 1 );
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min( lmp->first_vis, lmp->nbr_columns - 1 );
|
|
scroll_list( lmp, lmp->first_vis );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
}
|
|
if ( nbr_columns == XI_SCROLL_PGUP )
|
|
{
|
|
starting_column = lm_get_left_most_far_right_col( lmp, lmp->first_vis );
|
|
starting_column = min( starting_column, lmp->nbr_columns - 1 );
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min( lmp->first_vis, lmp->nbr_columns - 1 );
|
|
scroll_list( lmp, lmp->first_vis );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
return;
|
|
}
|
|
lmp->first_vis += nbr_columns;
|
|
if ( nbr_columns > 0 )
|
|
{
|
|
lmp->first_vis = min( lmp->first_vis, lm_get_left_most_far_right_col( lmp, lmp->nbr_columns ) );
|
|
lmp->first_vis = min( lmp->first_vis, lmp->nbr_columns - 1 );
|
|
}
|
|
else
|
|
{
|
|
lmp->first_vis = max( lmp->first_vis, lmp->fixed_columns );
|
|
lmp->first_vis = min( lmp->first_vis, lmp->nbr_columns - 1 );
|
|
}
|
|
scroll_list( lmp, lmp->first_vis );
|
|
lm_focus_cell_visible_attempt( lmp );
|
|
}
|
|
|
|
void
|
|
lm_calculate_pix_offsets( LM lm )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
lm_make_rrr_room_pix( lmp, 0, FALSE );
|
|
}
|
|
|
|
BOOLEAN
|
|
lm_cr_is_ok( LM lm, int row, int col, BOOLEAN v_scrolled )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
lm_column_data = lmp->lm_column_data[col];
|
|
if ( lm_column_data->cr_ok )
|
|
return TRUE;
|
|
if ( v_scrolled )
|
|
{
|
|
if ( lm_focus_cell_is_button_full_cell( lmp ) )
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if ( cell_data->button_full_cell )
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
lm_is_button_full_cell( LM lm, int row, int col )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
return cell_data->button_full_cell;
|
|
}
|
|
|
|
void
|
|
lm_set_rect( LM lm, XinRect *rect )
|
|
{
|
|
LM_DATA *lmp;
|
|
XinRect fu_rect;
|
|
|
|
lmp = (LM_DATA*)lm;
|
|
|
|
fu_rect = *rect;
|
|
fu_rect.right -= 2 * BORDER_WIDTH;
|
|
if (lmp->list_obj->v.list->hsb_win)
|
|
{
|
|
XinRect hsb_rect;
|
|
xi_get_hsb_rect( lmp->list_obj, & hsb_rect );
|
|
fu_rect.bottom += hsb_rect.bottom - hsb_rect.top;
|
|
}
|
|
xi_pu_to_fu( lmp->itf_obj, (XinPoint*)&fu_rect, 2 );
|
|
lmp->list_obj->v.list->xi_pnt = *(XinPoint*)&fu_rect;
|
|
if (lmp->list_obj->v.list->height != 0)
|
|
lmp->list_obj->v.list->height = fu_rect.bottom - fu_rect.top;
|
|
if (lmp->list_obj->v.list->width != 0 )
|
|
lmp->list_obj->v.list->width = fu_rect.right - fu_rect.left;
|
|
|
|
/* TODO - lm_recalc_metrics gets the proper height for the list not including
|
|
the hsb, then puts the hsb inside that rect instead of below it. Therefore,
|
|
the first time you resize, the list gets shorter by a scrollbar height, and
|
|
thereafter it doesn't change. */
|
|
lm_recalc_metrics( lm );
|
|
|
|
}
|