campo-sirio/xi/xilm.c
alex fa53273fe0 Patch level : 2.0 nopatch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
Compilazione Linux


git-svn-id: svn://10.65.10.50/trunk@11220 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-06-06 13:50:22 +00:00

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