/******************************************************************************* * 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 #define XI_R3_COMPAT #include "xi.h" #include "xitext.h" #include "xistx.h" #include "xilm.h" #include "xilmst.h" #include "xiutils.h" #include "xi_int.h" #if XIWS == XIWS_XM #include #include #endif #if XIWS == XIWS_WM #define BORDER_WIDTH 8 #define EDIT_BORDER_WIDTH_Y 0 #define EDIT_BORDER_SPACE_Y 0 #else #define BORDER_WIDTH 2 #define EDIT_BORDER_WIDTH_Y 1 #define EDIT_BORDER_SPACE_Y 1 #endif /******************************* STATIC DATA ********************************/ typedef struct s_xi_interface_create_data { XinRect rct; XI_OBJ_DEF *obj_def; XI_OBJ *itf; } XI_INTERFACE_CREATE_DATA; static XI_EQ *xi_eq; static BOOLEAN inited = FALSE; static XI_WINDOW_LIST *xi_window_list; static char *list_parent; extern XinWindow xi_modal_win; BOOLEAN xi_in_modal_wait_create = FALSE; static XI_INTERFACE_CREATE_DATA interface_create_data; XI_OBJ *xi_creating_itf = NULL; /******************************** FUNCTIONS *********************************/ BOOLEAN xi_compare_objs( XI_OBJ * obj_one, XI_OBJ * obj_two ) { if ( obj_one == obj_two ) return ( TRUE ); if ( obj_two != NULL && obj_two->type == XIT_CELL && obj_one != NULL && obj_one->type == XIT_CELL && obj_two->parent == obj_one->parent ) { XI_CELL_DATA *cell_one_cell_data = &obj_one->v.cell; XI_CELL_DATA *cell_two_cell_data = &obj_two->v.cell; return cell_one_cell_data->row == cell_two_cell_data->row && cell_one_cell_data->column == cell_two_cell_data->column && cell_one_cell_data->is_vert_scrolled == cell_two_cell_data->is_vert_scrolled; } return FALSE; } static XI_OBJ * get_non_focus_cell_obj( XI_LIST_DATA * list_data ) { int i; for ( i = 0; i < FOCUS_CELL_ARRAY_LEN; ++i ) if ( list_data->focus_cell == &list_data->focus_cell_array[i] ) break; i = ( i + 1 ) % FOCUS_CELL_ARRAY_LEN; return &list_data->focus_cell_array[i]; } XI_OBJ * xi_search_itf( XI_OBJ * xi_obj, XI_SEARCH_TYPE search_type, int parm1 ) { XI_OBJ *obj; XI_OBJ **objp; int i, column, tab_cid; unsigned long attrib; XI_OBJ *cell_obj; XI_LIST_DATA *list_data; LM lm; switch ( search_type ) { case XI_SEARCH_FOR_FOCUSABLE: switch ( xi_obj->type ) { case XIT_LIST: lm = xi_obj->v.list->lm; attrib = lm_get_attrib( lm, LM_LIST, 0, 0, FALSE ); if ( ( attrib & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) != ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) return NULL; return ( xi_obj ); case XIT_CELL: return ( xi_obj ); case XIT_COLUMN: lm = xi_obj->parent->v.list->lm; attrib = lm_get_attrib( lm, LM_LIST, 0, 0, FALSE ); if ( ( attrib & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) != ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) return NULL; column = xi_obj_to_idx( xi_obj ); attrib = lm_get_attrib( lm, LM_COLUMN, column, 0, FALSE ); if ( ( attrib & ( XI_ATR_ENABLED | XI_ATR_SELECTABLE | XI_ATR_VISIBLE ) ) != ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) return NULL; else { list_data = xi_obj->parent->v.list; cell_obj = get_non_focus_cell_obj( list_data ); cell_obj->v.cell.row = 0; cell_obj->v.cell.column = ( unsigned char ) column; return ( cell_obj ); } case XIT_FIELD: attrib = stx_get_attrib( xi_obj->v.field->stx ); if ( ( attrib & XI_ATR_ENABLED ) != 0 && ( attrib & XI_ATR_VISIBLE ) != 0 ) return ( xi_obj ); else return NULL; case XIT_BTN: #if XIWS == XIWS_MAC if ( xi_get_native_controls( xi_obj ) ) return NULL; #endif { unsigned long attrib; attrib = xi_obj->v.btn->attrib; if ( ( attrib & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) return xi_obj; else return NULL; } case XIT_GROUP: return NULL; default: break; } break; case XI_SEARCH_FOR_TAB_CID: switch ( xi_obj->type ) { case XIT_FIELD: tab_cid = xi_obj->v.field->tab_cid; break; case XIT_BTN: tab_cid = xi_obj->v.btn->tab_cid; break; case XIT_FORM: tab_cid = xi_obj->v.form->tab_cid; break; case XIT_CONTAINER: tab_cid = xi_obj->v.container->tab_cid; break; case XIT_LIST: tab_cid = xi_obj->v.list->tab_cid; break; default: tab_cid = -1; break; } if ( tab_cid == parm1 ) return xi_obj; break; case XI_SEARCH_FOR_FIELD: if ( xi_obj->type == XIT_FIELD ) return xi_obj; break; case XI_SEARCH_FOR_INITIAL: if (xi_obj->type == XIT_ITF && xi_obj->v.itf->initial_focus_cid != 0) { XI_OBJ *new_obj = xi_get_obj( xi_obj, xi_obj->v.itf->initial_focus_cid ); if ( ( xi_get_attrib( new_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) return new_obj; } return xi_search_itf( xi_obj, XI_SEARCH_FOR_FOCUSABLE, parm1 ); default: XinError( 20002, XinSeverityFatal, 0L ); } /* search child list */ objp = xi_obj->children; obj = NULL; for ( i = xi_obj->nbr_children; i > 0 && obj == NULL; i--, objp++ ) obj = xi_search_itf( *objp, search_type, parm1 ); return obj; } static void xi_remove_from_parent_list( XI_OBJ * xi_obj ) { XI_OBJ *parent; XI_OBJ **list; int n; BOOLEAN copying_down = FALSE; if ( ( parent = xi_obj->parent ) == NULL ) return; list = parent->children; n = parent->nbr_children; for ( ; n > 0; n--, list++ ) { if ( copying_down ) list[-1] = *list; if ( *list == xi_obj ) copying_down = TRUE; } /* error if we did not find the child in the list */ if ( !copying_down ) XinError( 20001, XinSeverityFatal, 0L ); parent->nbr_children--; } /* xi_find_next_obj: find the next control in the tabbing sequence. The focus_obj parameter indicates the object that currently has the focus. The type of navigation is given by the tab_type parameter. */ XI_OBJ * xi_find_next_obj( XI_OBJ * focus_obj, XI_NEXT_TYPE tab_type, long c ) { XI_OBJ_TYPE type; XI_OBJ *itf, *obj = NULL; int tab_cid = 0; if ( focus_obj == NULL || focus_obj->type == XIT_ITF ) { /* find the first thing on the interface */ return ( xi_search_itf( focus_obj->itf, XI_SEARCH_FOR_FOCUSABLE, 0 ) ); } type = focus_obj->type; itf = focus_obj->itf; switch ( tab_type ) { case XI_NEXT_FORM_TAB: case XI_NEXT_ITF_TAB: switch ( tab_type ) { case XI_NEXT_FORM_TAB: if ( type == XIT_FORM ) return ( xi_search_itf( itf, XI_SEARCH_FOR_FIELD, 0 ) ); obj = focus_obj; break; case XI_NEXT_ITF_TAB: obj = focus_obj->parent; if ( obj->type == XIT_ITF ) /* No container, ignore it */ return NULL; break; default: break; } while ( TRUE ) { switch ( obj->type ) { case XIT_FIELD: tab_cid = obj->v.field->tab_cid; break; case XIT_BTN: tab_cid = obj->v.btn->tab_cid; break; case XIT_FORM: tab_cid = obj->v.form->tab_cid; break; case XIT_LIST: tab_cid = obj->v.list->tab_cid; break; case XIT_CONTAINER: tab_cid = obj->v.container->tab_cid; break; case XIT_COLUMN: tab_cid = obj->cid + 1; break; default: XinError( 20003, XinSeverityFatal, 0L ); break; } obj = xi_get_obj( itf, tab_cid ); if ( obj == NULL || obj == focus_obj ) break; #if XIWS == XIWS_MAC if ( xi_get_native_controls( obj ) && ( obj->type == XIT_BTN || obj->type == XIT_CONTAINER ) ) continue; #endif if ( ( xi_get_attrib( obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) != ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) continue; if ( obj->type == XIT_LIST ) { int i, nbr_members; XI_OBJ **members; BOOLEAN have_column; members = xi_get_member_list( obj, &nbr_members ); have_column = FALSE; for ( i = 0; i < nbr_members; ++i ) { unsigned long attrib; attrib = xi_get_attrib( members[i] ); if ( ( attrib & XI_ATR_ENABLED ) && !( attrib & XI_ATR_SELECTABLE ) ) { have_column = TRUE; break; } } if ( !have_column ) continue; } /* If the tab key was pressed, and the focus is not on the first * enabled and visible radio button in the group, then skip to a * control that is not in the group. */ { XI_OBJ **rb_obj, *parent; int i; if ( c != XI_KEY_DOWN && obj->type == XIT_BTN && obj->v.btn->type == XIBT_RADIOBTN && obj->parent->type == XIT_CONTAINER ) { parent = obj->parent; for ( i = 0, rb_obj = parent->children; i < parent->nbr_children; ++i, ++rb_obj ) if ( ( xi_get_attrib( *rb_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) break; if ( *rb_obj != obj ) continue; } } /* If a meta-tab key was pressed, and the obj->type == XIT_FORM then * move the focus to the first field in the form */ if ( obj->type == XIT_FORM ) { XI_OBJ **field_obj; int i; for ( i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj ) if ( ( xi_get_attrib( *field_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) break; if ( i == obj->nbr_children ) continue; obj = *field_obj; } break; } return ( obj ); case XI_NEXT_FORM_BACKTAB: case XI_NEXT_ITF_BACKTAB: switch ( tab_type ) { case XI_NEXT_FORM_BACKTAB: if ( type == XIT_FORM ) return ( xi_search_itf( itf, XI_SEARCH_FOR_FIELD, 0 ) ); obj = focus_obj; break; case XI_NEXT_ITF_BACKTAB: obj = focus_obj->parent; if ( obj->type == XIT_ITF ) /* No container, ignore it */ return NULL; break; default: break; } while ( TRUE ) { /* xi_search_itf, searching for TAB CID finds the tab control id just * previous in the tabbing sequence, hence the break at the bottom of * the loop. */ obj = xi_search_itf( itf, XI_SEARCH_FOR_TAB_CID, obj->cid ); if ( obj == NULL || obj == focus_obj ) break; #if XIWS == XIWS_MAC if ( xi_get_native_controls( obj ) && ( obj->type == XIT_BTN || obj->type == XIT_CONTAINER ) ) continue; #endif if ( ( xi_get_attrib( obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) != ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) continue; if ( obj->type == XIT_LIST ) { int i, nbr_members; XI_OBJ **members; BOOLEAN have_column; members = xi_get_member_list( obj, &nbr_members ); have_column = FALSE; for ( i = 0; i < nbr_members; ++i ) { unsigned long attrib; attrib = xi_get_attrib( members[i] ); if ( ( attrib & XI_ATR_ENABLED ) && !( attrib & XI_ATR_SELECTABLE ) ) { have_column = TRUE; break; } } if ( !have_column ) continue; } /* If a meta-tab key was pressed, and the obj->type == XIT_FORM then * move the focus to the first field in the form */ if ( obj->type == XIT_FORM ) { XI_OBJ **field_obj; int i; for ( i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj ) if ( ( xi_get_attrib( *field_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) break; if ( i == obj->nbr_children ) continue; obj = *field_obj; } break; } if ( obj && c != XI_KEY_UP && obj->type == XIT_BTN && obj->v.btn->type == XIBT_RADIOBTN && obj->parent->type == XIT_CONTAINER && obj->parent->children[0] != obj ) { obj = obj->parent->children[0]; while ( TRUE ) { if ( ( xi_get_attrib( obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) break; obj = xi_search_itf( itf, XI_SEARCH_FOR_TAB_CID, obj->cid ); } } return ( obj ); } return NULL; } void xi_aga_field_set_caret_pos( XI_OBJ * xi_obj, int pos ) { if ( xi_obj->type == XIT_FIELD ) { STX_DATA *stxp = ( STX_DATA * ) xi_obj->v.field->stx; xi_text_selection_set( stxp->xi_text, pos, pos ); } } /* xi_lowlevel_focus: inform a control that it is gaining or losing the focus. A control may reset some internal state when this happens. This is not refusable. */ void xi_lowlevel_focus( XI_OBJ * xi_obj, BOOLEAN set ) { XI_OBJ *itf; XinWindow win; BOOLEAN native_controls = xi_get_native_controls( xi_obj ); itf = xi_obj->itf; win = itf->v.itf->xin_win; if ( native_controls ) { if ( set && xi_obj->type != XIT_BTN ) /* should be set, not ! set */ if ( XinWindowFocusGet( ) == win ) /* should be ==, not != */ XinWindowFocusSet( win ); } switch ( xi_obj->type ) { case XIT_CELL: lm_focus_set( xi_obj->parent->v.list->lm, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, set ); return; case XIT_FIELD: stx_focus_set( xi_obj->v.field->stx, set ); break; case XIT_BTN: { XI_BTN_DATA *bd; bd = xi_obj->v.btn; if ( !native_controls ) { xi_invalidate_rect( win, &bd->rct ); } else { if ( set ) XinWindowFocusSet( bd->btnctl ); } break; } default: /* ignore */ break; } } /* is_group_member: given an object, determine if it is in a group. */ static BOOLEAN is_group_member( XI_OBJ * obj, XI_OBJ * group ) { int *cidlist; int i; cidlist = group->v.group->cidlist; for ( i = group->v.group->nbr_cids; i > 0; i--, cidlist++ ) { if ( *cidlist == obj->cid ) return ( TRUE ); } return ( FALSE ); } BOOLEAN xi_is_focus_moving( XI_OBJ * xi_obj ) { XI_OBJ *itf = xi_obj->itf; return itf->v.itf->moving_focus; } /* ----------------------------------------------------------------------- */ /* lm_list_is_about_to_lose_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN lm_list_is_about_to_lose_focus( LM_DATA * lmp ) { if ( lm_focus_list_has( lmp ) && ( lm_focus_state_get( lmp ) == LM_FOCUS_VERTICALLY_SCROLLED ) ) { lm_focus_create_temp_row( lmp ); return TRUE; } return FALSE; } /* ----------------------------------------------------------------------- */ /* lm_list_did_lose_focus */ /* ----------------------------------------------------------------------- */ static void lm_list_did_lose_focus( LM_DATA * lmp ) { lm_focus_rec_free( lmp ); } /* ----------------------------------------------------------------------- */ /* lm_list_did_not_lose_focus */ /* ----------------------------------------------------------------------- */ static void lm_list_did_not_lose_focus( LM_DATA * lmp ) { lm_allocate_rec_info( lmp, lmp->realized_rows_array_len - 1 ); --lmp->nbr_realized_rows; lm_focus_rec_set( lmp, lm_focus_rec_saved_get( lmp ) ); } /* ----------------------------------------------------------------------- */ /* send focus event */ /* ----------------------------------------------------------------------- */ static BOOLEAN send_object_event( XI_OBJ * object, XI_EVENT_TYPE event_type ) { XI_EVENT xiev; MEMCLEAR( xiev ); xiev.type = event_type; xiev.v.xi_obj = object; call_cb( object->itf, &xiev ); return !xiev.refused; } /* ----------------------------------------------------------------------- */ /* move_focus_off_groups */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_group_focus( XI_OBJ * primary_obj, XI_OBJ * secondary_obj, XI_OBJ * itf, XI_EVENT_TYPE event_type, BOOLEAN primary_is_cell ) { XI_OBJ **objp; int i; BOOLEAN moving_between_rows = FALSE; if ( primary_obj == NULL || (!primary_is_cell && !xi_is_obj( primary_obj, itf ))) return TRUE; if ( secondary_obj != NULL && secondary_obj->type == XIT_CELL ) { if ( primary_obj->type == XIT_CELL ) moving_between_rows = ( primary_obj->v.cell.row != secondary_obj->v.cell.row ); secondary_obj = secondary_obj->parent->children[ secondary_obj->v.cell.column]; } if ( primary_obj->type == XIT_CELL ) primary_obj = primary_obj->parent->children[primary_obj->v.cell.column]; objp = primary_obj->itf->children; for ( i = primary_obj->itf->nbr_children; i > 0; i--, objp++ ) { XI_OBJ *obj; obj = *objp; if ( obj->type == XIT_GROUP && is_group_member( primary_obj, obj ) && ( secondary_obj == NULL || !is_group_member( secondary_obj, obj ) || moving_between_rows ) ) if ( !send_object_event( obj, event_type ) ) return FALSE; } return TRUE; } /* ----------------------------------------------------------------------- */ /* move_off_column */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_off_column( XI_OBJ * old_focus, XI_OBJ * new_focus ) { if ( new_focus != NULL && new_focus->type == XIT_CELL && old_focus->v.cell.column == new_focus->v.cell.column ) return TRUE; old_focus = old_focus->parent->children[old_focus->v.cell.column]; return send_object_event( old_focus, XIE_OFF_COLUMN ); } /* ----------------------------------------------------------------------- */ /* move_off_row */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_row_focus( XI_OBJ * primary_obj, XI_OBJ * secondary_obj, XI_EVENT_TYPE event_type ) { XI_OBJ row_obj; /* move off of row */ if ( secondary_obj != NULL && secondary_obj->type == XIT_CELL && primary_obj->v.cell.row == secondary_obj->v.cell.row && primary_obj->parent == secondary_obj->parent ) return TRUE; XI_MAKE_ROW( &row_obj, primary_obj->parent, primary_obj->v.cell.row ); row_obj.v.row_data.is_vert_scrolled = primary_obj->v.cell.is_vert_scrolled; if ( !send_object_event( &row_obj, event_type ) ) return FALSE; return TRUE; } /* ----------------------------------------------------------------------- */ /* move_on_column */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_on_column( XI_OBJ * old_focus, XI_OBJ * new_focus ) { if ( old_focus != NULL && old_focus->type == XIT_CELL && old_focus->parent == new_focus->parent && old_focus->v.cell.column == new_focus->v.cell.column ) return TRUE; new_focus = new_focus->parent->children[new_focus->v.cell.column]; return send_object_event( new_focus, XIE_ON_COLUMN ); } /* ----------------------------------------------------------------------- */ /* same_parents */ /* ----------------------------------------------------------------------- */ static BOOLEAN same_parents( XI_OBJ * one, XI_OBJ * two ) { if ( one != NULL && one->type != XIT_LIST && one->type != XIT_FORM ) one = one->parent; if ( two != NULL && two->type != XIT_LIST && two->type != XIT_FORM ) two = two->parent; return one == two; } /* ----------------------------------------------------------------------- */ /* gen_remove_focus_events */ /* ----------------------------------------------------------------------- */ static BOOLEAN gen_remove_focus_events( XI_OBJ * old_focus, XI_OBJ * new_focus ) { XI_OBJ * itf; BOOLEAN old_is_cell = (old_focus != NULL && old_focus->type == XIT_CELL); /* move off old 1st-level object */ if ( old_focus == NULL ) return TRUE; itf = old_focus->itf; switch ( old_focus->type ) { case XIT_CELL: if ( !send_object_event( old_focus, XIE_OFF_CELL ) || !move_off_column( old_focus, new_focus ) || !move_group_focus( old_focus, new_focus, itf, XIE_OFF_GROUP, old_is_cell ) || !move_row_focus( old_focus, new_focus, XIE_OFF_ROW ) ) return FALSE; if ( !same_parents( old_focus, new_focus ) ) return send_object_event( old_focus->parent, XIE_OFF_LIST ); break; case XIT_LIST: return ( move_group_focus( old_focus, new_focus, itf, XIE_OFF_GROUP, old_is_cell ) && ( same_parents( old_focus, new_focus ) || send_object_event( old_focus, XIE_OFF_LIST ) ) ); case XIT_FIELD: if ( !send_object_event( old_focus, XIE_OFF_FIELD ) || !move_group_focus( old_focus, new_focus, itf, XIE_OFF_GROUP, old_is_cell ) ) return FALSE; if ( xi_is_obj( old_focus, itf ) && old_focus->parent != new_focus->parent ) return send_object_event( old_focus->parent, XIE_OFF_FORM ); break; default: return move_group_focus( old_focus, new_focus, itf, XIE_OFF_GROUP, old_is_cell ); } return TRUE; } /* ----------------------------------------------------------------------- */ /* gen_place_focus_events */ /* ----------------------------------------------------------------------- */ static BOOLEAN gen_place_focus_events( XI_OBJ * old_focus, XI_OBJ * new_focus, BOOLEAN old_is_cell ) { XI_OBJ * itf; if ( new_focus == NULL ) return TRUE; if ( old_focus != NULL ) itf = old_focus->itf; else itf = new_focus->itf; switch ( new_focus->type ) { case XIT_CELL: if ( !same_parents( old_focus, new_focus ) && !send_object_event( new_focus->parent, XIE_ON_LIST ) ) return FALSE; return ( move_row_focus( new_focus, old_focus, XIE_ON_ROW ) && move_group_focus( new_focus, old_focus, itf, XIE_ON_GROUP, old_is_cell ) && move_on_column( old_focus, new_focus ) && send_object_event( new_focus, XIE_ON_CELL ) ); case XIT_LIST: return ( ( same_parents( old_focus, new_focus ) || send_object_event( new_focus, XIE_ON_LIST ) ) && move_group_focus( new_focus, old_focus, itf, XIE_ON_GROUP, old_is_cell ) ); case XIT_FIELD: if ( ( old_focus == NULL || new_focus->parent != old_focus->parent ) && !send_object_event( new_focus->parent, XIE_ON_FORM ) ) return FALSE; return ( move_group_focus( new_focus, old_focus, itf, XIE_ON_GROUP, old_is_cell ) && send_object_event( new_focus, XIE_ON_FIELD ) ); default: break; } return move_group_focus( new_focus, old_focus, itf, XIE_ON_GROUP, old_is_cell ); } /* ----------------------------------------------------------------------- */ /* find_cell_obj */ /* ----------------------------------------------------------------------- */ static XI_OBJ * find_cell_obj( XI_OBJ * new_focus ) { LM_DATA *lmp; XI_OBJ tmp_obj; XI_LIST_DATA *list_data; list_data = new_focus->parent->v.list; lmp = ( LM_DATA * ) list_data->lm; tmp_obj = *new_focus; new_focus = get_non_focus_cell_obj( tmp_obj.parent->v.list ); new_focus->v.cell.row = tmp_obj.v.cell.row; new_focus->v.cell.column = tmp_obj.v.cell.column; if ( new_focus->v.cell.row >= ( unsigned char ) lmp->nbr_realized_rows ) return new_focus->itf; return new_focus; } /* ----------------------------------------------------------------------- */ /* move_focus_to_list */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_focus_to_list( XI_OBJ ** focus_result ) { LM_DATA *lmp; int col; XI_OBJ *new_focus; XI_LIST_DATA *list_data; int first_col; int last_col; int start_col; new_focus = *focus_result; list_data = new_focus->v.list; lmp = ( LM_DATA * ) list_data->lm; if ( new_focus->nbr_children <= 0 ) return FALSE; if ( lmp->sizing_row ) return FALSE; if ( lmp->nbr_realized_rows == 0 ) { *focus_result = new_focus->itf; return TRUE; } if ( lmp->single_select ) /* attempt to select row */ return TRUE; new_focus = list_data->focus_cell; /* if cell is selectable, disabled, etc, then find another cell */ if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE ) start_col = new_focus->v.cell.column; else start_col = 0; col = start_col; lm_get_visible_columns( list_data->lm, &first_col, &last_col ); while ( TRUE ) { long attrib; attrib = lmp->lm_column_data[col]->attrib; if ( ( attrib & XI_ATR_ENABLED ) && !( attrib & XI_ATR_SELECTABLE ) && ( col < lm_get_fixed_columns( list_data->lm ) || (col >= first_col && col <= last_col ))) { new_focus->v.cell.column = ( unsigned char ) col; break; } col++; if ( col == lmp->nbr_columns ) col = 0; if ( col == start_col ) { *focus_result = new_focus->itf; return TRUE; } } if ( new_focus->v.cell.row >= ( unsigned char ) lmp->nbr_realized_rows ) { if ( new_focus->type == XIT_CELL ) { /* Last row had focus, but has been deleted. Set focus to new last row, * if there is one */ if ( lmp->nbr_realized_rows >= 1 ) new_focus->v.cell.row = lmp->nbr_realized_rows - 1; else new_focus = xi_find_next_obj( new_focus->parent, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR ); } else new_focus = new_focus->itf; } *focus_result = new_focus; return TRUE; } /* ----------------------------------------------------------------------- */ /* determine_focus_button */ /* ----------------------------------------------------------------------- */ static XI_OBJ * determine_focus_button( XI_OBJ * new_focus ) { int i; unsigned long attr = 0L; if ( !new_focus->nbr_children ) XinError( 20005, XinSeverityFatal, 0L ); for ( i = 0; i < new_focus->nbr_children; i++ ) { attr = xi_get_attrib( new_focus->children[i] ); if ( ( attr & XI_ATR_ENABLED ) && ( attr & XI_ATR_VISIBLE ) ) return new_focus->children[i]; } return xi_find_next_obj( new_focus, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR ); } /* ----------------------------------------------------------------------- */ /* determine_new_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN determine_new_focus( XI_OBJ ** new_focus ) { if ( *new_focus == NULL ) return TRUE; do { switch ( ( *new_focus )->type ) { case XIT_CELL: *new_focus = find_cell_obj( *new_focus ); break; case XIT_LIST: return move_focus_to_list( new_focus ); case XIT_FORM: { XI_OBJ *focus_field = ( *new_focus )->v.form->focus_field; if ( focus_field ) *new_focus = focus_field; break; } case XIT_CONTAINER: *new_focus = determine_focus_button( *new_focus ); break; default: break; } } while ( *new_focus != NULL && ( ( *new_focus )->type == XIT_CONTAINER || ( *new_focus )->type == XIT_FORM || ( *new_focus )->type == XIT_LIST ) ); if ( *new_focus == NULL ) return FALSE; return TRUE; } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ static void check_new_focus_enabled( XI_OBJ * xi_obj ) { if ( xi_obj == NULL ) return; switch ( xi_obj->type ) { case XIT_CELL: { BOOLEAN xi_obj_enabled; xi_obj_enabled = ( ( xi_get_attrib( xi_obj->parent ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ); if ( !xi_obj_enabled ) XinError( 20006, XinSeverityFatal, 0L ); break; } case XIT_BTN: case XIT_FIELD: case XIT_LIST: { BOOLEAN xi_obj_enabled; xi_obj_enabled = ( ( xi_get_attrib( xi_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ); if ( !xi_obj_enabled ) XinError( 20007, XinSeverityFatal, 0L ); break; } default: break; } } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ static BOOLEAN determine_alternate_focus( XI_OBJ * old_focus, XI_OBJ ** new_focus, XI_OBJ * itf, BOOLEAN next_if_disabled, int check_for_reenabled, BOOLEAN old_is_cell, BOOLEAN new_is_cell) { XI_OBJ *xi_obj; if (!new_is_cell && !xi_is_obj( *new_focus, itf )) { /* Former new focus deleted. We're guessing, now. */ if (!old_is_cell && !xi_is_obj( old_focus, itf )) { /* Both objects deleted. Find first available obj in itf. */ *new_focus = itf; } else { /* Find next obj from old_focus. */ *new_focus = xi_find_next_obj( old_focus, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR ); } } xi_obj = *new_focus; /* if field for new focus has been disabled, proceed with next field */ if ( xi_obj->type != XIT_CELL && xi_obj->type != XIT_ITF ) { unsigned long attrib; attrib = xi_get_attrib( xi_obj ); if ( !( attrib & XI_ATR_ENABLED ) ) { if ( next_if_disabled ) xi_obj = xi_find_next_obj( xi_obj, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR ); else return FALSE; } } /* if next field used to be disabled, and is not enabled, move to it */ if ( check_for_reenabled && (old_is_cell || xi_is_obj( old_focus, itf ))) { if ( xi_obj->type == XIT_FIELD ) { XI_OBJ *tmp_obj; tmp_obj = xi_find_next_obj( old_focus, check_for_reenabled == 1 ? XI_NEXT_FORM_TAB : XI_NEXT_FORM_BACKTAB, check_for_reenabled == 1 ? xi_get_pref( XI_PREF_FORM_TAB_CHAR ) : xi_get_pref( XI_PREF_FORM_BACKTAB_CHAR ) ); if ( tmp_obj ) xi_obj = tmp_obj; } } if ( xi_obj->type == XIT_CELL ) { LM_DATA *lmp; lmp = (LM_DATA *)xi_obj->parent->v.list->lm; if ( lmp->nbr_realized_rows == 0 ) { *new_focus = xi_obj->itf; return TRUE; } else { if ( xi_obj->v.cell.row > lmp->nbr_realized_rows - 1 ) xi_obj->v.cell.row = lmp->nbr_realized_rows - 1; } } *new_focus = xi_obj; return TRUE; } /* ----------------------------------------------------------------------- */ /* perform_move_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN perform_move_focus( XI_OBJ * old_focus, XI_OBJ * new_focus, BOOLEAN make_callbacks, BOOLEAN next_if_disabled, int check_for_reenabled ) { BOOLEAN draw_old_row; BOOLEAN draw_new_row; BOOLEAN old_is_cell = (old_focus != NULL && old_focus->type == XIT_CELL); BOOLEAN new_is_cell; XI_OBJ* itf; itf = new_focus->itf; if ( !determine_new_focus( &new_focus ) ) return FALSE; check_new_focus_enabled( new_focus ); /* remove focus */ if ( make_callbacks && !gen_remove_focus_events( old_focus, new_focus ) ) return FALSE; new_is_cell = (new_focus != NULL && new_focus->type == XIT_CELL); if ( !determine_alternate_focus( old_focus, &new_focus, itf, next_if_disabled, check_for_reenabled, old_is_cell, new_is_cell ) ) return FALSE; if ( make_callbacks && !gen_place_focus_events( old_focus, new_focus, old_is_cell ) ) return FALSE; /* if list has focus, it's a single-select list */ if ( new_focus != NULL && new_focus->type == XIT_LIST ) { unsigned long attrib; XI_OBJ row_obj; XI_LIST_DATA *list_data = new_focus->v.list; LM_DATA *lmp = ( LM_DATA * ) list_data->lm; int row = list_data->focus_cell->v.cell.row; /* See if the focus row is selected. */ if ( row >= lmp->nbr_realized_rows ) row = lmp->nbr_realized_rows - 1; XI_MAKE_ROW( &row_obj, new_focus, row ); attrib = xi_get_attrib( &row_obj ); /* If it isn't, see if any row is selected. */ if ( ( attrib & XI_ATR_SELECTED ) == 0 ) { for ( row = 0; row < lmp->nbr_realized_rows; row++ ) { XI_MAKE_ROW( &row_obj, new_focus, row ); attrib = xi_get_attrib( &row_obj ); if ( attrib & XI_ATR_SELECTED ) break; } } if ( row < lmp->nbr_realized_rows ) /* Move the focus to the selected row. */ list_data->focus_cell->v.cell.row = row; else { /* Select the first row in the list and make it the focus row. */ list_data->focus_cell->v.cell.row = 0; XI_MAKE_ROW( &row_obj, new_focus, 0 ); if ( make_callbacks && !list_data->in_select_process ) { XI_EVENT event; MEMCLEAR( event ); event.type = XIE_SELECT; event.v.select.xi_obj = &row_obj; event.v.select.selected = TRUE; event.v.select.records = lmp->recs; event.v.select.dbl_click = FALSE; call_cb( new_focus->itf, &event ); if ( event.refused ) return FALSE; } /* xi_set_attrib(&row_obj, attrib | XI_ATR_SELECTED ); */ } } /* if we get to here then it has happened */ { XI_ITF_DATA *itf_data; itf_data = new_focus->itf->v.itf; itf_data->chg_flag = FALSE; itf_data->focus_obj = new_focus; if ( itf_data->virtual_itf ) xi_make_obj_visible( new_focus ); } if ( new_focus->type == XIT_CELL ) new_focus->parent->v.list->focus_cell = new_focus; if ( new_focus->type == XIT_FIELD ) new_focus->parent->v.form->focus_field = new_focus; if ( old_focus != NULL && (old_is_cell || xi_is_obj( old_focus, itf ))) xi_lowlevel_focus( old_focus, FALSE ); if ( new_focus != NULL ) xi_lowlevel_focus( new_focus, TRUE ); /* If the old_focus or the new_focus is a cell, and they're in different * rows, redraw both rows. */ draw_old_row = FALSE; draw_new_row = FALSE; if ( old_focus && old_is_cell ) { if ( new_focus && new_focus->type == XIT_CELL ) { if ( old_focus->parent != new_focus->parent || old_focus->v.cell.row != new_focus->v.cell.row ) { draw_old_row = TRUE; draw_new_row = TRUE; } } else draw_old_row = TRUE; } else { if ( new_focus && new_focus->type == XIT_CELL ) draw_new_row = TRUE; } if ( draw_old_row ) { XI_LIST_DATA *list_data = old_focus->parent->v.list; LM_DATA *lmp = ( LM_DATA * ) list_data->lm; if ( ( !lmp->button_on_cell_focus || lmp->row_focus_border ) && old_focus->v.cell.is_vert_scrolled != TRUE && (int)old_focus->v.cell.row < lmp->nbr_realized_rows ) { lm_focus_cell_invis_make( lmp ); lm_redraw_row( ( LM_DATA * ) list_data->lm, old_focus->v.cell.row, FALSE ); lm_focus_cell_visible_attempt( lmp ); } } if ( draw_new_row ) { XI_LIST_DATA *list_data = new_focus->parent->v.list; LM_DATA *lmp = ( LM_DATA * ) list_data->lm; if ( !lmp->button_on_cell_focus || lmp->row_focus_border ) { lm_focus_cell_invis_make( lmp ); lm_redraw_row( lmp, new_focus->v.cell.row, FALSE ); lm_focus_cell_visible_attempt( lmp ); if ( lm_focus_state_get( lmp ) == LM_FOCUS_VISIBLE ) set_focus_cell_rct( lmp, new_focus->v.cell.row, new_focus->v.cell.column, FALSE ); } } if ( old_focus && (old_is_cell || xi_is_obj( old_focus, itf )) && new_focus ) xi_draw_foc_and_dflt_if_necessary( old_focus, new_focus ); return TRUE; } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ /* This function attempts to move the focus to the object indicated, returning TRUE if successful, FALSE if refused. This function will set or remove the focus from any low-level editing modules as necessary. If make_callbacks is TRUE, then XI callbacks will be issued to determine whether the focus change should be allowed before proceeding. */ BOOLEAN xi_move_focus_internal( XI_OBJ * xi_obj, BOOLEAN make_callbacks, BOOLEAN next_if_disabled, int check_for_reenabled ) { XI_OBJ *focus_obj; XI_OBJ *itf; XI_ITF_DATA *itf_data; LM_DATA *lmp = NULL; BOOLEAN focus_was_on_invisible = FALSE; itf = xi_obj->itf; itf_data = xi_obj->itf->v.itf; focus_obj = itf_data->focus_obj; if ( xi_compare_objs( focus_obj, xi_obj ) ) return ( TRUE ); if ( xi_obj->type == XIT_CELL ) lm_calculate_pix_offsets( xi_obj->parent->v.list->lm ); itf_data->moving_focus = TRUE; if ( focus_obj && focus_obj->type == XIT_CELL ) { XI_OBJ *list_obj; list_obj = focus_obj->parent; lmp = ( LM_DATA * ) ( list_obj->v.list->lm ); focus_was_on_invisible = lm_list_is_about_to_lose_focus( lmp ); } if ( !perform_move_focus( focus_obj, xi_obj, make_callbacks, next_if_disabled, check_for_reenabled ) ) { itf_data->moving_focus = FALSE; if ( focus_was_on_invisible ) lm_list_did_not_lose_focus( lmp ); if ( make_callbacks ) { XI_EVENT event; MEMCLEAR( event ); event.type = XIE_POST_NAVIGATION; call_cb( itf, &event ); } return FALSE; } itf_data->moving_focus = FALSE; if ( focus_was_on_invisible ) lm_list_did_lose_focus( lmp ); if ( make_callbacks ) { XI_EVENT event; MEMCLEAR( event ); event.type = XIE_POST_NAVIGATION; call_cb( itf, &event ); } itf_data->moving_focus = FALSE; return ( TRUE ); } BOOLEAN xi_move_focus( XI_OBJ * xi_obj ) { if (xi_obj != NULL) { if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL || ( xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE ) ) { if ( xi_obj->type == XIT_CELL ) { XI_OBJ *list_obj = xi_obj->parent; LM_DATA *lmp = ( LM_DATA * ) ( list_obj->v.list->lm ); if ( CELL_IS_SELECTABLE( ( LM ) lmp, xi_obj->v.cell.row, xi_obj->v.cell.column ) ) return FALSE; } return xi_move_focus_internal( xi_obj, TRUE, FALSE, 0 ); } } return FALSE; } void xi_set_focus( XI_OBJ * xi_obj ) { if (xi_obj != NULL) { if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL || ( xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE ) ) { if ( xi_obj->type == XIT_CELL ) { XI_OBJ *list_obj = xi_obj->parent; LM_DATA *lmp = ( LM_DATA * ) ( list_obj->v.list->lm ); if ( CELL_IS_SELECTABLE( ( LM ) lmp, xi_obj->v.cell.row, xi_obj->v.cell.column ) ) return; } xi_move_focus_internal( xi_obj, FALSE, FALSE, 0 ); } } } static void xi_add_to_parent_list( XI_OBJ * obj, int position ) { XI_OBJ *parent; if ( ( parent = obj->parent ) == NULL ) return; realloc_ptrs( ( void *** ) &parent->children, parent->nbr_children, parent ); if ( position == -1 ) parent->children[parent->nbr_children] = obj; else { int i; for ( i = parent->nbr_children; i > position; --i ) parent->children[i] = parent->children[i - 1]; parent->children[position] = obj; } parent->nbr_children++; } static void xi_stx_cb( STX_CB_DATA * stx_cb_data ) { XI_EVENT xiev; BOOLEAN send_cb = FALSE; XI_OBJ *xi_obj; xi_obj = xiev.v.xi_obj = ( XI_OBJ * ) stx_get_app_data( stx_cb_data->stx ); xiev.refused = FALSE; switch ( stx_cb_data->cb_type ) { case STX_CB_CHAR: /* generate an XIE_CHAR_FIELD */ xiev.type = XIE_CHAR_FIELD; xiev.v.chr.xi_obj = xi_obj; xiev.v.chr.ch = stx_cb_data->v.chr.ch; xiev.v.chr.shift = stx_cb_data->v.chr.shift; xiev.v.chr.control = stx_cb_data->v.chr.control; xiev.v.chr.alt = stx_cb_data->v.chr.alt; xiev.v.chr.is_paste = stx_cb_data->v.chr.is_paste; send_cb = TRUE; break; case STX_CB_CHANGE: /* generate an XIE_CHG_FIELD */ xiev.type = XIE_CHG_FIELD; send_cb = TRUE; break; case STX_CB_FOCUS: stx_cb_data->v.refused = !xi_move_focus_internal( xi_obj, TRUE, TRUE, 0 ); send_cb = FALSE; break; case STX_CB_DBL: xiev.type = XIE_DBL_FIELD; send_cb = TRUE; break; default: XinError( 20008, XinSeverityFatal, 0L ); } if ( send_cb ) call_cb( xi_obj->itf, &xiev ); if ( stx_cb_data->cb_type == STX_CB_CHAR ) { stx_cb_data->v.chr.ch = xiev.v.chr.ch; stx_cb_data->v.chr.refused = xiev.refused; } } static void xi_lm_cb( LM_CB_DATA * lm_cb_data ) { XI_EVENT xiev; BOOLEAN send_cb = FALSE; XI_OBJ *lm_obj; XI_OBJ *next_obj; XI_LIST_DATA *ldata; LM_DATA *lmp; XI_OBJ row_obj; // AGA: dichiarato oggetto locale di cui altrimenti si perde traccia nell'evento! MEMCLEAR( xiev ); lm_obj = ( XI_OBJ * ) lm_get_list_obj( lm_cb_data->lm ); lmp = ( LM_DATA * ) lm_obj->v.list->lm; ldata = lm_obj->v.list; xiev.v.xi_obj = ldata->focus_cell; next_obj = get_non_focus_cell_obj( ldata ); switch ( lm_cb_data->cb_type ) { case LM_CB_CHAR: /* generate an XIE_CHAR_CELL */ xiev.type = XIE_CHAR_CELL; xiev.v.chr.xi_obj = ldata->focus_cell; xiev.v.chr.ch = lm_cb_data->v.chr.ch; xiev.v.chr.shift = lm_cb_data->v.chr.shift; xiev.v.chr.control = lm_cb_data->v.chr.control; xiev.v.chr.alt = lm_cb_data->v.chr.alt; xiev.v.chr.is_paste = lm_cb_data->v.chr.is_paste; send_cb = TRUE; break; case LM_CB_CHANGE: xiev.type = XIE_CHG_CELL; send_cb = TRUE; break; case LM_CB_FOCUS: case LM_CB_CELL_BTN: { BOOLEAN ref; XI_OBJ *focus_obj; focus_obj = xi_get_focus( lm_obj->itf ); next_obj->v.cell.row = ( unsigned char ) lm_cb_data->row; next_obj->v.cell.column = ( unsigned char ) lm_cb_data->column; next_obj->v.cell.is_vert_scrolled = FALSE; ref = FALSE; if ( focus_obj && focus_obj->type == XIT_CELL && next_obj->type == XIT_CELL ) { if ( focus_obj->parent != next_obj->parent || focus_obj->v.cell.row != next_obj->v.cell.row || focus_obj->v.cell.column != next_obj->v.cell.column ) { if ( !xi_move_focus_internal( next_obj, TRUE, FALSE, 0 ) ) if ( lm_cb_data->cb_type == LM_CB_FOCUS ) ref = lm_cb_data->v.refused = TRUE; } } else if ( !xi_move_focus_internal( next_obj, TRUE, FALSE, 0 ) ) if ( lm_cb_data->cb_type == LM_CB_FOCUS ) ref = lm_cb_data->v.refused = TRUE; next_obj = get_non_focus_cell_obj( ldata ); next_obj->v.cell.row = ( unsigned char ) ( lm_cb_data->row ); next_obj->v.cell.column = ( unsigned char ) ( lm_cb_data->column ); send_cb = FALSE; if ( ( !ref ) && ( lm_cb_data->cb_type == LM_CB_CELL_BTN ) ) { xiev.type = XIE_BUTTON; xiev.v.xi_obj = next_obj; send_cb = TRUE; } break; } case LM_CB_DBL: xiev.type = XIE_DBL_CELL; xiev.v.xi_obj->v.cell.row = ( unsigned char ) ( lm_cb_data->row ); xiev.v.xi_obj->v.cell.column = ( unsigned char ) ( lm_cb_data->column ); send_cb = TRUE; break; case LM_CB_TEXT: xiev.type = XIE_CELL_REQUEST; xiev.v.cell_request.list = lm_obj; xiev.v.cell_request.s = lm_cb_data->v.text.text; xiev.v.cell_request.len = lm_cb_data->v.text.len; xiev.v.cell_request.col_nbr = lm_cb_data->column; xiev.v.cell_request.rec = lm_cb_data->rec; xiev.v.cell_request.icon_rid = lm_cb_data->v.text.icon_rid; xiev.v.cell_request.bitmap = lm_cb_data->v.text.bitmap; xiev.v.cell_request.attrib = lm_cb_data->v.text.attrib; xiev.v.cell_request.color = lm_cb_data->v.text.color; xiev.v.cell_request.back_color = lm_cb_data->v.text.back_color; xiev.v.cell_request.records = lmp->recs; send_cb = TRUE; break; case LM_CB_REC_ALLOCATE: xiev.type = XIE_REC_ALLOCATE; xiev.v.rec_allocate.list = lm_obj; xiev.v.rec_allocate.record = lm_cb_data->v.rec_allocate.record; send_cb = TRUE; break; case LM_CB_REC_FREE: xiev.type = XIE_REC_FREE; xiev.v.rec_free.list = lm_obj; xiev.v.rec_free.record = lm_cb_data->v.rec_free.record; send_cb = TRUE; break; case LM_CB_GET_FIRST: case LM_CB_GET_NEXT: case LM_CB_GET_PREV: case LM_CB_GET_LAST: switch ( lm_cb_data->cb_type ) { case LM_CB_GET_FIRST: xiev.type = XIE_GET_FIRST; break; case LM_CB_GET_NEXT: xiev.type = XIE_GET_NEXT; break; case LM_CB_GET_PREV: xiev.type = XIE_GET_PREV; break; case LM_CB_GET_LAST: xiev.type = XIE_GET_LAST; break; default: break; } xiev.v.rec_request.list = lm_obj; xiev.v.rec_request.spec_rec = lm_cb_data->v.rec_request.spec_rec; xiev.v.rec_request.data_rec = lm_cb_data->v.rec_request.data_rec; xiev.v.rec_request.percent = lm_cb_data->v.rec_request.percent; xiev.v.rec_request.attrib = lm_cb_data->v.rec_request.attrib; xiev.v.rec_request.color = lm_cb_data->v.rec_request.color; send_cb = TRUE; break; case LM_CB_GET_PERCENT: xiev.type = XIE_GET_PERCENT; xiev.v.get_percent.list = lm_obj; xiev.v.get_percent.record = lm_cb_data->v.get_percent.record; send_cb = TRUE; break; case LM_CB_SELECT: { if ( lm_cb_data->row == 255 && lm_cb_data->column == 255 ) { xiev.type = XIE_SELECT; xiev.v.select.xi_obj = lm_obj; xiev.v.select.selected = TRUE; xiev.v.select.dbl_click = FALSE; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.records = lmp->recs; xiev.v.select.column = 0; send_cb = TRUE; } else if ( lm_cb_data->row == 255 ) { xiev.type = XIE_SELECT; xiev.v.select.xi_obj = lm_obj->children[lm_cb_data->column]; xiev.v.select.selected = lm_cb_data->v.select.selected; xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.column = lm_cb_data->column; xiev.v.select.records = lmp->recs; send_cb = TRUE; } else { // XI_OBJ row_obj; AGA was here XI_MAKE_ROW( &row_obj, lm_obj, lm_cb_data->row ); xiev.type = XIE_SELECT; xiev.v.select.xi_obj = &row_obj; xiev.v.select.selected = lm_cb_data->v.select.selected; xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.column = lm_cb_data->column; xiev.v.select.records = lmp->recs; send_cb = TRUE; } break; } case LM_CB_ROW_SIZE: { // XI_OBJ row_obj; AGA was here XI_MAKE_ROW( &row_obj, lm_obj, lm_cb_data->row ); xiev.type = XIE_ROW_SIZE; xiev.v.row_size.xi_obj = &row_obj; xiev.v.row_size.new_row_height = lm_cb_data->v.row_size.new_row_height; send_cb = TRUE; break; } case LM_CB_COL_DELETE: xiev.type = XIE_COL_DELETE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; send_cb = TRUE; break; case LM_CB_COL_MOVE: xiev.type = XIE_COL_MOVE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; xiev.v.column.new_col_nbr = lm_cb_data->v.column.new_col_nbr; xiev.v.column.in_fixed = lm_cb_data->v.column.in_fixed; send_cb = TRUE; break; case LM_CB_COL_SIZE: xiev.type = XIE_COL_SIZE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; xiev.v.column.new_col_width = lm_cb_data->v.column.new_col_width; xiev.v.column.new_col_pixel_width = lm_cb_data->v.column.new_col_pixel_width; send_cb = TRUE; break; case LM_CB_DROP_ROW: xiev.type = XIE_DROP_ROW; xiev.v.drop_row.src_list = lm_cb_data->v.drop_row.src_list; xiev.v.drop_row.dest_list = lm_obj; xiev.v.drop_row.src_rec = lm_cb_data->v.drop_row.src_rec; xiev.v.drop_row.after_all_rows = lm_cb_data->v.drop_row.after_all_rows; xiev.v.drop_row.delete_row = lm_cb_data->v.drop_row.delete_row; if ( xiev.v.drop_row.after_all_rows || xiev.v.drop_row.delete_row ) xiev.v.drop_row.dest_rec = 0; else xiev.v.drop_row.dest_rec = lmp->recs[lm_cb_data->row]; xiev.v.drop_row.shift = lm_cb_data->v.drop_row.shift; xiev.v.drop_row.control = lm_cb_data->v.drop_row.control; send_cb = TRUE; break; default: XinError( 20009, XinSeverityFatal, 0L ); } if ( send_cb ) call_cb( lm_obj->itf, &xiev ); if ( lm_cb_data->cb_type == LM_CB_CHAR ) { lm_cb_data->v.chr.refused = xiev.refused; lm_cb_data->v.chr.ch = xiev.v.chr.ch; } if ( lm_cb_data->cb_type == LM_CB_SELECT ) lm_cb_data->v.select.refused = xiev.refused; if ( lm_cb_data->cb_type == LM_CB_ROW_SIZE ) lm_cb_data->v.row_size.refused = xiev.refused; if ( lm_cb_data->cb_type == LM_CB_TEXT ) { lm_cb_data->v.text.text = xiev.v.cell_request.s; lm_cb_data->v.text.len = xiev.v.cell_request.len; lm_cb_data->v.text.icon_rid = xiev.v.cell_request.icon_rid; lm_cb_data->v.text.bitmap = xiev.v.cell_request.bitmap; lm_cb_data->v.text.attrib = xiev.v.cell_request.attrib; lm_cb_data->v.text.color = xiev.v.cell_request.color; lm_cb_data->v.text.back_color = xiev.v.cell_request.back_color; lm_cb_data->v.text.font = xiev.v.cell_request.font; lm_cb_data->v.text.font_id = xiev.v.cell_request.font_id; lm_cb_data->v.text.button = xiev.v.cell_request.button; lm_cb_data->v.text.button_on_left = xiev.v.cell_request.button_on_left; lm_cb_data->v.text.button_on_focus = xiev.v.cell_request.button_on_focus; lm_cb_data->v.text.button_full_cell = xiev.v.cell_request.button_full_cell; lm_cb_data->v.text.button_icon_rid = xiev.v.cell_request.button_icon_rid; lm_cb_data->v.text.button_bitmap = xiev.v.cell_request.button_bitmap; } if ( lm_cb_data->cb_type == LM_CB_GET_PERCENT ) lm_cb_data->v.get_percent.percent = xiev.v.get_percent.percent; if ( lm_cb_data->cb_type == LM_CB_REC_ALLOCATE ) lm_cb_data->v.rec_allocate.record = xiev.v.rec_allocate.record; switch ( lm_cb_data->cb_type ) { case LM_CB_GET_FIRST: case LM_CB_GET_NEXT: case LM_CB_GET_PREV: case LM_CB_GET_LAST: lm_cb_data->v.rec_request.data_rec = xiev.v.rec_request.data_rec; lm_cb_data->v.rec_request.attrib = xiev.v.rec_request.attrib; lm_cb_data->v.rec_request.color = xiev.v.rec_request.color; lm_cb_data->v.rec_request.row_height = xiev.v.rec_request.row_height; lm_cb_data->v.rec_request.refused = xiev.refused; lm_cb_data->v.rec_request.has_focus = xiev.v.rec_request.has_focus; break; case LM_CB_COL_DELETE: case LM_CB_COL_MOVE: case LM_CB_COL_SIZE: lm_cb_data->v.column.refused = xiev.refused; break; default: break; } } /* This queue is more of a stack than a queue but event ordering is not important. This function is used to queue up events for later processing to avoid recursive callbacks at bad times. For example, XIE_INIT is queued up during interface creation. */ static void xi_enqueue( XI_EVENT * xiev, XI_OBJ * itf ) { XI_EQ *xi_el; xi_el = ( XI_EQ * ) xi_tree_malloc( sizeof( XI_EQ ), NULL ); xi_el->xiev = *xiev; xi_el->itf = itf; xi_el->next = NULL; if ( xi_eq == NULL ) xi_eq = xi_el; else { XI_EQ *last = xi_eq; while ( last->next != NULL ) last = last->next; last->next = xi_el; } } /* ------------------------------------------------------------------------- */ /* remove all events associated with an interface from the que */ /* ------------------------------------------------------------------------- */ static void xi_que_remove( XI_OBJ * itf ) { XI_EQ *current; XI_EQ *last; last = NULL; current = xi_eq; while ( current != NULL ) { if ( current->itf != itf ) { last = current; current = current->next; } else { XI_EQ *next = current->next; if ( last == NULL ) xi_eq = next; else last->next = next; xi_tree_free( current ); current = next; } } } /* This function will dequeue all events queued up via xi_enqueue. This function is called at the end of xi_event, so that any events that were queued would be flushed out at that time. */ void xi_dequeue( void ) { XI_EQ* old_eq; XI_EQ *xi_el; XI_OBJ **objp; XI_OBJ *editable; int i; old_eq = xi_eq; xi_eq = NULL; while ( old_eq != NULL ) { xi_el = old_eq; call_cb( xi_el->itf, &xi_el->xiev ); old_eq = old_eq->next; if ( xi_el->xiev.type == XIE_INIT ) { if (!xi_is_itf( xi_el->itf )) return; /* fill in all lists */ for ( objp = xi_el->itf->children, i = xi_el->itf->nbr_children; i != 0; i--, objp++ ) { if ( ( *objp )->type == XIT_LIST ) { if ( !( *objp )->v.list->done_initial_xi_scroll ) { if ( xi_get_attrib( *objp ) & XI_ATR_VISIBLE ) { ( *objp )->v.list->done_initial_xi_scroll = TRUE; xi_scroll_internal( *objp, XI_SCROLL_FIRST, ( *objp )->v.list->start_percent, FALSE ); } } } } editable = xi_search_itf( xi_el->itf, XI_SEARCH_FOR_INITIAL, 0 ); if ( xi_el->itf->v.itf->needs_update ) { xi_el->itf->v.itf->needs_update = FALSE; XinWindowRectInvalidate( xi_get_window( xi_el->itf ), NULL ); } if ( editable ) xi_move_focus_internal( editable, TRUE, FALSE, 0 ); xi_tree_free( xi_el ); } } } /* xi_add_window_to_list: Record a window as being an XI window, so that XI can tell its windows apart from other windows. */ void xi_add_window_to_list( XinWindow win, XI_OBJ * itf ) { XI_WINDOW_LIST *list; /* list_parent is the tree memory parent of all structures in the linked list * of windows. It is used to avoid clogging up the FIRSTNODE's child list * too much. */ if ( list_parent == NULL ) list_parent = ( char * ) xi_tree_malloc( 1, NULL ); list = ( XI_WINDOW_LIST * ) xi_tree_malloc( sizeof( XI_WINDOW_LIST ), list_parent ); list->next = xi_window_list; list->win = win; list->itf = itf; xi_window_list = list; } void xi_remove_window_from_list( XinWindow win ) { XI_WINDOW_LIST *list; XI_WINDOW_LIST *next; if ( win == xi_window_list->win ) { list = xi_window_list; xi_window_list = xi_window_list->next; xi_que_remove( list->itf ); xi_tree_free( list ); if ( xi_window_list == NULL ) { xi_tree_free( list_parent ); list_parent = NULL; } return; } else { for ( list = xi_window_list; list != NULL && ( next = list->next ) != NULL; list = next ) { if ( next->win == win ) { list->next = next->next; xi_que_remove( next->itf ); xi_tree_free( next ); return; } } } XinError( 20004, XinSeverityFatal, 0L ); } /* find an interface from its id */ XI_OBJ * xi_get_itf_from_id( int id ) { XI_WINDOW_LIST *list; list = xi_window_list; while ( list != NULL && list->itf->cid != id ) list = list->next; if ( list == NULL ) return NULL; return list->itf; } BOOLEAN xi_is_window( XinWindow win ) { register XI_WINDOW_LIST *list; for ( list = xi_window_list; list != NULL; list = list->next ) if ( list->win == win ) return TRUE; return FALSE; } BOOLEAN xi_is_itf( XI_OBJ * itf ) { register XI_WINDOW_LIST *list; for ( list = xi_window_list; list != NULL; list = list->next ) if ( list->itf == itf ) return TRUE; return FALSE; } XI_OBJ * xi_get_itf_containing( XinPoint * pt ) { register XI_WINDOW_LIST *list; for ( list = xi_window_list; list != NULL; list = list->next ) { XinRect rct; XinWindowRectOuterGet( list->win, &rct ); if ( XinRectPointContained( &rct, pt ) ) return list->itf; } return NULL; } BOOLEAN xi_is_changed( XI_OBJ * obj ) { return obj->itf->v.itf->chg_flag; } XI_OBJ * xi_get_itf( XinWindow win ) { XI_WINDOW_LIST *next; for ( next = xi_window_list; next != NULL; next = next->next ) if ( next->win == win ) { return next->itf; } return NULL; } BOOLEAN xi_itf_closing_is( XI_OBJ * itf ) { if ( itf == NULL || itf->type != XIT_ITF ) XinError( 20039, XinSeverityFatal, 0L ); return itf->v.itf->closing; } BOOLEAN xi_itf_in_event_destroy( XI_OBJ * itf ) { if (itf == NULL || itf->type != XIT_ITF ) XinError( 20039, XinSeverityFatal, 0L ); return itf->v.itf->in_event_destroy; } /* ------------------------------------------------------------------------ */ /* create_children */ /* ------------------------------------------------------------------------ */ static void create_children( XI_OBJ_DEF * xi_obj_def, XI_OBJ * obj, BOOLEAN creating_list ) { XI_OBJ_DEF **child; int i; /* create children of the object if there are any */ child = xi_obj_def->children; for ( i = 0; i < xi_obj_def->nbr_children; child++, i++ ) /* xi_create automatically adds object to the parent list */ xi_create_internal( obj, *child, creating_list, FALSE ); } /* ------------------------------------------------------------------------ */ /* create_interface */ /* ------------------------------------------------------------------------ */ static void interface_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * itf ) { static BOOLEAN first_itf = TRUE; XI_ITF_DATA *itf_data; XI_ITF_DEF *itf_def; XinRect def_rct; XinRect *rctp; XinRect rct; XinWindow itf_win; XinWindow parent = XinWindowTaskGet( ); BOOLEAN do_move_window = FALSE; XI_EVENT xiev; itf_def = xi_obj_def->v.itf; rctp = itf_def->rctp; xi_get_def_rect( xi_obj_def, &def_rct ); def_rct.left = 12; def_rct.right += 12; if ( rctp == NULL || rctp->top == rctp->bottom ) { rct = def_rct; if ( rctp ) xi_offset_rect( &rct, rctp->left, rctp->top ); } else rct = *rctp; itf_data = ( XI_ITF_DATA * ) xi_tree_malloc( sizeof( XI_ITF_DATA ), ( char * ) itf ); itf_data->xi_eh = itf_def->xi_eh; itf_data->half_baked = TRUE; itf_data->edit_menu = itf_def->edit_menu; itf_data->back_color = itf_def->back_color; itf_data->automatic_back_color = itf_def->automatic_back_color; if ( itf_def->automatic_back_color ) { if ( xi_get_pref( XI_PREF_3D_LOOK ) ) itf_data->back_color = XI_COLOR_LTGRAY; else itf_data->back_color = XI_COLOR_WHITE; } itf_data->virtual_itf = itf_def->virtual_itf; itf_data->modal = itf_def->modal; itf_data->size_font_to_win = itf_def->size_font_to_win; itf_data->tab_on_enter = itf_def->tab_on_enter; itf_data->prev_modal = XI_NULL_WINDOW; itf_data->bitmap = xi_bitmap_copy( itf_def->bitmap ); itf_data->modal_wait = itf_def->modal_wait; itf->v.itf = itf_data; itf_data->use_xil_win = itf_def->use_xil_win; itf_data->dequeue = XI_DEQUEUE_INIT; if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( itf_def->font ) XinFontCopy( &itf_data->font, itf_def->font ); } #ifdef XI_USE_XVT else { if ( itf_def->font_id ) itf_data->font = XinFontXvtConvert( itf_def->font_id ); } #endif itf_data->fu_height = xi_get_fu_height_font( itf_data->font ? itf_data->font : xi_get_system_font( ) ); itf_data->fu_width = xi_get_fu_width_font( itf_data->font ? itf_data->font : xi_get_system_font( ) ); itf_data->max_xi_pnt.h = def_rct.right - def_rct.left; itf_data->max_xi_pnt.v = def_rct.bottom - def_rct.top; xi_pu_to_fu( itf->itf, &itf_data->max_xi_pnt, 1 ); xi_even_fu_pnt( &itf_data->max_xi_pnt ); itf_data->menu_win = itf_def->menu_win; itf_data->initial_focus_cid = itf_def->initial_focus_cid; if ( itf_def->win ) { #ifdef XI_USE_XVT if ( !( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) XinXvtWindowRegister( itf_def->win, xi_event ); #endif itf_data->xin_win = itf_def->win; itf_win = itf_def->win; if ( itf_def->size_win ) do_move_window = TRUE; XinWindowRectGet( itf_win, &itf_data->original_win_rct ); if ( itf_data->font ) itf_data->original_font_size = ( int ) XinFontSizeGet( itf_data->font ); xi_add_window_to_list( itf_data->xin_win, itf ); if ( xi_get_pref( XI_PREF_USE_APP_DATA ) ) XinWindowAppDataSet( itf_data->xin_win, ( long ) ( itf ) ); if ( itf_data->virtual_itf ) { xi_adjust_sb_vir_itf( itf_win, itf ); XinScrollBarSet( itf_data->xin_win, XinScrollBarTypeHorizontal, 0, 100, 1, 0 ); XinScrollBarSet( itf_data->xin_win, XinScrollBarTypeVertical, 0, 100, 1, 0 ); } first_itf = FALSE; xi_add_to_parent_list( itf, -1 ); XinCoalesceInvalidates( itf_win, TRUE ); create_children( xi_obj_def, itf, FALSE ); /* queue up initialization event */ itf_data->needs_update = TRUE; xiev.type = XIE_INIT; xiev.v.xi_obj = itf; xi_enqueue( &xiev, itf ); itf_data->dequeue = XI_DEQUEUE_CALL; XinCoalesceInvalidates( itf_win, FALSE ); if ( do_move_window ) XinWindowRectSet( itf_win, &rct ); } else { XinWindowType win_type; win_type = XinWindowTypeDocument; if ( rct.top < xi_get_pref( XI_PREF_ITF_MIN_TOP ) ) { int delta; delta = ( int ) xi_get_pref( XI_PREF_ITF_MIN_TOP ) - rct.top; rct.top += delta; rct.bottom += delta; } if ( rct.left < xi_get_pref( XI_PREF_ITF_MIN_LEFT ) ) { int delta; delta = ( int ) xi_get_pref( XI_PREF_ITF_MIN_LEFT ) - rct.left; rct.left += delta; rct.right += delta; } { XinWindowDef Def; MEMCLEAR( Def ); Def.parent = itf_def->parent != NULL ? itf_def->parent : parent; Def.type = win_type; Def.p_rect = &rct; Def.title = itf_def->title; Def.border_style = itf_def->border_style_set ? itf_def->border_style : ( itf_def->ctl_size ? XinBorderSizable : XinBorderFixed ); Def.vertical_scroll_bar = itf_def->ctl_vscroll; Def.horizontal_scroll_bar = itf_def->ctl_hscroll; Def.close_button = itf_def->ctl_close; Def.iconized = itf_def->ctl_iconized; Def.iconizable = itf_def->ctl_iconizable; Def.visible = itf_def->visible; Def.enabled = itf_def->enabled; Def.back_color = XI_COLOR_WHITE; /* Special color for XM? */ Def.menu_bar_rid = itf_def->menu_bar_rid; Def.menu = itf_def->menu; Def.eh = ( XinWindowEventHandler ) xi_event; Def.maximized = itf_def->maximized; Def.icon_rid = itf_def->icon_rid; xi_creating_itf = itf; interface_create_data.itf = itf; interface_create_data.rct = rct; interface_create_data.obj_def = xi_obj_def; if ( itf_def->modal_wait ) { Def.mode = XinModalWait; xi_in_modal_wait_create = TRUE; } else if ( itf_def->modal ) Def.mode = XinModalReturn; else if ( itf_def->autoclose ) Def.mode = XinModalAutoclose; else Def.mode = XinModeless; XinWindowCreate( &Def ); itf_data->dequeue = XI_DEQUEUE_CALL; xi_in_modal_wait_create = FALSE; return; } } } /* ------------------------------------------------------------------------ */ /* xi_finish_interface_create() */ /* do post-XinWindowCreate stuff. */ /* ------------------------------------------------------------------------ */ void xi_finish_interface_create( XinWindow win ) { XI_ITF_DATA *itf_data; XinRect rct; XinWindow itf_win; XI_EVENT xiev; XI_OBJ_DEF *xi_obj_def; XI_OBJ *itf; if ( xi_creating_itf == NULL ) return; xi_in_modal_wait_create = FALSE; itf = interface_create_data.itf; itf_data = itf->v.itf; rct = interface_create_data.rct; itf_win = win; xi_obj_def = interface_create_data.obj_def; itf_data->xin_win = win; itf_data->win_xi_pnt.v = rct.bottom - rct.top; itf_data->win_xi_pnt.h = rct.right - rct.left; xi_pu_to_fu( itf->itf, &itf_data->win_xi_pnt, 1 ); xi_even_fu_pnt( &itf_data->win_xi_pnt ); XinWindowRectGet( itf_win, &itf_data->original_win_rct ); if ( itf_data->font ) itf_data->original_font_size = ( int ) XinFontSizeGet( itf_data->font ); xi_add_window_to_list( itf_data->xin_win, itf ); if ( xi_get_pref( XI_PREF_USE_APP_DATA ) ) XinWindowAppDataSet( itf_data->xin_win, ( long ) ( itf ) ); if ( itf_data->virtual_itf ) { xi_adjust_sb_vir_itf( itf_win, itf ); XinScrollBarSet( itf_data->xin_win, XinScrollBarTypeHorizontal, 0, 100, 1, 0 ); XinScrollBarSet( itf_data->xin_win, XinScrollBarTypeVertical, 0, 100, 1, 0 ); } xi_add_to_parent_list( itf, -1 ); XinCoalesceInvalidates( itf_win, TRUE ); create_children( xi_obj_def, itf, FALSE ); /* queue up initialization event */ xiev.type = XIE_INIT; xiev.v.xi_obj = itf; xi_enqueue( &xiev, itf ); XinCoalesceInvalidates( itf_win, FALSE ); } /* ------------------------------------------------------------------------ */ /* assign rectangles */ /* ------------------------------------------------------------------------ */ static void assign_rectangles( XI_OBJ * itf, XinRect * dest_form_rect, XinRect * dest_pixel_rect, XinRect * source_form_rect, XinRect * source_pixel_rect ) { if ( source_pixel_rect->left || source_pixel_rect->right || source_pixel_rect->top || source_pixel_rect->bottom ) { *dest_pixel_rect = *dest_form_rect = *source_pixel_rect; xi_pu_to_fu( itf, ( XinPoint * ) dest_form_rect, 2 ); } else { *dest_pixel_rect = *dest_form_rect = *source_form_rect; xi_fu_to_pu( itf, ( XinPoint * ) dest_pixel_rect, 2 ); } } /* ------------------------------------------------------------------------ */ /* container_create */ /* ------------------------------------------------------------------------ */ static void check_bitmap_max( XI_CONTAINER_DATA * cdata, XI_BITMAP * bitmap, int border ) { short w, h; if ( bitmap != NULL ) { xi_bitmap_size_get( bitmap, &w, &h ); w += border; h += border; if ( w > cdata->pix_width ) cdata->pix_width = w; if ( h > cdata->pix_height ) cdata->pix_height = h; } } static void container_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * container ) { XI_CONTAINER_DEF *cdef; XI_OBJ_DEF *child; XI_CONTAINER_DATA *cdata; int i, len, max_len; XI_BTN_TYPE button_type = XIBT_BUTTON; int border; if ( xi_obj_def->nbr_children <= 0 ) XinError( 20011, XinSeverityFatal, 0L ); cdef = xi_obj_def->v.container; cdata = ( XI_CONTAINER_DATA * ) xi_tree_malloc( sizeof( XI_CONTAINER_DATA ), ( char * ) container ); assign_rectangles( container->itf, &cdata->xi_rct, &cdata->rct, &cdef->xi_rct, &cdef->pixel_rect ); cdata->orientation = cdef->orientation; cdata->tab_cid = cdef->tab_cid; cdata->btn_height = cdef->btn_height; cdata->btn_width = cdef->btn_width; cdata->nbr_buttons = xi_obj_def->nbr_children; cdata->packed = cdef->packed; container->v.container = cdata; /* Determine largest bitmaps and longest text strings */ if ( cdata->packed ) border = 2 * ( ( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ) + 2 ); else border = 10; max_len = 0; for ( i = 0; i < xi_obj_def->nbr_children; ++i ) { child = xi_obj_def->children[i]; if ( child->type != XIT_BTN ) XinError( 20012, XinSeverityFatal, 0L ); if ( i == 0 ) button_type = child->v.btn->type; else if ( child->v.btn->type != button_type ) XinError( 20013, XinSeverityFatal, 0L ); if ( ( len = ( int ) strlen( child->v.btn->text ) ) > max_len ) max_len = len; check_bitmap_max( cdata, child->v.btn->up_bitmap, border ); check_bitmap_max( cdata, child->v.btn->down_bitmap, border ); check_bitmap_max( cdata, child->v.btn->disabled_bitmap, border ); } xi_container_rect_calc( container, max_len, button_type ); xi_add_to_parent_list( container, -1 ); create_children( xi_obj_def, container, FALSE ); } void xi_container_set_rect_internal( XI_OBJ *xi_obj, XinRect *rect ) { XI_CONTAINER_DATA *cdata; int i, len, max_len; int border; XI_OBJ *child = NULL; XinRect child_rect; cdata = xi_obj->v.container; /* Determine largest bitmaps and longest text strings */ if ( cdata->packed ) border = 2 * ( ( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ) + 2 ); else border = 10; max_len = 0; for ( i = 0; i < xi_obj->nbr_children; ++i ) { child = xi_obj->children[i]; if ( ( len = ( int ) strlen( child->v.btn->text ) ) > max_len ) max_len = len; check_bitmap_max( cdata, child->v.btn->up_bitmap, border ); check_bitmap_max( cdata, child->v.btn->down_bitmap, border ); check_bitmap_max( cdata, child->v.btn->disabled_bitmap, border ); } cdata->rct = *rect; if (!cdata->packed && cdata->orientation == XI_STACK_VERTICAL) { switch ( child->v.btn->type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: case XIBT_TABBTN: { int top_ofst, vert_spacing = 0, vert_form_unit; vert_form_unit = xi_get_fu_height( xi_obj->itf ); if ( !cdata->packed ) if ( ( vert_spacing = ( int ) xi_get_pref( XI_PREF_VERT_PIXEL_SPACING ) ) == 0 ) vert_spacing = ( int ) ( ( xi_get_pref( XI_PREF_VERT_SPACING ) * vert_form_unit ) / XI_FU_MULTIPLE ); top_ofst = vert_spacing / 2; cdata->rct.top -= top_ofst; cdata->rct.bottom -= top_ofst; } break; default: break; } } xi_container_rect_calc( xi_obj, max_len, child->v.btn->type ); switch (cdata->orientation) { case XI_STACK_VERTICAL: for (i = 0; i < xi_obj->nbr_children; ++i ) { child = xi_obj->children[i]; child_rect.top = cdata->rct.top + (cdata->step_down * i); child_rect.bottom = child_rect.top + cdata->pix_height; child_rect.left = cdata->rct.left; child_rect.right = cdata->rct.right; xi_set_rect_internal( child, &child_rect ); } break; case XI_STACK_HORIZONTAL: for (i = 0; i < xi_obj->nbr_children; ++i ) { child = xi_obj->children[i]; child_rect.left = cdata->rct.left + (cdata->step_across * i); child_rect.right = child_rect.left + cdata->pix_width; child_rect.top = cdata->rct.top; child_rect.bottom = cdata->rct.bottom; xi_set_rect_internal( child, &child_rect ); } break; case XI_GRID_VERTICAL: { int j; for (i=0; i < cdata->nbr_across; i++) { for (j=0; j < cdata->nbr_down; j++) { int pos = i*cdata->nbr_down + j; if (pos > xi_obj->nbr_children) break; child = xi_obj->children[pos]; child_rect.top = cdata->rct.top + (cdata->step_down * j); child_rect.left = cdata->rct.left + (cdata->step_across * i); child_rect.bottom = child_rect.top + cdata->pix_height; child_rect.right = child_rect.left + cdata->pix_width; xi_set_rect_internal( child, &child_rect ); } } } break; case XI_GRID_HORIZONTAL: { int j; for (i=0; i < cdata->nbr_down; i++) { for (j=0; j < cdata->nbr_across; j++) { int pos = i*cdata->nbr_across + j; if (pos > xi_obj->nbr_children) break; child = xi_obj->children[pos]; child_rect.top = cdata->rct.top + (cdata->step_down * i); child_rect.left = cdata->rct.left + (cdata->step_across * j); child_rect.bottom = child_rect.top + cdata->pix_height; child_rect.right = child_rect.left + cdata->pix_width; xi_set_rect_internal( child, &child_rect ); } } } break; } } /* ------------------------------------------------------------------------ */ /* rectangle_create */ /* ------------------------------------------------------------------------ */ static void rectangle_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * rectangle ) { XI_RECT_DATA *rect_data; XI_RECT_DEF *rect_def = xi_obj_def->v.rect; XinRect rct; rect_data = ( XI_RECT_DATA * ) xi_tree_malloc( sizeof( XI_RECT_DATA ), rectangle ); rect_data->fore_color = rect_def->fore_color; rect_data->back_color = rect_def->back_color; rect_data->hilight_color = rect_def->hilight_color; rect_data->shadow_color = rect_def->shadow_color; rect_data->well = rect_def->well; rect_data->ridge = rect_def->ridge; rect_data->attrib = rect_def->attrib; rect_data->bitmap = xi_bitmap_copy( rect_def->bitmap ); #if XIWS == XIWS_WM rect_data->xi_rct = rect_def->xi_rct; rct = rect_def->xi_rct; rct.top = ( rct.top / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; rct.left = ( rct.left / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; rct.bottom = ( ( rct.bottom + XI_FU_MULTIPLE / 2 ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; rct.right = ( ( rct.right + XI_FU_MULTIPLE / 2 ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; rect_data->rct = rct; #endif #if XIWS != XIWS_WM assign_rectangles( rectangle->itf, &rect_data->xi_rct, &rect_data->rct, &rect_def->xi_rct, &rect_def->pixel_rect ); #endif rectangle->v.rect = rect_data; xi_invalidate_rect( rectangle->itf->v.itf->xin_win, &rct ); xi_add_to_parent_list( rectangle, -1 ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20050, XinSeverityFatal, 0L ); } /* ------------------------------------------------------------------------ */ /* line_create */ /* ------------------------------------------------------------------------ */ static void line_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * line ) { XI_LINE_DATA *line_data; XI_LINE_DEF *line_def = xi_obj_def->v.line; XinPoint pnt1, pnt2; XinRect rct; line_data = ( XI_LINE_DATA * ) xi_tree_malloc( sizeof( XI_LINE_DATA ), line ); line_data->fore_color = line_def->fore_color; line_data->back_color = line_def->back_color; line_data->well = line_def->well; line_data->attrib = line_def->attrib; if ( line_def->pixel_pnt1.h || line_def->pixel_pnt1.v || line_def->pixel_pnt2.h || line_def->pixel_pnt2.v ) { pnt1 = line_def->pixel_pnt1; pnt2 = line_def->pixel_pnt2; line_data->xi_pnt1 = pnt1; line_data->xi_pnt2 = pnt2; xi_pu_to_fu( line->itf, &line_data->xi_pnt1, 1 ); xi_pu_to_fu( line->itf, &line_data->xi_pnt2, 1 ); } else { pnt1 = line_def->pnt1; pnt2 = line_def->pnt2; line_data->xi_pnt1 = pnt1; line_data->xi_pnt2 = pnt2; #if XIWS == XIWS_WM pnt1.h = ( pnt1.h / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; pnt1.v = ( pnt1.v / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; pnt2.h = ( pnt2.h / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; pnt2.v = ( pnt2.v / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; #endif #if XIWS != XIWS_WM xi_fu_to_pu( line->itf, &pnt1, 1 ); xi_fu_to_pu( line->itf, &pnt2, 1 ); #endif } line_data->pnt1 = pnt1; line_data->pnt2 = pnt2; line->v.line = line_data; rct.top = min( pnt1.v, pnt2.v ); rct.left = min( pnt1.h, pnt2.h ); rct.bottom = max( pnt1.v, pnt2.v ); rct.right = max( pnt1.h, pnt2.h ); xi_invalidate_rect( line->itf->v.itf->xin_win, &rct ); xi_add_to_parent_list( line, -1 ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20051, XinSeverityFatal, 0L ); } /* ------------------------------------------------------------------------ */ /* button_create */ /* ------------------------------------------------------------------------ */ static void button_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * button ) { XI_BTN_DATA *btn_data; XI_BTN_DEF *btn_def = xi_obj_def->v.btn; XinRect rct; XinWindow itf_win; itf_win = button->itf->v.itf->xin_win; btn_data = ( XI_BTN_DATA * ) xi_tree_malloc( sizeof( XI_BTN_DATA ), button ); btn_data->attrib = btn_def->attrib; btn_data->tab_cid = btn_def->tab_cid; btn_data->dflt = btn_def->dflt; btn_data->cancel = btn_def->cancel; btn_data->down_icon_rid = btn_def->down_icon_rid; btn_data->up_icon_rid = btn_def->up_icon_rid; btn_data->disabled_icon_rid = btn_def->disabled_icon_rid; btn_data->icon_x = btn_def->icon_x; btn_data->icon_y = btn_def->icon_y; btn_data->up_bitmap = xi_bitmap_copy( btn_def->up_bitmap ); btn_data->down_bitmap = xi_bitmap_copy( btn_def->down_bitmap ); btn_data->disabled_bitmap = xi_bitmap_copy( btn_def->disabled_bitmap ); btn_data->text = ( char * ) xi_tree_malloc( strlen( btn_def->text ) + 1, btn_data ); btn_data->checked = btn_def->checked; btn_data->type = btn_def->type; btn_data->fore_color = btn_def->fore_color; btn_data->draw_as = btn_def->draw_as; btn_data->drawable = btn_def->drawable; btn_data->mnemonic = btn_def->mnemonic; btn_data->mnemonic_instance = btn_def->mnemonic_instance; XinWindowHotkeySet( itf_win, btn_data->mnemonic ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( btn_def->font ) XinFontCopy( &btn_data->font, btn_def->font ); } #ifdef XI_USE_XVT else { if ( btn_def->font_id ) btn_data->font = XinFontXvtConvert( btn_def->font_id ); } #endif strcpy( btn_data->text, btn_def->text ); assign_rectangles( button->itf, &btn_data->xi_rct, &btn_data->rct, &btn_def->xi_rct, &btn_def->pixel_rect ); button->v.btn = btn_data; xi_button_rect_calc( button, button->parent->nbr_children ); rct = btn_data->rct; #ifdef XI_USE_XVT if ( !xi_get_native_controls( button ) ) xi_invalidate_rect( itf_win, &rct ); else { XinWindowDef Def; MEMCLEAR( Def ); Def.control_id = xi_obj_def->cid; switch ( btn_def->type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: Def.type = XinWindowTypeButton; break; case XIBT_RADIOBTN: case XIBT_TABBTN: Def.type = XinWindowTypeRadioButton; break; case XIBT_CHECKBOX: Def.type = XinWindowTypeCheckBox; break; } Def.border_style = XinBorderFixed; Def.p_rect = &rct; Def.visible = ( BOOLEAN ) ( ( btn_def->attrib & XI_ATR_VISIBLE ) != 0 ); Def.enabled = ( BOOLEAN ) ( ( btn_def->attrib & XI_ATR_ENABLED ) != 0 ); Def.parent = itf_win; Def.title = btn_data->text; Def.back_color = button->itf->v.itf->back_color; if ( btn_data->font ) XinFontCopy( &Def.font, btn_data->font ); else if ( button->itf->v.itf->font ) XinFontCopy( &Def.font, button->itf->v.itf->font ); else Def.font = xi_get_system_font(); btn_data->btnctl = XinWindowCreate( &Def ); if ( btn_def->checked && Def.type == XinWindowTypeCheckBox ) XinWindowCheckBox( btn_data->btnctl, TRUE ); } #else xi_invalidate_rect( itf_win, &rct ); #endif xi_add_to_parent_list( button, -1 ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20052, XinSeverityFatal, 0L ); } /* ------------------------------------------------------------------------ */ /* form_create */ /* ------------------------------------------------------------------------ */ static void form_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * form ) { XI_FORM_DATA *form_data; XI_FORM_DEF *form_def; form_def = xi_obj_def->v.form; form_data = ( XI_FORM_DATA * ) xi_tree_malloc( sizeof( XI_FORM_DATA ), ( char * ) form ); form_data->attrib = XI_ATR_VISIBLE | XI_ATR_ENABLED; form_data->tab_cid = form_def->tab_cid; form->v.form = form_data; xi_add_to_parent_list( form, -1 ); create_children( xi_obj_def, form, FALSE ); } /* ------------------------------------------------------------------------ */ /* field_create */ /* ------------------------------------------------------------------------ */ static void field_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * field ) { STX_DEF stxdef; XI_FIELD_DATA *field_data; XI_FIELD_DEF *xi_fd; int btn_dim_x; int btn_dim_x2; int fu_width; int fu_height; int edit_height; int btn_space; XinWindow itf_win; int leading, ascent, descent, font_height; itf_win = field->itf->v.itf->xin_win; fu_width = xi_get_fu_width( field->itf ); fu_height = xi_get_fu_height( field->itf ); xi_fd = xi_obj_def->v.field; if ( xi_fd->button_width > 0 ) { btn_dim_x = xi_fd->button_width; if (btn_dim_x < 6) btn_dim_x = 6; } else { btn_dim_x = ( fu_height * XI_FU_MULTIPLE ) / fu_width; /* btn_dim_x is actual width of button */ #if XIWS != XIWS_WM /* make buttons 70% wide as high */ btn_dim_x = ( int ) ( ( long ) btn_dim_x * 83L / 100L ); #endif } btn_space = btn_dim_x / 6; /* btn_dim_x2 is the button width + space, rounded up to */ /* the next even form unit */ btn_dim_x2 = btn_dim_x + btn_space; btn_dim_x2 = ( ( btn_dim_x2 + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; if (xi_fd->button_width == 0) btn_dim_x = ( int ) ( ( ( long ) btn_dim_x * fu_width ) / XI_FU_MULTIPLE ); btn_dim_x2 = ( int ) ( ( ( long ) btn_dim_x2 * fu_width ) / XI_FU_MULTIPLE ); MEMCLEAR( stxdef ); stxdef.cid = xi_obj_def->cid; stxdef.pnt = xi_fd->pixel_origin; if ( stxdef.pnt.v == 0 && stxdef.pnt.h == 0 ) { stxdef.pnt = xi_fd->pnt; xi_fu_to_pu( field->itf, &stxdef.pnt, 1 ); } stxdef.pixel_width = xi_fd->pixel_width; if ( stxdef.pixel_width == 0 ) stxdef.pixel_width = xi_fd->field_width * fu_width / XI_FU_MULTIPLE; stxdef.xi_rct = xi_fd->xi_rct; field_data = ( XI_FIELD_DATA * ) xi_tree_malloc( sizeof( XI_FIELD_DATA ), ( char * ) field ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( xi_fd->font ) { XinFontCopy( &stxdef.font, xi_fd->font ); field_data->font_set = TRUE; } } #ifdef XI_USE_XVT else { if ( xi_fd->font_id ) { stxdef.font = XinFontXvtConvert( xi_fd->font_id ); field_data->font_set = TRUE; } } #endif if ( !stxdef.font ) { if ( field->itf->v.itf->font ) { stxdef.font = field->itf->v.itf->font; field_data->font_set = FALSE; } else { stxdef.font = xi_get_system_font( ); field_data->font_set = FALSE; } } field_data->rct.top = stxdef.pnt.v; field_data->rct.left = stxdef.pnt.h; field_data->rct.right = stxdef.pnt.h + stxdef.pixel_width; field_data->rct.bottom = stxdef.pnt.v + fu_height; XinWindowFontMap( itf_win, stxdef.font ); XinFontMetricsGet( stxdef.font, &leading, &ascent, &descent ); font_height = ascent + leading + descent; edit_height = font_height + ( 2 * EDIT_BORDER_WIDTH_Y ) + ( 2 * EDIT_BORDER_SPACE_Y ); if ( !( xi_fd->xi_rct.top || xi_fd->xi_rct.bottom || xi_fd->xi_rct.left || xi_fd->xi_rct.right ) ) { if ( xi_fd->button ) { field_data->btn_rct.top = stxdef.pnt.v; if ( xi_fd->button_on_left ) { field_data->btn_rct.left = stxdef.pnt.h; field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; if (field_data->no_button_space == XinFlagFalse || (field_data->no_button_space == XinFlagNotSet && !xi_get_pref( XI_PREF_NO_BUTTON_SPACE ))) { if ( xi_fd->pixel_button_distance ) stxdef.pnt.h = field_data->btn_rct.right + xi_fd->pixel_button_distance; else stxdef.pnt.h += btn_dim_x2; } } else { #if XIWS == XIWS_WM BOOLEAN b; b = ( BOOLEAN ) ( xi_fd->attrib & XI_ATR_BORDER ); field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width + ( b ? 24 : 8 ); field_data->btn_rct.right = field_data->btn_rct.left + 8; #endif #if XIWS != XIWS_WM /* TODO problem with this code */ /* TODO Need a boolean - place button next to field */ /* TODO Need to handle correctly if use a button on a field with xi_rct * specified */ if ( xi_fd->pixel_button_distance ) { field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width + xi_fd->pixel_button_distance; field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; } else { int right; right = stxdef.pnt.h + stxdef.pixel_width + btn_dim_x2; /* convert to form units */ right = ( int ) ( ( ( long ) right * XI_FU_MULTIPLE ) / fu_width ); /* round up to nearest FU multiple */ right = ( ( right + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; /* convert to pixels */ right = ( int ) ( ( ( long ) right * fu_width ) / XI_FU_MULTIPLE ); field_data->btn_rct.right = right; field_data->btn_rct.left = right - btn_dim_x; } #endif } } } else { field_data->rct = xi_fd->xi_rct; xi_fu_to_pu( field->itf, ( XinPoint * ) & field_data->rct, 2 ); if ( xi_fd->button ) { field_data->btn_rct = xi_fd->xi_rct; xi_fu_to_pu( field->itf, ( XinPoint * ) & field_data->btn_rct, 2 ); if ( xi_fd->button_on_left ) { XinPoint p; p.h = btn_dim_x2; xi_pu_to_fu( field->itf, &p, 1 ); field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; if (field_data->no_button_space == XinFlagFalse || (field_data->no_button_space == XinFlagNotSet && !xi_get_pref( XI_PREF_NO_BUTTON_SPACE ))) { stxdef.xi_rct.left += p.h; stxdef.xi_rct.right += p.h; } } else { int right; right = field_data->btn_rct.right + btn_space + btn_dim_x2; /* convert to form units */ right = ( int ) ( ( ( long ) right * XI_FU_MULTIPLE ) / fu_width ); /* round up to nearest FU multiple */ right = ( ( right + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; /* convert to pixels */ right = ( int ) ( ( ( long ) right * fu_width ) / XI_FU_MULTIPLE ); field_data->btn_rct.right = right; field_data->btn_rct.left = right - btn_dim_x; } } } field_data->btn_rct.bottom = field_data->btn_rct.top + edit_height; stxdef.pix_char_width = fu_width; stxdef.attrib = xi_fd->attrib; stxdef.text_size = xi_fd->text_size; stxdef.back_color = xi_fd->back_color; stxdef.enabled_color = xi_fd->enabled_color; stxdef.disabled_color = xi_fd->disabled_color; stxdef.disabled_back_color = xi_fd->disabled_back_color; stxdef.active_color = xi_fd->active_color; stxdef.active_back_color = xi_fd->active_back_color; stxdef.hilight_color = xi_fd->hilight_color; stxdef.shadow_color = xi_fd->shadow_color; stxdef.stx_cb = xi_stx_cb; stxdef.app_data = ( long ) ( field ); stxdef.parent = ( char * ) field_data; stxdef.well = xi_fd->well; stxdef.platform = xi_fd->platform; stxdef.auto_tab = xi_fd->auto_tab; stxdef.scroll_bar = xi_fd->scroll_bar; stxdef.cr_ok = xi_fd->cr_ok; stxdef.var_len_text = xi_fd->var_len_text; stxdef.parent_obj = field; stxdef.button = xi_fd->button; stxdef.button_on_left = xi_fd->button_on_left; stxdef.button_rect = field_data->btn_rct; stxdef.no_button_space = xi_fd->no_button_space; stxdef.button_width = xi_fd->button_width; /* The stx_create() can change the field button rect if the button goes inside the field area. */ field_data->stx = stx_create( itf_win, &stxdef, &field_data->btn_rct ); field_data->tab_cid = xi_fd->tab_cid; field_data->button = xi_fd->button; field_data->button_on_left = xi_fd->button_on_left; field_data->no_button_space = xi_fd->no_button_space; field_data->icon_rid = xi_fd->icon_rid; field_data->button_bitmap = xi_bitmap_copy( xi_fd->button_bitmap ); field_data->button_width = xi_fd->button_width; field_data->well = xi_fd->well; field_data->platform = xi_fd->platform; field_data->xi_rct = xi_fd->xi_rct; field_data->xi_pnt = xi_fd->pnt; field_data->field_width = xi_fd->field_width; field_data->var_len_text = xi_fd->var_len_text; field_data->mnemonic = xi_fd->mnemonic; XinWindowHotkeySet( itf_win, field_data->mnemonic ); field->v.field = field_data; xi_add_to_parent_list( field, -1 ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20053, XinSeverityFatal, 0L ); } void xi_field_set_rect_internal( XI_OBJ *field_obj, XinRect *rect ) { XI_FIELD_DATA *field_data; int btn_dim_x; int btn_dim_x2; int fu_width; int fu_height; int edit_height; int btn_space; XinWindow itf_win; XinRect stx_rect; int leading, ascent, descent, font_height; field_data = field_obj->v.field; itf_win = field_obj->itf->v.itf->xin_win; fu_width = xi_get_fu_width( field_obj->itf ); fu_height = xi_get_fu_height( field_obj->itf ); if ( field_data->button_width > 0 ) { btn_dim_x = field_data->button_width; if (btn_dim_x < 6) btn_dim_x = 6; } else { btn_dim_x = ( fu_height * XI_FU_MULTIPLE ) / fu_width; /* btn_dim_x is actual width of button */ #if XIWS != XIWS_WM /* make buttons 70% wide as high */ btn_dim_x = ( int ) ( ( long ) btn_dim_x * 83L / 100L ); #endif } btn_space = btn_dim_x / 6; /* btn_dim_x2 is the button width + space, rounded up to */ /* the next even form unit */ btn_dim_x2 = btn_dim_x + btn_space; btn_dim_x2 = ( ( btn_dim_x2 + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; if (field_data->button_width == 0) btn_dim_x = ( int ) ( ( ( long ) btn_dim_x * fu_width ) / XI_FU_MULTIPLE ); btn_dim_x2 = ( int ) ( ( ( long ) btn_dim_x2 * fu_width ) / XI_FU_MULTIPLE ); XinWindowFontMap( itf_win, xi_text_font_get( stx_xi_text_get( field_data->stx ) ) ); XinFontMetricsGet( xi_text_font_get( stx_xi_text_get( field_data->stx ) ), &leading, &ascent, &descent ); font_height = ascent + leading + descent; edit_height = font_height + ( 2 * EDIT_BORDER_WIDTH_Y ) + ( 2 * EDIT_BORDER_SPACE_Y ); field_data->rct = *rect; stx_rect = *rect; if ( field_data->button ) { field_data->btn_rct = *rect; if ( field_data->button_on_left ) { XinPoint p; p.h = btn_dim_x2; xi_pu_to_fu( field_obj->itf, &p, 1 ); field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; if (field_data->no_button_space == XinFlagFalse || (field_data->no_button_space == XinFlagNotSet && !xi_get_pref( XI_PREF_NO_BUTTON_SPACE ))) { stx_rect.left += p.h; stx_rect.right += p.h; } } else { int right; right = field_data->btn_rct.right + btn_space + btn_dim_x2; /* convert to form units */ right = ( int ) ( ( ( long ) right * XI_FU_MULTIPLE ) / fu_width ); /* round up to nearest FU multiple */ right = ( ( right + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; /* convert to pixels */ right = ( int ) ( ( ( long ) right * fu_width ) / XI_FU_MULTIPLE ); field_data->btn_rct.right = right; field_data->btn_rct.left = right - btn_dim_x; } } field_data->btn_rct.bottom = field_data->btn_rct.top + edit_height; /* The stx_set_rect() can change the field button rect if the button goes inside the field area. */ stx_set_rect( itf_win, field_data->stx, &stx_rect, &field_data->btn_rct ); { XinRect empty_rect = {0,0,0,0}; XinPoint empty_point = { 0,0 } ; field_data->xi_rct = empty_rect; field_data->xi_pnt = empty_point; } } /* ------------------------------------------------------------------------ */ /* text_create */ /* ------------------------------------------------------------------------ */ static void text_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * text ) { XI_TEXT_DATA *text_data; XI_TEXT_DEF *text_def = xi_obj_def->v.text; text_data = ( XI_TEXT_DATA * ) xi_tree_malloc( sizeof( XI_TEXT_DATA ), text ); text_data->attrib = text_def->attrib; assign_rectangles( text->itf, &text_data->xi_rct, &text_data->rct, &text_def->xi_rct, &text_def->pixel_rect ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( text_def->font ) XinFontCopy( &text_data->font, text_def->font ); } #ifdef XI_USE_XVT else { if ( text_def->font_id ) text_data->font = XinFontXvtConvert( text_def->font_id ); } #endif text_data->text = ( char * ) xi_tree_malloc( strlen( text_def->text ) + 1, text ); strcpy( text_data->text, text_def->text ); text_data->fore_color = text_def->fore_color; text_data->back_color = text_def->back_color; text_data->mnemonic = text_def->mnemonic; text_data->mnemonic_instance = text_def->mnemonic_instance; text->v.text = text_data; xi_invalidate_rect( text->itf->v.itf->xin_win, &text_data->rct ); xi_add_to_parent_list( text, -1 ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20055, XinSeverityFatal, 0L ); } /* ------------------------------------------------------------------------ */ /* group_create */ /* ------------------------------------------------------------------------ */ static void group_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * group, BOOLEAN creating_list ) { XI_GROUP_DEF *group_def = xi_obj_def->v.group; XI_GROUP_DATA *group_data; group_data = ( XI_GROUP_DATA * ) xi_tree_malloc( sizeof( XI_GROUP_DATA ), group ); group_data->nbr_cids = group_def->nbr_cids; group_data->cidlist = ( int * ) xi_tree_malloc( sizeof( int ) * group_def->nbr_cids, group_data ); memcpy( ( char * ) group_data->cidlist, ( char * ) group_def->cids, sizeof( int ) * group_def->nbr_cids ); group->v.group = group_data; xi_add_to_parent_list( group, -1 ); create_children( xi_obj_def, group, creating_list ); } /* ------------------------------------------------------------------------ */ /* column_create */ /* ------------------------------------------------------------------------ */ static void column_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * obj, BOOLEAN creating_list ) { LM_COLUMN_DEF lm_column_def; XI_COLUMN_DATA *column_data; XI_COLUMN_DEF *col_def; XI_OBJ **column; int i; int pixel_width; LM_DATA *lmp; XI_LIST_DATA *list_data; int char_pixel_width; list_data = obj->parent->v.list; lmp = ( LM_DATA * ) list_data->lm; MEMCLEAR( lm_column_def ); column_data = ( XI_COLUMN_DATA * ) xi_tree_malloc( sizeof( XI_COLUMN_DATA ), ( char * ) obj ); col_def = xi_obj_def->v.column; lm_column_def.attrib = col_def->attrib; char_pixel_width = xi_get_fu_width( obj->itf ); if ( col_def->pixel_width == 0 ) { if ( xi_get_xil_pref( obj->parent->parent ) ) col_def->pixel_width = col_def->width * char_pixel_width; else col_def->pixel_width = col_def->width * char_pixel_width / XI_FU_MULTIPLE; } pixel_width = col_def->pixel_width; if ( list_data->width ) { pixel_width = lmp->pixel_width; for ( i = 0; i < min( lmp->fixed_columns, lmp->nbr_columns ); ++i ) pixel_width -= lmp->lm_column_data[i]->pix_width; pixel_width = min( pixel_width, col_def->pixel_width ); } if ( col_def->position ) lm_column_def.position = min( col_def->position, lmp->nbr_columns ); else { for ( lm_column_def.position = i = 0, column = obj->parent->children; i < obj->parent->nbr_children; i++, column++ ) { if ( ( *column )->type != XIT_COLUMN ) XinError( 20015, XinSeverityFatal, 0L ); if ( ( *column )->v.column->sort_number < col_def->sort_number ) lm_column_def.position++; } } lm_column_def.pix_width = pixel_width; lm_column_def.text_size = col_def->text_size; if ( lm_column_def.text_size < 2 ) lm_column_def.text_size = 2; lm_column_def.heading_text = col_def->heading_text; lm_column_def.center_heading = col_def->center_heading; #if XIWS != XIWS_WM lm_column_def.heading_well = col_def->heading_well; lm_column_def.heading_platform = col_def->heading_platform; lm_column_def.column_well = col_def->column_well; lm_column_def.column_platform = col_def->column_platform; #else lm_column_def.heading_well = FALSE; lm_column_def.heading_platform = FALSE; lm_column_def.column_well = FALSE; lm_column_def.column_platform = FALSE; #endif if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( col_def->font ) XinFontCopy( &lm_column_def.font, col_def->font ); } #ifdef XI_USE_XVT else { if ( col_def->font_id ) lm_column_def.font = XinFontXvtConvert( col_def->font_id ); } #endif lm_column_def.icon_rid = col_def->icon_rid; lm_column_def.icon_x = col_def->icon_x; lm_column_def.icon_y = col_def->icon_y; lm_column_def.bitmap = xi_bitmap_copy( col_def->bitmap ); lm_column_def.size_rows = col_def->size_rows; lm_column_def.suppress_update_heading = col_def->suppress_update_heading; lm_column_def.suppress_update_cells = col_def->suppress_update_cells; lm_column_def.vertical_align_center = col_def->vertical_align_center; lm_column_def.vertical_align_bottom = col_def->vertical_align_bottom; lm_column_def.wrap_text = col_def->wrap_text; if ( col_def->wrap_text ) if ( lmp->max_lines_in_cell == 1 ) lmp->max_lines_in_cell = 5; lm_column_def.wrap_text_scrollbar = col_def->wrap_text_scrollbar; lm_column_def.cr_ok = col_def->cr_ok; lm_column_def.var_len_text = col_def->var_len_text; lm_column_def.auto_tab = col_def->auto_tab; lm_column_def.icon_mode = col_def->icon_mode; obj->v.column = column_data; column_data->sort_number = col_def->sort_number; xi_add_to_parent_list( obj, lm_column_def.position ); lm_create_column( obj->parent->v.list->lm, &lm_column_def, ( BOOLEAN ) ( !creating_list ), TRUE ); if ( xi_obj_def->nbr_children != 0 ) XinError( 20056, XinSeverityFatal, 0L ); if ( list_data->width == 0 && list_data->sb_win ) xi_move_list_scroll_bar( obj->parent ); } /* ------------------------------------------------------------------------ */ /* list_data_create */ /* ------------------------------------------------------------------------ */ static void list_data_create( XI_LIST_DEF * list_def, XI_OBJ * list ) { XI_LIST_DATA *list_data; list_data = ( XI_LIST_DATA * ) xi_tree_malloc( sizeof( XI_LIST_DATA ), ( char * ) list ); list->v.list = list_data; list_data->xi_pnt = list_def->xi_pnt; list_data->height = list_def->height; list_data->one_row_list = list_def->one_row_list; list_data->start_percent = list_def->start_percent; list_data->horz_sync_list = list_def->horz_sync_list; list_data->vert_sync_list = list_def->vert_sync_list; list_data->row_focus_border = list_def->row_focus_border; list_data->row_focus_border_color = list_def->row_focus_border_color; list_data->max_lines_in_cell = list_def->max_lines_in_cell; list_data->single_select = list_def->single_select; list_data->scroll_on_thumb_track = list_def->scroll_on_thumb_track; if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { if ( list_def->font ) XinFontCopy( &list_data->font, list_def->font ); } #ifdef XI_USE_XVT else { if ( list_def->font_id ) list_data->font = XinFontXvtConvert( list_def->font_id ); } #endif if ( !list_data->font ) { if ( list->itf->v.itf->font ) XinFontCopy( &list_data->font, list->itf->v.itf->font ); else XinFontCopy( &list_data->font, xi_get_system_font( ) ); } } /* ------------------------------------------------------------------------ */ /* list_module_def_create */ /* ------------------------------------------------------------------------ */ static void list_module_def_create( LM_DEF * lm_def, XI_LIST_DEF * list_def, XI_OBJ * list ) { /* create LM */ XI_LIST_DATA *list_data = list->v.list; MEMCLEAR( *lm_def ); lm_def->cid = list->cid; lm_def->pnt = list_def->xi_pnt; if ( xi_get_xil_pref( list->parent ) ) lm_def->pixel_height = list_def->height; else { if ( list_def->pixel_origin.h || list_def->pixel_origin.v ) lm_def->pnt = list_def->pixel_origin; else { lm_def->pnt = list_def->xi_pnt; xi_fu_to_pu( list->itf, &lm_def->pnt, 1 ); } if ( list_def->pixel_height ) lm_def->pixel_height = list_def->pixel_height; else lm_def->pixel_height = list_def->height * xi_get_fu_height( list->itf ) / XI_FU_MULTIPLE; } lm_def->pix_char_width = xi_get_fu_width( list->itf ); lm_def->attrib = list_def->attrib; lm_def->back_color = list_def->back_color; lm_def->enabled_color = list_def->enabled_color; lm_def->disabled_color = list_def->disabled_color; lm_def->disabled_back_color = list_def->disabled_back_color; lm_def->active_color = list_def->active_color; lm_def->active_back_color = list_def->active_back_color; lm_def->white_space_color = list_def->white_space_color; if ( !lm_def->white_space_color ) lm_def->white_space_color = XI_COLOR_LTGRAY; lm_def->rule_color = list_def->rule_color; if ( !lm_def->rule_color ) lm_def->rule_color = XI_COLOR_BLACK; lm_def->lm_cb = xi_lm_cb; if ( list_data->font ) lm_def->font = list_data->font; else if ( list->itf->v.itf->font ) lm_def->font = list->itf->v.itf->font; else lm_def->font = xi_get_system_font( ); if ( list_def->font ) lm_def->is_list_font = TRUE; if ( list_def->font_id ) lm_def->is_list_font = TRUE; lm_def->no_heading = list_def->no_heading; lm_def->one_row_list = list_def->one_row_list; lm_def->sizable_columns = list_def->sizable_columns; lm_def->movable_columns = list_def->movable_columns; lm_def->fixed_columns = list_def->fixed_columns; #if XIWS == XIWS_WM lm_def->min_cell_height = 8; lm_def->min_heading_height = list_def->min_heading_height; #else lm_def->min_cell_height = list_def->min_cell_height; lm_def->min_heading_height = list_def->min_heading_height; #endif lm_def->no_horz_lines = list_def->no_horz_lines; lm_def->no_vert_lines = list_def->no_vert_lines; lm_def->first_vis_column = list_def->first_vis_column; lm_def->drop_and_delete = list_def->drop_and_delete; lm_def->select_cells = list_def->select_cells; lm_def->get_all_records = list_def->get_all_records; lm_def->resize_with_window = list_def->resize_with_window; lm_def->horz_sync_list = list_def->horz_sync_list; lm_def->vert_sync_list = list_def->vert_sync_list; lm_def->row_focus_border = list_def->row_focus_border; lm_def->row_focus_border_color = list_def->row_focus_border_color; lm_def->single_select = list_def->single_select; lm_def->retain_back_color_on_select = list_def->retain_back_color_on_select; lm_def->drag_and_drop_rows = list_def->drag_and_drop_rows; lm_def->drag_rows_autoscroll = list_def->drag_rows_autoscroll; lm_def->button_on_cell_focus = list_def->button_on_cell_focus; lm_def->position_by_typing_cid = list_def->position_by_typing_cid; if ( xi_get_xil_pref( list->parent ) ) lm_def->pixel_width = list_def->width; else { if ( list_def->pixel_width ) lm_def->pixel_width = list_def->pixel_width; else { XinPoint p; p.h = list_def->width; p.v = 0; xi_fu_to_pu( list->itf, &p, 1 ); lm_def->pixel_width = p.h; } lm_def->max_lines_in_cell = list_def->max_lines_in_cell; } } /* ------------------------------------------------------------------------ */ /* lm_get_width */ /* ------------------------------------------------------------------------ */ static int lm_get_width( XI_OBJ_DEF * obj_def, int fu_width, int columns, short *fixed_cols ) { XI_LIST_DEF *list_def = obj_def->v.list; int i; int number_fixed_columns; int fixed_column_width; int max_movable_column; int movable_column_width; int total_columns; int width; XI_OBJ_DEF **column; int list_pix_width; /* calculate specified width of list */ if ( xi_def_get_xil_pref( obj_def->parent ) ) list_pix_width = obj_def->v.list->width; else { if ( obj_def->v.list->pixel_width ) list_pix_width = obj_def->v.list->pixel_width; else list_pix_width = obj_def->v.list->width * fu_width / XI_FU_MULTIPLE; } /* calculate all pixel widths */ column = obj_def->children; total_columns = obj_def->nbr_children; /* If it is an empty list, just return */ if ( total_columns <= 0 ) return 0; for ( i = 0; i < total_columns; ++column, ++i ) { XI_COLUMN_DEF *col = ( *column )->v.column; if ( !col->pixel_width ) { if ( xi_def_get_xil_pref( obj_def->parent ) ) col->pixel_width = col->width * fu_width; else col->pixel_width = col->width * fu_width / XI_FU_MULTIPLE; } } /* find sum of fixed column widths */ number_fixed_columns = min( list_def->fixed_columns, total_columns - 1 ); column = obj_def->children; fixed_column_width = 0; for ( i = 0; i < number_fixed_columns; ++column, ++i ) { fixed_column_width += ( *column )->v.column->pixel_width + lm_get_col_spacing( ); if ( fixed_column_width >= list_pix_width ) { number_fixed_columns = i; fixed_column_width -= ( *column )->v.column->pixel_width + lm_get_col_spacing( ); break; } } /* remove extra internal rule width */ fixed_column_width -= lm_get_col_spacing( ); /* find largest moveable column width, and sum of movable column widths */ max_movable_column = 0; movable_column_width = 0; if ( columns <= number_fixed_columns ) { columns = number_fixed_columns; /* if we have any movable columns, columns must be at least */ /* # fixed_columns + 1 */ if ( total_columns > number_fixed_columns ) columns++; } for ( ; i < columns; ++column, ++i ) { XI_COLUMN_DEF *col = ( *column )->v.column; movable_column_width += col->pixel_width; max_movable_column = max( max_movable_column, col->pixel_width ); } for ( ; i < total_columns; ++column, ++i ) max_movable_column = max( max_movable_column, ( *column )->v.column->pixel_width ); /* add the internal column rules for movable columns */ if ( columns > number_fixed_columns + 1 ) movable_column_width += ( columns - number_fixed_columns - 1 ) * lm_get_col_spacing( ); /* use either the sum of the movable columns, or the largest movable column */ movable_column_width = max( movable_column_width, max_movable_column ); /* calculate width */ width = 2 * BORDER_WIDTH + fixed_column_width + movable_column_width; /* add the rule between fixed & movable columns */ if ( columns > number_fixed_columns && number_fixed_columns > 0 ) width += lm_get_col_spacing( ); *fixed_cols = number_fixed_columns; return width; } /* ------------------------------------------------------------------------ */ /* xi_list_def_get_client_width */ /* ------------------------------------------------------------------------ */ int xi_list_def_get_client_width( XI_OBJ_DEF * obj_def, int columns ) { XinFont *font; int width; short temp; font = xi_def_get_font( obj_def ); width = xi_get_fu_width_font( font ); XinFontDestroy( font ); return lm_get_width( obj_def, width, columns, &temp ); } /* ------------------------------------------------------------------------ */ /* xi_list_def_get_outer_width */ /* ------------------------------------------------------------------------ */ int xi_list_def_get_outer_width( XI_OBJ_DEF * obj_def, int columns ) { int result; result = xi_list_def_get_client_width( obj_def, columns ); if ( obj_def->v.list->scroll_bar ) result += ( int ) xi_get_pref( XI_PREF_SB_OFFSET ) + ( int ) xi_get_pref( XI_PREF_SB_WIDTH ); #if XIWS == XIWS_WM return result; #else return result + 2 * BORDER_WIDTH; #endif } /* ------------------------------------------------------------------------ */ /* list_create */ /* ------------------------------------------------------------------------ */ static void list_create( XI_OBJ_DEF * xi_obj_def, XI_OBJ * list ) { XI_LIST_DEF *list_def = xi_obj_def->v.list; XI_LIST_DATA *list_data; LM_DEF lm_def; int i, min_height; XinRect rct, min_rct; XinWindow itf_win; BOOLEAN save_or; itf_win = list->itf->v.itf->xin_win; list_data_create( list_def, list ); list_data = list->v.list; list_module_def_create( &lm_def, list_def, list ); if ( list_def->resize_with_window && list->parent && list->parent->itf->v.itf->xin_win ) { XinRect cr; XinWindowRectGet( list->parent->itf->v.itf->xin_win, &cr ); save_or = xi_obj_def->v.list->one_row_list; xi_obj_def->v.list->one_row_list = TRUE; xi_get_def_rect( xi_obj_def, &min_rct ); xi_obj_def->v.list->one_row_list = save_or; min_height = min_rct.bottom - min_rct.top; lm_def.pixel_height = cr.bottom - lm_def.pnt.v; if ( lm_def.pixel_width ) lm_def.pixel_height -= ( int ) xi_get_pref( XI_PREF_SB_HEIGHT ); lm_def.pixel_height = max( lm_def.pixel_height, min_height ); if ( lm_def.pixel_width ) { lm_def.pixel_width = cr.right - lm_def.pnt.h - 2 * BORDER_WIDTH; if ( list_def->scroll_bar ) lm_def.pixel_width -= ( int ) xi_get_pref( XI_PREF_SB_WIDTH ); } } if ( lm_def.pixel_width ) { int min_width; min_width = lm_get_width( xi_obj_def, lm_def.pix_char_width, 1, &lm_def.fixed_columns ); /* insure minimum size */ if ( min_width > lm_def.pixel_width ) lm_def.pixel_width = min_width; } lm_def.list_obj = list; lm_def.itf_obj = list->itf; lm_def.parent = ( char * ) list_data; list_data->width = lm_def.pixel_width; /* TODO calculate and set realized_rows_array_len TODO also set nbr_rows, if * user specified a specific nbr of rows. */ list_data->lm = lm_create( itf_win, &lm_def, list_data ); list_data->scroll_bar_button = list_def->scroll_bar_button; /* Initialize focus obj data. Use list object for defaults. */ list_data->focus_cell_array[0] = *list; list_data->focus_cell_array[0].parent = list; list_data->focus_cell_array[0].type = XIT_CELL; list_data->focus_cell_array[0].v.cell.row = list_data->focus_cell_array[0].v.cell.column = 0; list_data->focus_cell_array[0].v.cell.is_vert_scrolled = FALSE; for ( i = 1; i < FOCUS_CELL_ARRAY_LEN; ++i ) list_data->focus_cell_array[i] = list_data->focus_cell_array[0]; list_data->focus_cell = &list_data->focus_cell_array[0]; list_data->tab_cid = list_def->tab_cid; list_data->scroll_bar = list_def->scroll_bar; xi_add_to_parent_list( list, -1 ); create_children( xi_obj_def, list, TRUE ); if ( list_def->scroll_bar ) { if ( list_data->sb_win ) xi_move_list_scroll_bar( list ); else { XinRect rct; long attrib; attrib = lm_get_attrib( list_data->lm, LM_LIST, 0, 0, FALSE ); xi_get_sb_rect( list, &rct ); { XinWindowDef Def; MEMCLEAR( Def ); Def.control_id = list->cid; Def.type = XinWindowTypeVerticalScrollBar; Def.p_rect = &rct; Def.title = ""; Def.visible = ( BOOLEAN ) ( ( attrib & XI_ATR_VISIBLE ) != 0 ); Def.enabled = TRUE; Def.parent = itf_win; list_data->sb_win = XinWindowCreate( &Def ); } if ( !( attrib & XI_ATR_ENABLED ) ) XinWindowEnable( list_data->sb_win, FALSE ); xi_get_sb_rect( list, &rct ); if ( list_data->scroll_bar_button ) xi_invalidate_rect( list->itf->v.itf->xin_win, &list_data->sbb_rct ); } } if ( lm_def.pixel_width != 0 ) { unsigned long attrib; attrib = lm_get_attrib( list_data->lm, LM_LIST, 0, 0, FALSE ); xi_get_hsb_rect( list, &rct ); { XinWindowDef Def; MEMCLEAR( Def ); Def.control_id = list->cid + HSCROLL_CID_CONST; Def.type = XinWindowTypeHorizontalScrollBar; Def.p_rect = &rct; Def.title = ""; Def.visible = ( BOOLEAN ) ( ( attrib & XI_ATR_VISIBLE ) != 0 ); Def.enabled = TRUE; Def.parent = itf_win; list_data->hsb_win = XinWindowCreate( &Def ); } if ( !( attrib & XI_ATR_ENABLED ) ) XinWindowEnable( list_data->hsb_win, FALSE ); lm_set_hscroll_range( list_data->lm ); } xi_get_rect( list, &rct ); xi_inflate_rect( &rct, 8 ); xi_invalidate_rect( itf_win, &rct ); lm_set_hscroll_range( list->v.list->lm ); if ( xi_obj_def->v.list->first_vis_column ) { XinWindowPaintForce( itf_win ); xi_hscroll_internal( list, xi_obj_def->v.list->first_vis_column - lm_def.fixed_columns, 0 ); } } /* ------------------------------------------------------------------------ */ /* xi_create_internal */ /* ------------------------------------------------------------------------ */ /* xi_create_internal performs the following steps: 1. Copy the *_DEFs into *_DATAs 2. Call creation functions for LM, STX, buttons 3. Initialize event routing */ XI_OBJ * xi_create_internal( XI_OBJ * parent, XI_OBJ_DEF * xi_obj_def, BOOLEAN creating_list, BOOLEAN r4_api ) { XI_OBJ *obj; if ( !inited ) xi_init_internal( r4_api ); /* object data initialization common to all types */ obj = ( XI_OBJ * ) xi_tree_malloc( sizeof( XI_OBJ ), ( char * ) parent ); obj->parent = parent; obj->cid = xi_obj_def->cid; obj->type = xi_obj_def->type; obj->app_data = xi_obj_def->app_data; obj->app_data2 = xi_obj_def->app_data2; if (xi_obj_def->help_key != NULL) { obj->help_key = (char *)xi_tree_malloc( strlen( xi_obj_def->help_key ) + 1, obj ); strcpy( obj->help_key, xi_obj_def->help_key ); } else obj->help_key = NULL; if ( xi_obj_def->type != XIT_ITF ) { XinRect rct; XI_ITF_DATA *itf_data; obj->itf = parent->itf; xi_get_def_rect( xi_obj_def, &rct ); xi_pu_to_fu( NULL, ( XinPoint * ) & rct, 2 ); itf_data = obj->itf->v.itf; itf_data->max_xi_pnt.h = max( itf_data->max_xi_pnt.h, rct.right ); itf_data->max_xi_pnt.v = max( itf_data->max_xi_pnt.v, rct.bottom ); } else obj->itf = obj; switch ( xi_obj_def->type ) { case XIT_ITF: interface_create( xi_obj_def, obj ); break; case XIT_CONTAINER: container_create( xi_obj_def, obj ); break; case XIT_RECT: rectangle_create( xi_obj_def, obj ); break; case XIT_LINE: line_create( xi_obj_def, obj ); break; case XIT_BTN: button_create( xi_obj_def, obj ); break; case XIT_FORM: form_create( xi_obj_def, obj ); break; case XIT_FIELD: field_create( xi_obj_def, obj ); break; case XIT_LIST: list_create( xi_obj_def, obj ); break; case XIT_COLUMN: column_create( xi_obj_def, obj, creating_list ); break; case XIT_TEXT: text_create( xi_obj_def, obj ); break; case XIT_GROUP: group_create( xi_obj_def, obj, creating_list ); break; case XIT_CELL: case XIT_ROW: default: XinError( 20016, XinSeverityFatal, 0L ); } return obj; } void xi_close_window_internal( XI_OBJ * itf ) { if ( itf->v.itf->bitmap != NULL ) xi_bitmap_destroy( itf->v.itf->bitmap ); XinFontUnmap( xi_get_system_font() ); /* RGM: Unmap hack */ XinWindowDestroy( itf->v.itf->xin_win ); } static void xi_delete_internal( XI_OBJ * xi_obj, BOOLEAN recursive ) { XinRect rct; XI_OBJ_TYPE type = xi_obj->type; if ( xi_obj->itf->v.itf->focus_obj == xi_obj ) xi_obj->itf->v.itf->focus_obj = NULL; switch ( type ) { case XIT_FIELD: xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); stx_delete( xi_obj->v.field->stx, xi_obj->v.field->font_set ); break; case XIT_FORM: case XIT_CONTAINER: { XI_OBJ **objlist; int n; /* loop over sub-objects */ if ( !recursive ) { objlist = xi_get_member_list( xi_obj, &n ); for ( ; n > 0; n--, objlist++ ) xi_delete_internal( *objlist, TRUE ); break; } } case XIT_GROUP: break; case XIT_ITF: { XI_ITF_DATA *itf_data; itf_data = xi_obj->v.itf; if ( itf_data->in_callback ) { itf_data->closing = TRUE; XinWindowEnable( itf_data->xin_win, FALSE ); } else xi_close_window_internal( xi_obj ); return; } case XIT_LIST: { XI_LIST_DATA *list_data; list_data = xi_obj->v.list; xi_get_rect( xi_obj, &rct ); if ( list_data->scroll_bar ) XinWindowDestroy( list_data->sb_win ); if ( list_data->hsb_win ) XinWindowDestroy( list_data->hsb_win ); if ( list_data->font ) XinFontDestroy( list_data->font ); xi_inflate_rect( &rct, 8 ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); if ( !recursive ) lm_delete( list_data->lm ); else { LM_DATA *lmp = LMP( list_data->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( list_data->lm ); } break; } case XIT_COLUMN: { XI_LIST_DATA *list_data; int col_nbr; BOOLEAN move_hsb; list_data = xi_obj->parent->v.list; col_nbr = xi_obj_to_idx( xi_obj ); move_hsb = ( col_nbr < ( ( LM_DATA * ) ( list_data->lm ) )->fixed_columns ); if ( !recursive ) lm_delete_column( list_data->lm, col_nbr, TRUE ); if ( list_data->scroll_bar && ( !list_data->width ) ) xi_move_list_scroll_bar( xi_obj->parent ); if ( !recursive ) { if ( list_data->hsb_win && move_hsb ) { list_data->have_hsb_rct = FALSE; xi_move_list_hscroll_bar( xi_obj->parent ); } } break; } case XIT_TEXT: xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); if ( xi_obj->v.text->font ) XinFontDestroy( xi_obj->v.text->font ); break; case XIT_RECT: xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); if ( xi_obj->v.rect->bitmap != NULL ) xi_bitmap_destroy( xi_obj->v.rect->bitmap ); break; case XIT_LINE: xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); break; case XIT_BTN: if ( xi_obj->v.btn->btnctl ) XinWindowDestroy( xi_obj->v.btn->btnctl ); else { xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); } if ( xi_obj->v.btn->up_bitmap != NULL ) xi_bitmap_destroy( xi_obj->v.btn->up_bitmap ); if ( xi_obj->v.btn->down_bitmap != NULL ) xi_bitmap_destroy( xi_obj->v.btn->down_bitmap ); if ( xi_obj->v.btn->disabled_bitmap != NULL ) xi_bitmap_destroy( xi_obj->v.btn->disabled_bitmap ); break; default: XinError( 20017, XinSeverityFatal, 0L ); break; } if ( !recursive ) { xi_remove_from_parent_list( xi_obj ); if ( type == XIT_COLUMN ) /* an ugly hack */ { XI_LIST_DATA *list_data; list_data = xi_obj->parent->v.list; lm_make_rrr_room_pix( ( LM_DATA * ) list_data->lm, 0, FALSE ); } xi_tree_free( ( char * ) xi_obj ); } } void xi_delete( XI_OBJ * xi_obj ) { xi_delete_internal( xi_obj, FALSE ); } void xi_move_column_internal( XI_OBJ * column, int position, BOOLEAN in_hscrolling ) { XI_OBJ *list; XI_LIST_DATA *list_data; LM_DATA *lm_data; LM_COLUMN_DATA *col_data; LM_COLUMN_DEF lm_column_def; int col_nbr, i; BOOLEAN move_hsb = FALSE; int focus_row, focus_column; BOOLEAN v_scrolled; BOOLEAN redraw_row = FALSE; list = column->parent; list_data = list->v.list; lm_data = ( LM_DATA * ) list_data->lm; i = xi_obj_to_idx( column ); if ( lm_focus_cell_get( lm_data, &focus_row, &focus_column, &v_scrolled ) ) if ( focus_column == i && lm_data->row_focus_border ) redraw_row = TRUE; if ( list_data->hsb_win ) if ( i < lm_data->fixed_columns || position < lm_data->fixed_columns ) move_hsb = TRUE; if ( position == lm_data->fixed_columns && !in_hscrolling ) move_hsb = TRUE; col_nbr = xi_obj_to_idx( column ); col_data = lm_data->lm_column_data[col_nbr]; MEMCLEAR( lm_column_def ); lm_column_def.attrib = col_data->attrib; lm_column_def.position = position; lm_column_def.pix_width = col_data->pix_width; lm_column_def.text_size = col_data->text_size; lm_column_def.heading_text = ( char * ) xi_tree_malloc( strlen( col_data->heading_text ) + 1, list_data ); strcpy( lm_column_def.heading_text, col_data->heading_text ); lm_column_def.center_heading = col_data->center_heading; #if XIWS != XIWS_WM lm_column_def.heading_well = col_data->heading_well; lm_column_def.heading_platform = col_data->heading_platform; lm_column_def.column_well = col_data->column_well; lm_column_def.column_platform = col_data->column_platform; #else lm_column_def.heading_well = FALSE; lm_column_def.heading_platform = FALSE; lm_column_def.column_well = FALSE; lm_column_def.column_platform = FALSE; #endif lm_column_def.icon_rid = col_data->icon_rid; lm_column_def.icon_x = col_data->icon_x; lm_column_def.icon_y = col_data->icon_y; lm_column_def.bitmap = xi_bitmap_copy( col_data->bitmap ); lm_column_def.vertical_align_center = col_data->vertical_align_center; lm_column_def.vertical_align_bottom = col_data->vertical_align_bottom; lm_column_def.wrap_text = col_data->wrap_text; lm_column_def.wrap_text_scrollbar = col_data->wrap_text_scrollbar; lm_column_def.cr_ok = col_data->cr_ok; lm_column_def.var_len_text = col_data->var_len_text; lm_column_def.auto_tab = col_data->auto_tab; lm_column_def.icon_mode = col_data->icon_mode; if ( col_data->font ) XinFontCopy( &lm_column_def.font, col_data->font ); if ( col_nbr == focus_column ) xi_set_focus( list->itf ); lm_delete_column( ( LM ) lm_data, col_nbr, FALSE ); xi_remove_from_parent_list( column ); xi_add_to_parent_list( column, lm_column_def.position ); lm_create_column( ( LM ) lm_data, &lm_column_def, TRUE, in_hscrolling ); /* If column has focus, adjust focus cell value */ if ( col_nbr == focus_column ) { list_data->focus_cell->v.cell.column = position; xi_set_focus( list_data->focus_cell ); } if ( move_hsb ) { list->v.list->have_hsb_rct = FALSE; xi_move_list_hscroll_bar( column->parent ); } lm_set_hscroll_range( ( LM ) lm_data ); lm_set_hscroll_bar( ( LM ) lm_data ); if ( redraw_row && !v_scrolled ) lm_redraw_row( lm_data, focus_row, FALSE ); } void xi_move_column( XI_OBJ * column, int position ) { XI_OBJ *list; XI_LIST_DATA *list_data; LM_DATA *lm_data; int current_pos; list = column->parent; list_data = list->v.list; lm_data = ( LM_DATA * ) list_data->lm; current_pos = xi_obj_to_idx( column ); xi_move_column_internal( column, position, ( BOOLEAN ) ( current_pos >= lm_data->fixed_columns ) ); } BOOLEAN xi_is_auto_tab( XI_OBJ * xi_obj ) { if ( xi_obj->type == XIT_FIELD ) return ( ( STX_DATA * ) xi_obj->v.field->stx )->auto_tab; if ( xi_obj->type == XIT_COLUMN ) return LMP( xi_obj->parent->v.list->lm )-> lm_column_data[xi_obj_to_idx( xi_obj )]->auto_tab; return FALSE; } void xi_init_internal( BOOLEAN r4_api ) { if ( !inited ) { xi_set_pref( XI_PREF_R4_API, r4_api ); inited = TRUE; xi_init_sysvals( ); } }