fa53273fe0
Files correlati : Ricompilazione Demo : [ ] Commento : Compilazione Linux git-svn-id: svn://10.65.10.50/trunk@11220 c028cbd2-c16b-5b4b-a496-9718f37d4682
1623 lines
47 KiB
C
Executable File
1623 lines
47 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"
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Metrics Documentation
|
|
lmp->rct.top and lmp->rct.bottom are the top and bottom of the list, excluding the
|
|
horizontal scroll bar.
|
|
lmp->rct.left is the physical left position of the list
|
|
lmp->rct.right is the position of the physical right position of the list. However, if the
|
|
list is a horizontal scrolling list, then lmp->rct.right will be beyond lmp->width.
|
|
It is useful for drawing using the virtual functions, but it is necessary to subtract
|
|
lmp->rct.left before calling the drawing functions, because the drawing functions will
|
|
add lmp->rct.left to the h values before drawing.
|
|
-------------------------------------------------------------------------*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
ROWS: REALIZED, and ALLOCATED-USED, and ALLOCATED-NOT USED.
|
|
|
|
In the realized rows array, there are three types of rows.
|
|
|
|
First, there are rows that are not being used at all. These are the rows
|
|
after lmp->nbr_realized_rows. The record handles for these rows are 0L.
|
|
|
|
Second, there are rows that are allocated, and used. These are the rows
|
|
after 0, and before lmp->nbr_realized_rows.
|
|
The record handles for these rows are not 0L.
|
|
|
|
Third, there are rows that are allocated, and not used. These are the rows
|
|
after 0, and less than lmp->nbr_realized_rows.
|
|
The record handles for these rows are not 0L. If one of these rows is requested
|
|
to be allocated, and the handle is not 0L, then then allocation event is not
|
|
done. If one of these rows is requested to be freed, and the handle is 0L,
|
|
then the free event is not done.
|
|
-------------------------------------------------------------------------*/
|
|
|
|
/* Error codes: 20900 - 20918 */
|
|
|
|
|
|
#define LM_REDRAW_ATR (LM_ATR_VISIBLE | LM_ATR_ENABLED)
|
|
|
|
#define LM_REQUESTING_CELL(lm, row, col) (LMP(lm)->in_cell_request && LMP(lm)->cell_request_row == (row) && LMP(lm)->cell_request_col == (col))
|
|
|
|
#define BUFLEN 256
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_last_vis
|
|
lmp: current lmp
|
|
process: calculates the last fully visible column in the list
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_calc_last_vis( LM_DATA * lmp )
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
int l1;
|
|
|
|
if ( !lmp->pixel_width )
|
|
lmp->last_vis = lmp->nbr_columns - 1;
|
|
else
|
|
{
|
|
lmp->last_vis = lmp->first_vis;
|
|
for ( l1 = lmp->first_vis + 1; l1 < lmp->nbr_columns; ++l1 )
|
|
{
|
|
column_data = lmp->lm_column_data[l1];
|
|
if ( ( column_data->x_pix_pos - lmp->delta_x + column_data->pix_width )
|
|
>= lmp->pixel_width )
|
|
{
|
|
lmp->last_vis = l1 - 1;
|
|
return;
|
|
}
|
|
lmp->last_vis = l1;
|
|
}
|
|
if ( l1 == lmp->nbr_columns )
|
|
lmp->last_vis = l1 - 1;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_col_spacing
|
|
returns: column spacing
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_col_spacing( void )
|
|
{
|
|
return ( 2 * ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET ) + RULE_WIDTH_V );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_left_most_far_right_column
|
|
lmp: current lmp
|
|
nbr_columns: column, from which we will count back
|
|
notes: This function is also used when the users presses page up on the
|
|
horizontal scroll bar, to determine the new left most column.
|
|
Get the column number for the column that would be visible if the
|
|
list is scrolled entirely over to the right. This is necessary
|
|
to compute the position of the horizontal thumb, and other reasons.
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_left_most_far_right_col( LM_DATA * lmp, int nbr_columns )
|
|
{
|
|
int width,
|
|
i;
|
|
|
|
#if XIWS == XIWS_WM
|
|
width = lmp->pixel_width;
|
|
#else
|
|
width = lmp->pixel_width + ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET )
|
|
+ RULE_WIDTH_V;
|
|
#endif
|
|
for ( i = 0; i < min( lmp->fixed_columns, lmp->nbr_columns ); ++i )
|
|
width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing( );
|
|
for ( i = nbr_columns - 1; i >= lmp->fixed_columns; --i )
|
|
{
|
|
width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing( );
|
|
if ( width <= 0 )
|
|
break;
|
|
}
|
|
return ( i + 1 );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_cell_rect
|
|
rctp: pointer to rectangle to be filled in
|
|
lm: current lm
|
|
row: relevant row
|
|
col: relevant column
|
|
inner: if TRUE, get the inner rectangle of the cell, else get the outer
|
|
rectangle of the cell
|
|
physical_rct: if TRUE, get the physical rectangle, else get the virtual
|
|
rectangle
|
|
notes: This function is called before starting the text edit object for the cell.
|
|
returns: rctp
|
|
-------------------------------------------------------------------------*/
|
|
XinRect *
|
|
lm_get_cell_rect( XinRect * rctp, LM lm, int row, int col, BOOLEAN inner, BOOLEAN physical_rct )
|
|
{
|
|
LM_COLUMN_DATA *temp_lmcd;
|
|
int col_offset;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
temp_lmcd = lmp->lm_column_data[col];
|
|
|
|
rctp->top = lmp->pix_offsets[row];
|
|
#if XIWS != XIWS_WM
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row] - RULE_WIDTH_V;
|
|
#else
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row];
|
|
#endif
|
|
|
|
rctp->left = temp_lmcd->x_pix_pos;
|
|
rctp->right = rctp->left + temp_lmcd->pix_width + 2 *
|
|
( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
|
|
if ( inner )
|
|
{
|
|
rctp->left += col_offset;
|
|
rctp->right -= col_offset;
|
|
#if XIWS != XIWS_WM
|
|
rctp->top += RULE_Y_OFFSET_TOP;
|
|
rctp->bottom -= RULE_Y_OFFSET_BOTTOM;
|
|
#endif
|
|
}
|
|
if ( physical_rct )
|
|
{
|
|
rctp->left += lmp->rct.left;
|
|
rctp->right += lmp->rct.left;
|
|
|
|
if ( rctp->left >= lmp->vir_left )
|
|
{
|
|
rctp->left -= lmp->delta_x;
|
|
rctp->right -= lmp->delta_x;
|
|
}
|
|
|
|
rctp->top = rctp->top + lmp->rrr_offset + lmp->mlr.top;
|
|
rctp->bottom = rctp->bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
}
|
|
return ( rctp );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_row_rect
|
|
rctp: pointer to rectangle to be filled in
|
|
lm: current lm
|
|
row: relevant row
|
|
returns: rctp
|
|
-------------------------------------------------------------------------*/
|
|
XinRect *
|
|
lm_get_row_rect( XinRect * rctp, LM lm, int row )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
rctp->top = lmp->pix_offsets[row];
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row];
|
|
|
|
rctp->left = lmp->rct.left + BORDER_WIDTH;
|
|
#if XIWS != XIWS_WM
|
|
rctp->right = lmp->rct.right - BORDER_WIDTH;
|
|
#else
|
|
rctp->right = lmp->rct.right;
|
|
#endif
|
|
if ( lmp->pixel_width )
|
|
rctp->right = rctp->left + lmp->pixel_width;
|
|
|
|
return ( rctp );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_adj_h
|
|
lmp: current lmp
|
|
h: pointer to horizontal coord to convert
|
|
returns: TRUE if position is visible
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_adj_h( LM_DATA * lmp, short *h )
|
|
{
|
|
if ( *h >= lmp->vir_left )
|
|
{
|
|
XinRect r;
|
|
|
|
*h -= lmp->delta_x;
|
|
if ( *h < lmp->vir_left )
|
|
return FALSE;
|
|
r = lmp->rct;
|
|
if ( lmp->pixel_width )
|
|
r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
return ( *h <= r.right );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_rct
|
|
lmp: current lmp
|
|
r: pointer to rectangle to be filled in
|
|
returns: r
|
|
-------------------------------------------------------------------------*/
|
|
XinRect *
|
|
lm_get_list_rct( LM_DATA * lmp, XinRect * r )
|
|
{
|
|
*r = lmp->rct;
|
|
if ( lmp->pixel_width )
|
|
r->right = r->left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
return r;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_fixed_columns
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_fixed_columns( LM lm, int new_fixed_count )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
int col_spacing,
|
|
i;
|
|
XinRect rct_to_invalidate,
|
|
rct;
|
|
|
|
if ( new_fixed_count > lmp->nbr_columns )
|
|
new_fixed_count = lmp->nbr_columns;
|
|
col_spacing = lm_get_col_spacing( );
|
|
lmp->fixed_columns = new_fixed_count;
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
lmp->delta_x = 0;
|
|
|
|
/* 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;
|
|
}
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
lm_get_list_rct( lmp, &rct_to_invalidate );
|
|
xi_invalidate_rect( lmp->win, &rct_to_invalidate );
|
|
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 );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_cleanup
|
|
lm: current lm
|
|
notes: Destroys all row data and fonts
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_cleanup( LM lm )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
int col_nbr;
|
|
|
|
for ( col_nbr = 0; col_nbr < lmp->nbr_columns; col_nbr++ )
|
|
{
|
|
if ( lmp->lm_column_data[col_nbr]->font )
|
|
XinFontDestroy( lmp->lm_column_data[col_nbr]->font );
|
|
xi_bitmap_destroy( lmp->lm_column_data[col_nbr]->bitmap );
|
|
}
|
|
|
|
lm_remove_all_rows( lmp, TRUE );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete
|
|
lm: current lm
|
|
notes: do not call this function in response to XinEventDestroy.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_delete( LM lm )
|
|
{
|
|
XinRect r;
|
|
LM_DATA *lmp = LMP( lm );
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
if ( lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled ) )
|
|
{
|
|
lm_focus_remove( lmp, focus_row, focus_column, v_scrolled );
|
|
}
|
|
lm_cleanup( lm );
|
|
lm_get_list_rct( lmp, &r );
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
xi_tree_free( ( char * ) lm );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_x_pix_pos
|
|
lm: current lm
|
|
lcdata: column data pointer
|
|
position: position of column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calc_x_pix_pos( LM lm, LM_COLUMN_DATA * lcdata, int position )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
LM_COLUMN_DATA *lmcd;
|
|
|
|
if ( position )
|
|
lmcd = lmp->lm_column_data[position - 1];
|
|
lcdata->x_pix_pos = ( !position ) ? BORDER_WIDTH :
|
|
lmcd->x_pix_pos + lmcd->pix_width + lm_get_col_spacing( );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to invalidate
|
|
adj_h: adjust the horizontal coords
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rect( LM_DATA * lmp, XinRect * rctp, BOOLEAN adj_h )
|
|
{
|
|
XinRect r;
|
|
|
|
r = *rctp;
|
|
if ( adj_h )
|
|
{
|
|
lm_adj_h( lmp, &r.left );
|
|
lm_adj_h( lmp, &r.right );
|
|
}
|
|
|
|
lm_adj_v( lmp, r.top );
|
|
lm_adj_v( lmp, r.bottom );
|
|
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rect2
|
|
lmp: current lmp
|
|
rctp: rectangle to invalidate
|
|
adj_left: if TRUE, adjust left of rctp
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rect2( LM_DATA * lmp, XinRect * rctp, BOOLEAN adj_left )
|
|
{
|
|
XinRect r;
|
|
|
|
r = *rctp;
|
|
if ( adj_left )
|
|
lm_adj_h( lmp, &r.left );
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_fixed_columns
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_fixed_columns( LM lm )
|
|
{
|
|
return ( ( LM_DATA * ) lm )->fixed_columns;
|
|
}
|
|
|
|
|
|
void
|
|
lm_local_hscroll( LM lm, int nbr_columns )
|
|
{
|
|
LM_DATA *lmp;
|
|
XI_LIST_DATA *list_data;
|
|
XI_OBJ *other_list;
|
|
|
|
lmp = ( LM_DATA * ) lm;
|
|
list_data = lmp->list_obj->v.list;
|
|
lm_hscroll( lm, nbr_columns, 0 );
|
|
if ( list_data->horz_sync_list &&
|
|
!list_data->scrolling_in_progress )
|
|
{
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj( lmp->itf_obj,
|
|
list_data->horz_sync_list );
|
|
if ( other_list )
|
|
lm_hscroll( other_list->v.list->lm, nbr_columns, 0 );
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
lm_xi_text_set_color_and_attrib( LM_DATA * lmp, LM_COLUMN_DATA * lm_column_data,
|
|
LM_CELL_DATA * cell_data, int row )
|
|
{
|
|
unsigned long attrib,
|
|
cell_attrib;
|
|
|
|
cell_data->xi_text->fore_color = lmp->enabled_color;
|
|
if ( lmp->row_colors[row] )
|
|
cell_data->xi_text->fore_color = lmp->row_colors[row];
|
|
if ( cell_data->color )
|
|
cell_data->xi_text->fore_color = cell_data->color;
|
|
cell_data->xi_text->back_color = lmp->back_color;
|
|
if ( cell_data->back_color )
|
|
cell_data->xi_text->back_color = cell_data->back_color;
|
|
cell_attrib = cell_data->attrib &
|
|
( XI_ATR_HCENTER | XI_ATR_RJUST );
|
|
attrib = lm_column_data->attrib;
|
|
if ( cell_attrib )
|
|
{
|
|
attrib &= ~( XI_ATR_HCENTER | XI_ATR_RJUST );
|
|
attrib |= cell_attrib;
|
|
}
|
|
xi_text_right_justify_set( cell_data->xi_text, ( BOOLEAN ) ( ( attrib & XI_ATR_RJUST ) != 0 ) );
|
|
}
|
|
|
|
void
|
|
lm_xi_text_construct( LM_DATA * lmp, int row, int column )
|
|
{
|
|
XinFont *font;
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
int pix_spacing;
|
|
LM_CELL_DATA *cell_data;
|
|
XinRect rect;
|
|
|
|
lm_column_data = lmp->lm_column_data[column];
|
|
cell_data = &lmp->cell_data[row][column];
|
|
pix_spacing = lm_column_data->pix_width -
|
|
( cell_data->button ? lmp->pix_row_spacing : 0 );
|
|
if ( cell_data->font )
|
|
font = cell_data->font;
|
|
else if ( lmp->font )
|
|
font = lmp->font;
|
|
else
|
|
font = xi_get_system_font( );
|
|
cell_data->xi_text =
|
|
xi_text_construct( lmp->win, pix_spacing, font, lmp, lm_column_data->wrap_text,
|
|
XI_MULTILINE_SCROLLBAR_CID, FALSE );
|
|
rect = lmp->mlr;
|
|
if ( lmp->pixel_width )
|
|
rect.right = rect.left + lmp->pixel_width;
|
|
xi_text_clip_set( cell_data->xi_text, &rect );
|
|
lm_xi_text_set_color_and_attrib( lmp, lm_column_data, cell_data, row );
|
|
xi_text_parent_obj_set( cell_data->xi_text, lmp->list_obj );
|
|
xi_text_scrollbar_set( cell_data->xi_text, lm_column_data->wrap_text_scrollbar );
|
|
xi_text_read_only_set( cell_data->xi_text, ( lm_column_data->attrib & XI_ATR_READONLY ) != 0 );
|
|
xi_text_password_set( cell_data->xi_text, ( lm_column_data->attrib & XI_ATR_PASSWORD ) != 0 );
|
|
xi_text_cr_ok_set( cell_data->xi_text, lm_column_data->cr_ok );
|
|
xi_text_var_len_text_set( cell_data->xi_text, lm_column_data->var_len_text );
|
|
xi_text_pix_width_set( cell_data->xi_text, pix_spacing );
|
|
xi_text_buffer_size_set( cell_data->xi_text, lm_column_data->text_size );
|
|
xi_text_min_buffer_size_set( cell_data->xi_text, lm_column_data->text_size );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_text
|
|
lm: current lm
|
|
row: row
|
|
col: column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
do_lm_cb_text( LM_DATA * lmp, int row, int col, BOOLEAN preserve_focus_text )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
XI_BITMAP *new_bitmap;
|
|
|
|
cell_data = &( lmp->cell_data[row][col] );
|
|
lm_cb_data.lm = ( LM ) lmp;
|
|
lm_cb_data.cb_type = LM_CB_TEXT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = ( unsigned char ) row;
|
|
lm_cb_data.rec = lmp->recs[row];
|
|
lm_cb_data.column = ( unsigned char ) col;
|
|
lm_column_data = lmp->lm_column_data[col];
|
|
if ( xi_text_buffer_size_get( cell_data->xi_text ) )
|
|
{
|
|
lmp->cell_request_text = XinMemoryAlloc( xi_text_buffer_size_get( cell_data->xi_text ) );
|
|
strcpy( lmp->cell_request_text, xi_text_get( cell_data->xi_text ) );
|
|
}
|
|
lm_cb_data.v.text.text = xi_text_get( cell_data->xi_text );
|
|
lm_cb_data.v.text.len = xi_text_buffer_size_get( cell_data->xi_text );
|
|
if ( lm_cb_data.v.text.text )
|
|
lm_cb_data.v.text.text[0] = '\0';
|
|
lm_cb_data.v.text.font = NULL;
|
|
lm_cb_data.v.text.font_id = NULL;
|
|
lm_cb_data.v.text.icon_rid = cell_data->icon_rid;
|
|
lm_cb_data.v.text.bitmap = cell_data->bitmap;
|
|
lm_cb_data.v.text.attrib = cell_data->attrib;
|
|
lm_cb_data.v.text.color = 0;
|
|
lm_cb_data.v.text.back_color = 0;
|
|
lmp->in_cell_request = TRUE;
|
|
lmp->cell_request_row = row;
|
|
lmp->cell_request_col = col;
|
|
( *lmp->lm_cb ) ( &lm_cb_data );
|
|
cell_data->icon_rid = lm_cb_data.v.text.icon_rid;
|
|
new_bitmap = xi_bitmap_copy( lm_cb_data.v.text.bitmap );
|
|
xi_bitmap_destroy( cell_data->bitmap );
|
|
cell_data->bitmap = new_bitmap;
|
|
cell_data->attrib = lm_cb_data.v.text.attrib;
|
|
cell_data->color = lm_cb_data.v.text.color;
|
|
cell_data->back_color = lm_cb_data.v.text.back_color;
|
|
if ( lm_column_data->var_len_text &&
|
|
lm_cb_data.v.text.text != xi_text_get( cell_data->xi_text ))
|
|
{
|
|
/* The callback func reallocated the string, so the old pointer is simply not valid. */
|
|
xi_text_buffer_set( cell_data->xi_text, lm_cb_data.v.text.text );
|
|
xi_text_reinitialize( cell_data->xi_text );
|
|
}
|
|
if ( lm_cb_data.v.text.len != xi_text_buffer_size_get( cell_data->xi_text ) )
|
|
xi_text_buffer_size_set( cell_data->xi_text, lm_cb_data.v.text.len );
|
|
if ( lmp->cell_request_text && strcmp( xi_text_get( cell_data->xi_text ), lmp->cell_request_text ) != 0 )
|
|
xi_text_wrap( cell_data->xi_text );
|
|
if ( lmp->cell_request_text )
|
|
XinMemoryFree( lmp->cell_request_text );
|
|
lmp->in_cell_request = FALSE;
|
|
lmp->cell_request_text = NULL;
|
|
cell_data->valid_data = TRUE;
|
|
lm_focus_cell_text_set( lmp, preserve_focus_text, lm_cb_data.v.text.text, row, col, FALSE );
|
|
#if XIWS != XIWS_WM
|
|
/* cell buttons not supported for XVT/CH */
|
|
cell_data->button = lm_cb_data.v.text.button;
|
|
cell_data->button_on_left = lm_cb_data.v.text.button_on_left;
|
|
cell_data->button_on_focus = lm_cb_data.v.text.button_on_focus;
|
|
cell_data->button_full_cell = lm_cb_data.v.text.button_full_cell;
|
|
cell_data->button_icon_rid = lm_cb_data.v.text.button_icon_rid;
|
|
new_bitmap = xi_bitmap_copy( lm_cb_data.v.text.button_bitmap );
|
|
xi_bitmap_destroy( cell_data->button_bitmap );
|
|
cell_data->button_bitmap = new_bitmap;
|
|
#endif
|
|
if ( cell_data->font )
|
|
XinFontDestroy( cell_data->font );
|
|
if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) )
|
|
{
|
|
if ( lm_cb_data.v.text.font )
|
|
XinFontCopy( &cell_data->font, lm_cb_data.v.text.font );
|
|
else
|
|
cell_data->font = NULL;
|
|
}
|
|
#ifdef XI_USE_XVT
|
|
else
|
|
{
|
|
if ( lm_cb_data.v.text.font_id )
|
|
cell_data->font = XinFontXvtConvert( lm_cb_data.v.text.font_id );
|
|
else
|
|
cell_data->font = NULL;
|
|
}
|
|
#endif
|
|
if ( cell_data->font != NULL )
|
|
XinWindowFontMap( lmp->win, cell_data->font );
|
|
if ( cell_data->font )
|
|
xi_text_font_set( cell_data->xi_text, cell_data->font );
|
|
else if ( lmp->font )
|
|
xi_text_font_set( cell_data->xi_text, lmp->font );
|
|
else
|
|
xi_text_font_set( cell_data->xi_text, xi_get_system_font( ) );
|
|
lm_xi_text_set_color_and_attrib( lmp, lm_column_data, cell_data, row );
|
|
if ( lm_column_data->wrap_text )
|
|
xi_text_wrap( cell_data->xi_text );
|
|
if ( !preserve_focus_text )
|
|
{
|
|
int frow,
|
|
fcol;
|
|
BOOLEAN fis_scrolled;
|
|
|
|
lm_focus_cell_get( lmp, &frow, &fcol, &fis_scrolled );
|
|
if ( frow == row && fcol == col )
|
|
{
|
|
lmp->focus_state->focus_cell_attrib = cell_data->attrib;
|
|
if ( lmp->focus_state->focus_cell_font )
|
|
{
|
|
XinFontDestroy( lmp->focus_state->focus_cell_font );
|
|
lmp->focus_state->focus_cell_font = NULL;
|
|
}
|
|
if ( cell_data->font )
|
|
{
|
|
XinFontCopy( &lmp->focus_state->focus_cell_font, cell_data->font );
|
|
}
|
|
lmp->focus_state->focus_cell_color = cell_data->color;
|
|
lmp->focus_state->focus_cell_back_color = cell_data->back_color;
|
|
lmp->focus_state->button = cell_data->button;
|
|
lmp->focus_state->button_full_cell = cell_data->button_full_cell;
|
|
lmp->focus_state->button_on_left = cell_data->button_on_left;
|
|
lmp->focus_state->button_icon_rid = cell_data->button_icon_rid;
|
|
lmp->focus_state->button_bitmap = cell_data->button_bitmap;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_attrib
|
|
lm: current lm
|
|
lm_part: may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL
|
|
returns: attribute
|
|
notes: all rows are
|
|
-------------------------------------------------------------------------*/
|
|
unsigned long
|
|
lm_get_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
|
|
BOOLEAN v_scrolled )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
switch ( lm_part )
|
|
{
|
|
case LM_LIST:
|
|
return ( lmp->attrib );
|
|
case LM_ROW:
|
|
if ( v_scrolled )
|
|
return lm_focus_rec_attrib_get( lmp );
|
|
else
|
|
return ( lmp->row_attribs[idx] );
|
|
case LM_COLUMN:
|
|
return ( lmp->lm_column_data[idx]->attrib );
|
|
case LM_CELL:
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
/* TODO this used to test lm_focus_state_get also */
|
|
if ( v_scrolled )
|
|
return lm_focus_cell_attrib_get( lmp );
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if ( !cell_data->valid_data )
|
|
do_lm_cb_text( lmp, idx, idx2, TRUE );
|
|
return ( cell_data->attrib );
|
|
}
|
|
}
|
|
XinError( 20907, XinSeverityFatal, 0L );
|
|
return 0L;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_buf_size
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_buf_size( LM lm, LM_PART part, int idx )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
NOREF( part );
|
|
return ( lmp->lm_column_data[idx]->text_size );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_cid
|
|
lm: current lm
|
|
returns: control id of list
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_cid( LM lm )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
return lmp->cid;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_rect
|
|
lm: current lm
|
|
part: may be LM_LIST, LM_COLUMN, or LM_ROW
|
|
idx: if LM_LIST, not used
|
|
if LM_COLUMN, column number
|
|
if LM_ROW, row number
|
|
rct: rectangle to be filled in
|
|
returns: rct
|
|
-------------------------------------------------------------------------*/
|
|
XinRect *
|
|
lm_get_rect( LM lm, LM_PART part, int idx, XinRect * rct )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
switch ( part )
|
|
{
|
|
case LM_LIST:
|
|
*rct = lmp->rct;
|
|
if ( lmp->pixel_width )
|
|
rct->right = rct->left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
break;
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[idx];
|
|
if ( idx >= lmp->fixed_columns )
|
|
rct->left = lmp->rct.left + column_data->x_pix_pos - lmp->delta_x;
|
|
else
|
|
rct->left = lmp->rct.left + column_data->x_pix_pos;
|
|
rct->right = rct->left + column_data->pix_width +
|
|
2 * ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
rct->top = lmp->rct.top;
|
|
rct->bottom = lmp->rct.bottom;
|
|
break;
|
|
}
|
|
case LM_ROW:
|
|
{
|
|
int con;
|
|
|
|
con = lmp->rrr_offset + lmp->mlr.top;
|
|
|
|
rct->top = lmp->pix_offsets[idx] + con;
|
|
rct->bottom = rct->top + lmp->pix_heights[idx];
|
|
|
|
rct->left = lmp->rct.left;
|
|
rct->right = lmp->rct.right;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return rct;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_text
|
|
lm: current lm
|
|
s: string to be filled in
|
|
NULL is valid
|
|
len: size of string to be filled in
|
|
if the length of the text is longer than the size of the buffer s,
|
|
then len-1 characters will be copied, and s[len-1] will be set
|
|
to '\0'
|
|
row: row number of cell
|
|
column: column number of cell
|
|
returns: s
|
|
-------------------------------------------------------------------------*/
|
|
char *
|
|
lm_get_text( LM lm, char *s, int len, int row, int column,
|
|
BOOLEAN v_scrolled )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
char *b;
|
|
|
|
if ( row == LM_HEADING_TEXT )
|
|
b = lmp->lm_column_data[column]->heading_text;
|
|
/* TODO this used to test lm_focus_state_get also */
|
|
else if ( v_scrolled )
|
|
b = lm_focus_cell_text_get( lmp );
|
|
else
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if ( row >= lmp->nbr_realized_rows || column >= lmp->nbr_columns )
|
|
{
|
|
XinError( 20908, XinSeverityWarning, 0L );
|
|
b = NULL;
|
|
}
|
|
else
|
|
{
|
|
cell_data = &lmp->cell_data[row][column];
|
|
if ( !cell_data->valid_data )
|
|
{
|
|
do_lm_cb_text( lmp, row, column, TRUE );
|
|
b = xi_text_get( cell_data->xi_text );
|
|
}
|
|
else
|
|
{
|
|
/* If we're currently in a cell request, xi_text_get(
|
|
* cell_data->xi_text ) will return "". */
|
|
if ( LM_REQUESTING_CELL( lm, row, column ) )
|
|
b = lmp->cell_request_text;
|
|
else
|
|
b = xi_text_get( cell_data->xi_text );
|
|
}
|
|
}
|
|
}
|
|
if ( s && b )
|
|
{
|
|
tstrncpy( s, b, len );
|
|
return s;
|
|
}
|
|
else
|
|
return b;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_sel
|
|
lm: current lm
|
|
c1: pointer to integer to contain selection start
|
|
c2: pointer to integer to contain selection stop
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_sel( LM lm, int *c1, int *c2 )
|
|
{
|
|
lm_focus_cell_selection_get( ( LM_DATA * ) lm, c1, c2 );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rows_internal
|
|
lm: current lm
|
|
row_start: starting row
|
|
row_end: ending row
|
|
redraw: if TRUE, then redraw the rows
|
|
column: if -1, then do for all columns
|
|
if set, then do for a specific column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rows_internal( LM lm, int row_start, int row_end,
|
|
BOOLEAN redraw, int column,
|
|
BOOLEAN preserve_focus_text )
|
|
{
|
|
int row,
|
|
col;
|
|
XinRect rct1,
|
|
rct2;
|
|
LM_DATA *lmp = LMP( lm );
|
|
int focus_row,
|
|
focus_column;
|
|
BOOLEAN v_scrolled,
|
|
has_focus,
|
|
optimize;
|
|
|
|
row_end = min( row_end, lmp->nbr_realized_rows - 1 );
|
|
if ( row_start > row_end || row_start < 0 )
|
|
return;
|
|
has_focus = lm_focus_cell_get( lmp, &focus_row, &focus_column, &v_scrolled );
|
|
optimize = xi_get_pref( XI_PREF_OPTIMIZE_CELL_REQUESTS ) != 0;
|
|
for ( row = row_start; row <= row_end; row++ )
|
|
{
|
|
for ( col = ( column == -1 ) ? 0 : column;
|
|
col < ( ( column == -1 ) ? ( lmp->nbr_columns ) : ( column + 1 ) );
|
|
col++ )
|
|
{
|
|
if ( optimize )
|
|
{
|
|
/* if the cell that we are doing cell request for has focus, and we are
|
|
* not supposed to preserve focus text, then we need to call
|
|
* do_lm_cb_text so that the focus cell text will be set to the new
|
|
* value so that when we restart editing, the correct value will be in
|
|
* the edit control. */
|
|
if ( has_focus && !v_scrolled && !preserve_focus_text && row == focus_row && col == focus_column )
|
|
do_lm_cb_text( lmp, row, col, preserve_focus_text );
|
|
else
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &( lmp->cell_data[row][col] );
|
|
cell_data->valid_data = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
do_lm_cb_text( lmp, row, col, preserve_focus_text );
|
|
}
|
|
}
|
|
}
|
|
if ( redraw )
|
|
{
|
|
if ( ( column == -1 ) && ( row_start == 0 ) &&
|
|
( row_end == lmp->nbr_realized_rows - 1 ) )
|
|
{
|
|
lm_get_row_rect( &rct1, lm, row_start );
|
|
lm_get_row_rect( &rct2, lm, row_end );
|
|
rct1.bottom = rct2.bottom;
|
|
lm_invalidate_rect( lmp, &rct1, FALSE );
|
|
}
|
|
else
|
|
{
|
|
int col_start,
|
|
col_end;
|
|
|
|
if ( column == -1 )
|
|
{
|
|
col_start = 0;
|
|
col_end = lmp->nbr_columns - 1;
|
|
}
|
|
else
|
|
col_start = col_end = column;
|
|
draw_cell_range( lmp, row_start, row_end, col_start,
|
|
col_end, FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rows
|
|
lm: current lm
|
|
row_start: starting row
|
|
row_end: ending row
|
|
redraw: if TRUE, then redraw the rows
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rows( LM lm, int row_start, int row_end, BOOLEAN redraw )
|
|
{
|
|
lm_invalidate_rows_internal( lm, row_start, row_end, redraw, -1, TRUE );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_color
|
|
lm: current lm
|
|
part: must be LM_ROW, or LM_CELL
|
|
idx: if LM_ROW, row number
|
|
if LM_CELL, row number
|
|
idx2: if LM_ROW, not used
|
|
if LM_CELL, column number
|
|
color: color to set
|
|
half_baked: if set, don't redraw
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_color( LM lm, LM_PART part, int idx, int idx2, BOOLEAN v_scrolled,
|
|
XinColor color, BOOLEAN half_baked )
|
|
{
|
|
BOOLEAN do_redraw;
|
|
LM_DATA *lmp = LMP( lm );
|
|
|
|
switch ( part )
|
|
{
|
|
case LM_ROW:
|
|
if ( v_scrolled )
|
|
lm_focus_rec_color_set( lmp, color );
|
|
else
|
|
{
|
|
do_redraw = ( color != lmp->row_colors[idx] );
|
|
lmp->row_colors[idx] = color;
|
|
if ( !half_baked && do_redraw )
|
|
{
|
|
XinRect r;
|
|
|
|
lm_get_row_rect( &r, lm, idx );
|
|
lm_invalidate_rect( lmp, &r, FALSE );
|
|
}
|
|
}
|
|
break;
|
|
case LM_CELL:
|
|
if ( !v_scrolled )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if ( !cell_data->valid_data )
|
|
return;
|
|
cell_data->color = color;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_move_to
|
|
lmp: current lmp
|
|
p: point
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_move_to( LM_DATA * lmp, XinPoint p, BOOLEAN adj_v, BOOLEAN adj_h )
|
|
{
|
|
|
|
if ( adj_h )
|
|
{
|
|
p.h += lmp->rct.left;
|
|
lm_adj_h( lmp, &p.h );
|
|
}
|
|
|
|
if ( adj_v )
|
|
lm_adj_v( lmp, p.v );
|
|
|
|
xi_move_to( lmp->win, p );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_line
|
|
lmp: current lmp
|
|
p: point
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_draw_line( LM_DATA * lmp, XinPoint p, BOOLEAN adj_v, BOOLEAN adj_h )
|
|
{
|
|
if ( adj_h )
|
|
{
|
|
p.h += lmp->rct.left;
|
|
if ( lm_adj_h( lmp, &p.h ) )
|
|
{
|
|
if ( adj_v )
|
|
lm_adj_v( lmp, p.v );
|
|
xi_draw_line( lmp->win, p );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( adj_v )
|
|
lm_adj_v( lmp, p.v );
|
|
xi_draw_line( lmp->win, p );
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: xvtch_draw_line
|
|
lmp: current lm pointer
|
|
from: from point
|
|
to: to point
|
|
-------------------------------------------------------------------------*/
|
|
#if XIWS == XIWS_WM
|
|
static void
|
|
xvtch_draw_line( LM_DATA * lmp, XinPoint * from, XinPoint * to, BOOLEAN adj_h )
|
|
{
|
|
int i,
|
|
len;
|
|
|
|
char c_v = ( char ) C_V;
|
|
char *s,
|
|
*s2;
|
|
|
|
if ( from->h == to->h )
|
|
{
|
|
/* draw vertical line */
|
|
if ( adj_h )
|
|
{
|
|
from->h += lmp->rct.left;
|
|
if ( lm_adj_h( lmp, &from->h ) )
|
|
{
|
|
for ( i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH )
|
|
xi_draw_text( lmp->win, lmp->cur_font, from->h, i, &c_v, 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH )
|
|
xi_draw_text( lmp->win, from->h, i, &c_v, 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = ( to->h - from->h ) / VPIX_PER_CH;
|
|
s = xi_tree_malloc( len + 4, NULL );
|
|
s2 = s;
|
|
for ( i = 0; i < len; ++i )
|
|
{
|
|
|
|
*s2 = C_H;
|
|
++s2;
|
|
}
|
|
xi_draw_text( lmp->win, from->h, from->v + VPIX_PER_CH, s, len );
|
|
xi_tree_free( s );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#if XIWS == XIWS_WM
|
|
static char c_xd,
|
|
c_xu,
|
|
c_v,
|
|
c_xx;
|
|
|
|
#endif
|
|
|
|
|
|
void
|
|
lm_xi_text_prect_get( LM_DATA * lmp, LM_COLUMN_DATA * column_data,
|
|
LM_CELL_DATA * cell_data, int row, int col, int col_offset,
|
|
int leading, int ascent, int descent, XinRect * rctp )
|
|
{
|
|
XinRect rct,
|
|
row_rct;
|
|
|
|
lm_get_row_rect( &row_rct, ( LM ) lmp, row );
|
|
/* don't need to test for the rule, it is drawn elsewhere */
|
|
#if XIWS != XIWS_WM
|
|
row_rct.bottom--;
|
|
if ( row_rct.bottom < row_rct.top )
|
|
row_rct.bottom = row_rct.top;
|
|
#endif
|
|
lm_get_rect( ( LM ) lmp, LM_COLUMN, col, &rct );
|
|
lm_adj_v( lmp, row_rct.top );
|
|
lm_adj_v( lmp, row_rct.bottom );
|
|
rct.top = row_rct.top;
|
|
rct.bottom = row_rct.bottom;
|
|
rct.left += col_offset;
|
|
rct.right -= col_offset;
|
|
if ( !column_data->wrap_text )
|
|
{
|
|
if ( column_data->vertical_align_bottom )
|
|
{
|
|
int new_top;
|
|
|
|
#if XIWS == XIWS_WM
|
|
new_top = rct.bottom - ( leading + ascent + descent );
|
|
#else
|
|
new_top = rct.bottom - ( leading + ascent + descent ) - 3;
|
|
#endif
|
|
rct.top = max( rct.top, new_top );
|
|
}
|
|
else if ( column_data->vertical_align_center )
|
|
{
|
|
int height,
|
|
delta,
|
|
new_top,
|
|
new_bottom;
|
|
|
|
height = leading + ascent + descent;
|
|
delta = ( rct.bottom - rct.top - height ) / 2;
|
|
new_top = rct.top + delta;
|
|
new_bottom = rct.bottom - delta;
|
|
rct.top = max( rct.top, new_top );
|
|
rct.bottom = min( rct.bottom, new_bottom );
|
|
}
|
|
else if ( !column_data->vertical_align_center && !cell_data->button_full_cell )
|
|
{
|
|
int new_bottom;
|
|
|
|
#if XIWS == XIWS_WM
|
|
new_bottom = rct.top + leading + ascent + descent;
|
|
#else
|
|
new_bottom = rct.top + leading + ascent + descent + 4;
|
|
#endif
|
|
rct.bottom = min( rct.bottom, new_bottom );
|
|
}
|
|
}
|
|
if ( cell_data->button )
|
|
{
|
|
XinRect r;
|
|
|
|
r = rct;
|
|
xi_inflate_rect( &r, 1 );
|
|
if ( !cell_data->button_full_cell && ( !cell_data->button_on_focus
|
|
|| lm_row_has_focus( lmp, row, FALSE ) ) )
|
|
{
|
|
if ( cell_data->button_on_left )
|
|
{
|
|
r.right = r.left + lmp->pix_row_spacing;
|
|
rct.left = r.right;
|
|
}
|
|
else
|
|
{
|
|
r.left = r.right - lmp->pix_row_spacing;
|
|
rct.right = r.left - ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
}
|
|
}
|
|
}
|
|
#if XIWS != XIWS_WM
|
|
rct.top += RULE_Y_OFFSET_TOP;
|
|
rct.bottom -= RULE_Y_OFFSET_BOTTOM;
|
|
#endif
|
|
|
|
if ( column_data->column_well || column_data->column_platform )
|
|
{
|
|
rct.left++;
|
|
rct.right--;
|
|
}
|
|
*rctp = rct;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: redraw_cell
|
|
lm: current lm
|
|
row:
|
|
col:
|
|
update: if TRUE, redraw_cell is being called due to an XinEventPaint event.
|
|
clip_rct: clip rectangle
|
|
-------------------------------------------------------------------------*/
|
|
/*-------------------------------------------------------------------------*/
|
|
/* redraw_cell */
|
|
/*-------------------------------------------------------------------------*/
|
|
void
|
|
redraw_cell( LM lm, int row, int col, BOOLEAN update )
|
|
{
|
|
draw_cell_range( ( LM_DATA * ) lm, row, row, col, col, update );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_redraw_row */
|
|
/*-------------------------------------------------------------------------*/
|
|
void
|
|
lm_redraw_row( LM_DATA * lmp, int row, BOOLEAN update )
|
|
{
|
|
draw_cell_range( lmp, row, row, 0, lmp->nbr_columns - 1, update );
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
oevt: original xvt event, without virtual space coordinate conversions
|
|
rowp: if set, to be filled in with the results of the row hit test
|
|
columnp: if set, to be filled in with the results of the column hit test
|
|
is_vis: row is fully visible
|
|
is_part_vis:row is partially visible
|
|
returns: 0 - no hit
|
|
1 - hit
|
|
5 - hit on cell button
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_hit_test( LM lm, XinEvent * ep, XinEvent * oevt, int *rowp, int *columnp,
|
|
BOOLEAN * is_vis, BOOLEAN * is_hit, BOOLEAN * is_part_vis )
|
|
{
|
|
int row,
|
|
column,
|
|
temp,
|
|
col_offset,
|
|
tmp_v,
|
|
i,
|
|
first,
|
|
last;
|
|
int *pix_offsetsp,
|
|
*pix_heightsp;
|
|
LM_DATA *lmp = LMP( lm );
|
|
XinPoint where;
|
|
|
|
if ( is_vis )
|
|
*is_vis = TRUE;
|
|
if ( is_hit )
|
|
*is_hit = FALSE;
|
|
if ( is_part_vis )
|
|
*is_part_vis = FALSE;
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
where = ep->v.mouse.where;
|
|
|
|
/* if the mouse is to the left or the right of the list, return 0 */
|
|
if ( oevt->v.mouse.where.h < 0 )
|
|
return 0;
|
|
if ( lmp->pixel_width &&
|
|
( oevt->v.mouse.where.h > ( lmp->rct.left + lmp->pixel_width
|
|
+ BORDER_WIDTH ) ) )
|
|
return 0;
|
|
|
|
/* if the mouse is in the column headings */
|
|
if ( where.v > lmp->pix_top && where.v < lmp->pix_row1_top )
|
|
{
|
|
for ( column = 0; column < lmp->nbr_columns; column++ )
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos + col_offset;
|
|
if ( where.h >= temp && where.h < temp + column_data->pix_width )
|
|
{
|
|
*rowp = -1;
|
|
*columnp = column;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* if the mouse is above the list, return 0 */
|
|
if ( where.v < lmp->pix_row1_top )
|
|
return 0;
|
|
|
|
/* 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 ) )
|
|
{
|
|
row = i;
|
|
break;
|
|
}
|
|
}
|
|
if ( i > last )
|
|
{
|
|
if ( is_vis )
|
|
*is_vis = FALSE;
|
|
return 0;
|
|
}
|
|
if ( is_vis )
|
|
{
|
|
if ( i < lmp->first_fully_vis || i > lmp->last_fully_vis )
|
|
{
|
|
*is_vis = FALSE;
|
|
if ( ( i == lmp->last_fully_vis + 1 ) && ( ep->v.mouse.where.v < lmp->mlr.bottom ) )
|
|
{
|
|
if ( is_part_vis )
|
|
*is_part_vis = TRUE;
|
|
}
|
|
}
|
|
else
|
|
*is_vis = TRUE;
|
|
}
|
|
else if ( i < lmp->first_fully_vis || i > lmp->last_fully_vis )
|
|
return 0;
|
|
for ( column = 0; column < lmp->nbr_columns; column++ )
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos + col_offset;
|
|
if ( where.h >= temp && where.h < temp + column_data->pix_width )
|
|
{
|
|
if ( ( ( lmp->attrib & ( LM_ATR_ENABLED | LM_ATR_VISIBLE ) ) == ( LM_ATR_ENABLED | LM_ATR_VISIBLE ) )
|
|
&& ( lmp->lm_column_data[column]->attrib & ( LM_COL_ATR_ENABLED | LM_COL_ATR_SELECTABLE ) ) )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
*rowp = row;
|
|
*columnp = column;
|
|
if ( is_hit )
|
|
*is_hit = TRUE;
|
|
cell_data = &lmp->cell_data[row][column];
|
|
if ( cell_data->button )
|
|
{
|
|
XinRect outer_rct;
|
|
XinPoint p;
|
|
|
|
lm_get_cell_rect( &outer_rct, lm, row, column, FALSE, FALSE );
|
|
xi_inflate_rect( &outer_rct, 1 );
|
|
if ( !cell_data->button_full_cell )
|
|
{
|
|
if ( cell_data->button_on_left )
|
|
outer_rct.right = outer_rct.left + lmp->pix_row_spacing;
|
|
else
|
|
outer_rct.left = outer_rct.right - lmp->pix_row_spacing;
|
|
}
|
|
p = ep->v.mouse.where;
|
|
p.v = tmp_v;
|
|
if ( xi_pt_in_rect( &outer_rct, p ) )
|
|
{
|
|
return 5;
|
|
}
|
|
}
|
|
else if ( lm_focus_cell_has( lmp, row, column, FALSE ) )
|
|
{
|
|
XinRect outer_rct;
|
|
XinPoint p;
|
|
|
|
lm_get_cell_rect( &outer_rct, lm, row, column, FALSE, FALSE );
|
|
xi_inflate_rect( &outer_rct, 1 );
|
|
if ( cell_data->xi_text )
|
|
xi_text_rect_get_adjusted( cell_data->xi_text, &outer_rct );
|
|
p = ep->v.mouse.where;
|
|
p.v = tmp_v;
|
|
if ( !xi_pt_in_rect( &outer_rct, p ) )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
*rowp = row;
|
|
*columnp = column;
|
|
if ( is_hit )
|
|
*is_hit = TRUE;
|
|
if ( is_part_vis )
|
|
*is_part_vis = FALSE;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if ( is_part_vis )
|
|
*is_part_vis = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_font
|
|
lm: current lm
|
|
part: must be LM_COLUMN, or LM_CELL
|
|
idx: column number
|
|
idx2: if LM_CELL, row number
|
|
font: font to set
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_font( LM lm, LM_PART part, int idx, int idx2, XinFont * font )
|
|
{
|
|
LM_DATA *lmp = LMP( lm );
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
switch ( part )
|
|
{
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *lmcd;
|
|
XinRect rct;
|
|
|
|
lmcd = lmp->lm_column_data[idx];
|
|
if ( lmcd->font )
|
|
XinFontDestroy( lmcd->font );
|
|
if ( font )
|
|
XinFontCopy( &lmcd->font, font );
|
|
else
|
|
lmcd->font = NULL;
|
|
lm_get_rect( lm, LM_COLUMN, idx, &rct );
|
|
lm_invalidate_rect( lmp, &rct, TRUE );
|
|
break;
|
|
}
|
|
case LM_CELL:
|
|
{
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if ( cell_data->font )
|
|
XinFontDestroy( cell_data->font );
|
|
if ( font )
|
|
XinFontCopy( &cell_data->font, font );
|
|
else
|
|
cell_data->font = NULL;
|
|
if ( cell_data->font != NULL )
|
|
XinWindowFontMap( lmp->win, cell_data->font );
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* LM drawing functions */
|
|
|
|
#if 0
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_clip
|
|
lmp: current lmp
|
|
rctp: clipping rectangle
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_set_clip( LM_DATA * lmp, XinRect * rctp )
|
|
{
|
|
XinRect r;
|
|
|
|
r = *rctp;
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
lm_adj_h( lmp, &r.left );
|
|
lm_adj_h( lmp, &r.right );
|
|
|
|
xi_set_clip( lmp->win, &r );
|
|
}
|
|
|
|
#endif
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_text
|
|
lmp: current lmp
|
|
h: h position
|
|
v: v position
|
|
s: string
|
|
len: length of string
|
|
-------------------------------------------------------------------------*/
|
|
#if XIWS == XIWS_WM
|
|
static void
|
|
lm_draw_text( LM_DATA * lmp, int h, int v, char *s, int len )
|
|
{
|
|
short sh;
|
|
|
|
sh = h;
|
|
sh += lmp->rct.left;
|
|
if ( lm_adj_h( lmp, &sh ) )
|
|
{
|
|
lm_adj_v( lmp, v );
|
|
xi_draw_text( lmp->win, sh, v, s, len );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
Make it so a row can have the focus.
|
|
Tab will move focus to a cell in the row, if there is a cell in the row
|
|
that can take focus.
|
|
If XI_ATR_SELECTABLE is set for any columns, space will select the
|
|
row.
|
|
Up arrow and down arrow work. If the focus is on a cell, the focus stays
|
|
on a cell. If the focus is on a row, the focus stays on a row.
|
|
Page up and down should work.
|
|
If the focus is on the last editable cell, and tab_wrap is set, then the
|
|
focus moves to the next row.
|
|
If the focus is
|
|
the focus move to the current row.
|
|
Have an option on a list by list basis, enter selects if a row has the
|
|
focus. Enter will act like a double click selection.
|
|
If the row focus option is set, put up the other hand cursor.
|
|
|
|
possibly revisit how text is stored in cells - may want indefinite buffer
|
|
size for a column.
|
|
when entering text in a cell, continually evaluate the correct height of
|
|
the cell. The function to recalc number of rows and break points should
|
|
compare line by line, until there is a difference, then do detailed
|
|
comparison after the difference.
|
|
it should be possible to scroll the list backwards to gain more room above
|
|
if the cell is at the bottom of the list
|
|
if the cell is already the maximum possible height, then not necessary to
|
|
do any more comparisons
|
|
limit text edit to buffer size
|
|
make sure that the clipboard works
|
|
|
|
TODO in the future
|
|
------------------
|
|
if height is 0, make the list height be the same as the window height
|
|
expose lm drawing functions
|
|
xi_set_icon for buttons
|
|
make an option so that when the user tabs to an edit control that already contains text, the
|
|
insertion point is set to the right of the text.
|
|
settable background color for text on a 3d radio button or check box, (tab buttons also)
|
|
make function xi_is_nav_char
|
|
make readonly cells
|
|
need colors for static text
|
|
want ability on XVT/CH to have single character fields. Eliminate the [ and ].
|
|
*/
|
|
|
|
void
|
|
set_focus_cell_rct( LM_DATA * lmp, int row, int col, BOOLEAN in_update_event )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
LM_COLUMN_DATA *column_data;
|
|
int leading,
|
|
ascent,
|
|
descent;
|
|
int col_offset;
|
|
XinRect rct;
|
|
XinRect mlr = lmp->mlr;
|
|
|
|
col_offset = ( int ) xi_get_pref( XI_PREF_COLUMN_OFFSET );
|
|
|
|
cell_data = &lmp->cell_data[row][col];
|
|
column_data = lmp->lm_column_data[col];
|
|
|
|
if ( cell_data->font )
|
|
XinFontMetricsGet( cell_data->font, &leading, &ascent, &descent );
|
|
else
|
|
XinFontMetricsGet( lmp->font, &leading, &ascent, &descent );
|
|
|
|
lm_xi_text_prect_get( lmp, column_data, cell_data, row, col, col_offset, leading,
|
|
ascent, descent, &rct );
|
|
xi_text_prect_set( cell_data->xi_text, &rct );
|
|
if ( lmp->pixel_width )
|
|
mlr.right = mlr.left + lmp->pixel_width;
|
|
xi_text_clip_set( cell_data->xi_text, &mlr );
|
|
if ( xi_text_editing_is( cell_data->xi_text ) )
|
|
xi_text_draw( cell_data->xi_text, 0L, 0L, in_update_event );
|
|
}
|
|
|
|
XI_TEXT *
|
|
lm_xi_text_focus_get( LM lm )
|
|
{
|
|
LM_DATA *lmp = ( LM_DATA * ) lm;
|
|
int row,
|
|
col;
|
|
BOOLEAN is_vert;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if ( !lm_focus_cell_get( lmp, &row, &col, &is_vert ) )
|
|
return NULL;
|
|
if ( is_vert )
|
|
return NULL;
|
|
cell_data = &( lmp->cell_data[row][col] );
|
|
return cell_data->xi_text;
|
|
}
|