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