Files : Aggiunto il simbolo wxGTK per Linux git-svn-id: svn://10.65.10.50/trunk@12157 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, 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 );
 | |
| 
 | |
| }
 |