/******************************************************************************* * 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 #include #endif #define MAXPIX 6000 #define VRCT_TO_PRCT( rp ) \ ( rp )->left -= cur_delta_x; \ ( rp )->right -= cur_delta_x; \ ( rp )->top -= cur_delta_y; \ ( rp )->bottom -= cur_delta_y; /* ERROR CODES 20000-20089 */ BOOLEAN xi_false = FALSE; void xi_finish_interface_create( XinWindow win ); extern XI_OBJ *xi_creating_itf; static int xi_send_event( XI_OBJ * xi_obj, XinEvent * ep, BOOLEAN do_subtree ); #ifndef NO_PRIMARY_SELECTION #if XIWS == XIWS_XM static XI_OBJ *rp_xi_obj = NULL; static void receive_primesel( Widget widget, XtPointer data, Atom * selection, Atom * type, XtPointer value, unsigned long *length, int *format ) { char *s; XinWindow win; char *p; /* printf("receive_primesel: ENTERED, widget %d, selection %d, type %d\n", * widget, *selection, *type); */ /* printf(" length %d, format %d\n", length, * *format); */ /* check if request for primary selection was successful */ if ( *selection != XA_PRIMARY || *type != XA_STRING || *format != 8 ) { /* printf("receive_primesel: get primary selection failed\n"); */ return; } /* allocate space and fill in text from selection value */ s = XinMemoryAlloc( *length + 1 ); /* Assertion for out of memory? */ strncpy( s, ( char * ) value, *length ); s[*length] = '\0'; /* printf("receive_primesel: primary selection text = '%s'\n", s); */ XtFree( ( char * ) value ); /* this must be freed with XtFree */ /* xvt_dm_post_note("Text from Primary selection is '%s'", s); */ if ( rp_xi_obj ) { win = xi_get_window( rp_xi_obj ); rp_xi_obj = NULL; for ( p = s; *p != '\0'; ++p ) { XinEvent ev; MEMCLEAR( ev ); ev.type = XinEventCharacter; ev.v.character.ch = ( unsigned char ) *p; xi_event( win, &ev ); XinWindowPaintForce( win ); } } XinMemoryFree( s ); } static void get_primary_selection( XI_OBJ * itf, XinWindow win ) { Widget widget; rp_xi_obj = itf; /* printf("get_primary_selection: ENTERED, win %d\n", win); */ /* request PRIMARY selection */ if ( rp_xi_obj) { widget = ( Widget ) XinWindowWidgetGet( win ); XtGetSelectionValue( widget, XA_PRIMARY, XA_STRING, receive_primesel, NULL, XtLastTimestampProcessed( XtDisplay( widget ) ) ); } /* printf("get_primary_selection: returning\n"); */ } #endif #endif BOOLEAN call_cb( XI_OBJ * itf, XI_EVENT * xiev ) { XI_ITF_DATA *itf_data; itf_data = itf->v.itf; itf_data->in_callback++; XinCoalesceInvalidates( itf_data->xin_win, TRUE ); ( *itf_data->xi_eh ) ( ( struct _xi_obj * ) itf, xiev ); #ifdef WINRUNNER xir_record( itf, xiev ); #endif if ( xi_is_itf( itf ) ) { XinCoalesceInvalidates( itf_data->xin_win, FALSE ); itf_data->in_callback--; if ( itf_data->in_callback == 0 && itf_data->closing ) { itf_data->closing = FALSE; xi_close_window_internal( itf ); return FALSE; } } return TRUE; } static long event_to_longchar( XinEvent * ep ) { long c = ep->v.character.ch; if ( ep->v.character.control ) c |= XI_MOD_CONTROL; if ( ep->v.character.shift ) c |= XI_MOD_SHIFT; if ( ep->v.character.alt ) c |= XI_MOD_ALT; return ( c ); } void xi_column_set_pixel_width( XI_OBJ * column, int width ) { int i; XI_LIST_DATA *list; LM_DATA *lm_data; list = column->parent->v.list; lm_data = ( LM_DATA * ) list->lm; if ( column->type != XIT_COLUMN ) XinError( 20010, XinSeverityFatal, 0L ); lm_column_set_pixel_width( list->lm, xi_obj_to_idx( column ), width ); if ( list->sb_win && ( !list->width ) ) xi_move_list_scroll_bar( column->parent ); i = xi_obj_to_idx( column ); if ( i < lm_data->fixed_columns && list->hsb_win ) xi_move_list_hscroll_bar( column->parent ); } void xi_set_column_width( XI_OBJ * column, int width ) { int width_in_chars; if ( xi_get_xil_pref( column->itf ) ) width_in_chars = width; else width_in_chars = width / XI_FU_MULTIPLE; xi_column_set_pixel_width( column, width_in_chars * ( ( LM_DATA * ) column->parent->v.list->lm ) ->pix_char_width ); } static XI_OBJ * xi_get_default( XI_OBJ * obj ) { XI_OBJ **objlist; XI_OBJ *temp; int n; temp = obj->itf->v.itf->focus_obj; if ( temp != NULL && temp->type == XIT_BTN ) return temp; if ( obj->type == XIT_BTN && obj->v.btn->dflt ) return obj; switch ( obj->type ) { case XIT_GROUP: case XIT_CELL: case XIT_ROW: return NULL; default: break; } /* search in child list */ objlist = xi_get_member_list( obj, &n ); for ( ; n > 0; n--, objlist++ ) { /* call recursively for generality in future versions */ if ( ( temp = xi_get_default( *objlist ) ) != NULL ) return temp; } return NULL; } static XI_OBJ * xi_get_cancel( XI_OBJ * obj ) { XI_OBJ **objlist; XI_OBJ *temp; int n; if ( obj->type == XIT_BTN && obj->v.btn->cancel ) return obj; switch ( obj->type ) { case XIT_GROUP: case XIT_CELL: case XIT_ROW: return NULL; default: break; } /* search in child list */ objlist = xi_get_member_list( obj, &n ); for ( ; n > 0; n--, objlist++ ) { /* call recursively for generality in future versions */ if ( ( temp = xi_get_cancel( *objlist ) ) != NULL ) return temp; } return NULL; } XI_OBJ * xi_get_obj_from_mnemonic( XI_OBJ * obj, char ch ) { XI_OBJ **objlist; XI_OBJ *temp; int n; if ( obj->type == XIT_BTN && toupper( obj->v.btn->mnemonic ) == toupper( ch ) ) return obj; if ( obj->type == XIT_FIELD && toupper( obj->v.field->mnemonic ) == toupper( ch ) ) return obj; switch ( obj->type ) { case XIT_GROUP: case XIT_CELL: case XIT_ROW: return NULL; default: break; } /* search in child list */ objlist = xi_get_member_list( obj, &n ); for ( ; n > 0; n--, objlist++ ) { /* call recursively for generality in future versions */ if ( ( temp = xi_get_obj_from_mnemonic( *objlist, ch ) ) != NULL ) return temp; } return NULL; } void xi_hscroll_internal( XI_OBJ * xi_obj, int nbr_lines, int pos ) { XI_OBJ *itf; XI_OBJ *focus; LM lm = xi_obj->v.list->lm; itf = xi_obj->parent; focus = xi_get_focus( itf ); if ( focus && focus->parent == xi_obj ) { if ( xi_get_pref( XI_PREF_KEEP_FOCUS_FIXED ) ) { lm_hscroll( lm, nbr_lines, pos ); } else { if ( xi_move_focus( itf ) ) lm_hscroll( lm, nbr_lines, pos ); } } else lm_hscroll( lm, nbr_lines, pos ); } void xi_hscroll( XI_OBJ * xi_obj, int nbr_lines ) { xi_hscroll_internal( xi_obj, nbr_lines, 0 ); } static void control_event_hscroll( XI_OBJ * xi_obj, int nbr_lines, int pos ) { XI_LIST_DATA *list_data; XI_OBJ *other_list; list_data = xi_obj->v.list; xi_hscroll_internal( xi_obj, nbr_lines, pos ); if ( list_data->horz_sync_list && !list_data->scrolling_in_progress ) { list_data->scrolling_in_progress = TRUE; other_list = xi_get_obj( xi_obj->itf, list_data->horz_sync_list ); if ( other_list ) xi_hscroll_internal( other_list, nbr_lines, pos ); list_data->scrolling_in_progress = FALSE; } } void xi_control_event_scroll( XI_OBJ * xi_obj, int nbr_lines, int percent, BOOLEAN same_cell ) { XI_LIST_DATA *list_data; XI_OBJ *other_list; list_data = xi_obj->v.list; xi_scroll_internal( xi_obj, nbr_lines, percent, same_cell ); if ( list_data->vert_sync_list && !list_data->scrolling_in_progress ) { list_data->scrolling_in_progress = TRUE; other_list = xi_get_obj( xi_obj->itf, list_data->vert_sync_list ); if ( other_list ) xi_scroll_internal( other_list, nbr_lines, percent, same_cell ); list_data->scrolling_in_progress = FALSE; } } static void control_event( XI_OBJ * itf, XinWindow win, XinEvent * ep ) { XI_ITF_DATA *itf_data; XI_OBJ *xi_obj; itf_data = itf->v.itf; win = itf_data->xin_win; if ( ep->v.control.control_id == XI_MULTILINE_SCROLLBAR_CID ) { XI_TEXT *text; text = xi_text_focus_get( itf_data->xin_win ); if ( text && xi_text_editing_is( text ) ) xi_text_event( text, ep, FALSE, NULL ); return; } if ( ( xi_obj = xi_get_obj( itf, ep->v.control.control_id ) ) != NULL ) { switch ( xi_obj->type ) { case XIT_FIELD: { XI_TEXT *text; text = stx_xi_text_get( xi_obj->v.field->stx ); if ( text ) /* && xi_text_editing_is( text ) ) */ xi_text_event( text, ep, FALSE, NULL ); return; } case XIT_BTN: { XI_EVENT xiev; XinWindow front_win = XinWindowFocusGet( ); MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; call_cb( itf, &xiev ); if ( xi_is_itf( itf ) && xi_is_window( win ) && xi_get_focus( itf ) != xi_obj ) { if ( win ) XinWindowFrontSet( win ); if ( front_win != win && front_win ) XinWindowFrontSet( front_win ); } break; } case XIT_LIST: { switch ( ep->v.control.ctrl_info.v.scroll.action ) { case XinScrollBarActionLineUp: xi_control_event_scroll( xi_obj, -1, 0, TRUE ); break; case XinScrollBarActionLineDown: xi_control_event_scroll( xi_obj, 1, 0, TRUE ); break; case XinScrollBarActionPageUp: xi_control_event_scroll( xi_obj, XI_SCROLL_PGUP, 0, TRUE ); break; case XinScrollBarActionPageDown: xi_control_event_scroll( xi_obj, XI_SCROLL_PGDOWN, 0, TRUE ); break; case XinScrollBarActionThumb: case XinScrollBarActionThumbTrack: if (ep->v.control.ctrl_info.v.scroll.action == XinScrollBarActionThumbTrack && xi_obj->v.list->scroll_on_thumb_track != TRUE) break; { int percent = ep->v.control.ctrl_info.v.scroll.position; if ( XinScrollBarProportionGet( ep->v.control.ctrl_info.win, XinScrollBarTypeEither ) + percent == 100 ) xi_control_event_scroll( xi_obj, XI_SCROLL_LAST, 0, TRUE ); else xi_control_event_scroll( xi_obj, XI_SCROLL_FIRST, percent, TRUE ); break; } default: break; } break; } default: break; } } if ( xi_is_itf( itf ) && ( xi_obj = xi_get_obj( itf, ep->v.control.control_id - HSCROLL_CID_CONST ) ) != NULL ) { switch ( xi_obj->type ) { case XIT_LIST: switch ( ep->v.control.ctrl_info.v.scroll.action ) { case XinScrollBarActionLineUp: control_event_hscroll( xi_obj, -1, 0 ); break; case XinScrollBarActionLineDown: control_event_hscroll( xi_obj, 1, 0 ); break; case XinScrollBarActionPageUp: control_event_hscroll( xi_obj, XI_SCROLL_PGUP, 0 ); break; case XinScrollBarActionPageDown: control_event_hscroll( xi_obj, XI_SCROLL_PGDOWN, 0 ); break; case XinScrollBarActionThumb: case XinScrollBarActionThumbTrack: if (ep->v.control.ctrl_info.v.scroll.action == XinScrollBarActionThumbTrack && xi_obj->v.list->scroll_on_thumb_track != TRUE) break; { int prop; int rng1, rng2; int pos; prop = XinScrollBarProportionGet( ep->v.control.ctrl_info.win, XinScrollBarTypeEither ); XinScrollBarRangeGet( ep->v.control.ctrl_info.win, XinScrollBarTypeEither, &rng1, &rng2 ); pos = ( rng2 - rng1 - prop ) ? ( int ) ( ep->v.control.ctrl_info.v.scroll.position * 100L / ( rng2 - rng1 - prop ) ) : 0; control_event_hscroll( xi_obj, XI_SCROLL_FIRST, pos ); break; } default: break; } break; default: break; } } } void xi_set_trap_obj( XI_OBJ * xi_obj ) { XI_OBJ *itf; XI_ITF_DATA *itf_data; itf = xi_obj->itf; itf_data = itf->v.itf; itf_data->trap_obj = xi_obj; itf_data->trap_explicit = TRUE; } static void destroy_controls( XI_OBJ * xi_obj ) { XI_OBJ **objp; int i; switch ( xi_obj->type ) { case XIT_LIST: if ( xi_obj->v.list->font ) XinFontDestroy( xi_obj->v.list->font ); lm_cleanup( xi_obj->v.list->lm ); break; case XIT_FIELD: if ( xi_obj->v.field->font_set ) stx_destroy_font( xi_obj->v.field->stx ); break; case XIT_TEXT: if ( xi_obj->v.text->font ) XinFontDestroy( xi_obj->v.text->font ); break; case XIT_ITF: if ( xi_obj->v.itf->font ) XinFontDestroy( xi_obj->v.itf->font ); break; case XIT_BTN: xi_bitmap_destroy( xi_obj->v.btn->up_bitmap ); xi_bitmap_destroy( xi_obj->v.btn->down_bitmap ); xi_bitmap_destroy( xi_obj->v.btn->disabled_bitmap ); break; default: break; } objp = xi_obj->children; for ( i = xi_obj->nbr_children; i > 0; i--, objp++ ) destroy_controls( *objp ); } static void copy_to_clip( XI_OBJ * focus_obj ) { int b, e; char *buff; xi_get_sel( focus_obj, &b, &e ); if ( b != e ) { long len; len = e - b; buff = xi_get_text( focus_obj, NULL, 0 ); XinClipboardPut( XinClipboardFormatText, len, &buff[b] ); } } static void update_menus( void ) { BOOLEAN paste_enable; BOOLEAN cut_or_copy_enable = FALSE; XI_OBJ *itf; XI_ITF_DATA *itfdata; XinWindow win; win = XinWindowFocusGet( ); if ( win == XI_NULL_WINDOW || !xi_is_window( win ) ) return; itf = xi_get_itf( win ); itfdata = itf->v.itf; if ( itfdata->menu_win != XI_NULL_WINDOW ) win = itfdata->menu_win; if ( itfdata->edit_menu ) { XI_OBJ *focus_obj; paste_enable = XinClipboardFormatAvail( XinClipboardFormatText ); XinWindowMenuItemEnable( win, XI_MENU_EDIT_PASTE, paste_enable ); focus_obj = xi_get_focus( itf ); if ( ( focus_obj && ( focus_obj->type == XIT_CELL ) ) || ( focus_obj && ( focus_obj->type == XIT_FIELD ) ) ) { int s, e; xi_get_sel( focus_obj, &s, &e ); if ( s != e ) cut_or_copy_enable = TRUE; } if ( paste_enable != itfdata->paste_enable ) { XinWindowMenuItemEnable( win, XI_MENU_EDIT_PASTE, paste_enable ); itfdata->paste_enable = paste_enable; } if ( cut_or_copy_enable != itfdata->cut_or_copy_enable ) { XinWindowMenuItemEnable( win, XI_MENU_EDIT_CUT, cut_or_copy_enable ); XinWindowMenuItemEnable( win, XI_MENU_EDIT_COPY, cut_or_copy_enable ); XinWindowMenuItemEnable( win, XI_MENU_EDIT_CLEAR, cut_or_copy_enable ); itfdata->cut_or_copy_enable = cut_or_copy_enable; } } } static void do_edit_menu( XI_OBJ * itf, XinEvent * ep ) { XI_OBJ *focus_obj; unsigned long attrib = 0L; focus_obj = xi_get_focus( itf ); if ( focus_obj && focus_obj->type != XIT_ITF ) { switch ( focus_obj->type ) { case XIT_FIELD: attrib = xi_get_attrib( focus_obj ); break; case XIT_CELL: { XI_OBJ *list; XI_OBJ *column; XI_OBJ **members; int col_nbr, nbr_members; list = focus_obj->parent; members = xi_get_member_list( list, &nbr_members ); col_nbr = focus_obj->v.cell.column; column = members[col_nbr]; attrib = xi_get_attrib( column ); break; } default: break; } if ( attrib & XI_ATR_EDITMENU ) { int b, e; switch ( ep->v.menu_command.tag ) { case XI_MENU_EDIT_CUT: copy_to_clip( focus_obj ); /* fall through */ case XI_MENU_EDIT_CLEAR: xi_get_sel( focus_obj, &b, &e ); #if 1 // #ifdef XVAGA if ( b == e ) { e++; xi_set_sel( focus_obj, b, e ); } #endif if ( b != e ) { XinEvent ev; MEMCLEAR( ev ); ev.type = XinEventCharacter; ev.v.character.ch = XI_KEY_DEL; xi_event( xi_get_window( itf ), &ev ); } update_menus( ); break; case XI_MENU_EDIT_COPY: copy_to_clip( focus_obj ); update_menus( ); break; case XI_MENU_EDIT_PASTE: #ifdef XI_USE_TX_SUPPORT if ( xi_get_pref( XI_PREF_USE_TX_SUPPORT ) ) if ( focus_obj->type == XIT_FIELD ) if ( xi_is_txedit( focus_obj ) ) if ( xi_get_pref( XI_PREF_MULTILINE_QUICK_PASTE ) ) break; #endif { char *cb, *p; long size; if ( ( cb = XinClipboardGet( XinClipboardFormatText, &size ) ) != NULL ) { XinWindow win; win = xi_get_window( itf ); itf->v.itf->pasting = TRUE; p = cb; if ( ( focus_obj->type == XIT_FIELD || focus_obj->type == XIT_CELL ) && xi_get_pref( XI_PREF_MULTILINE_QUICK_PASTE ) ) { XI_TEXT *text; text = xi_text_focus_get( win ); if ( text ) if ( text->multi_line ) { xi_text_paste_internal( text, p ); itf->v.itf->pasting = FALSE; XinMemoryFree( cb ); break; } } /* Che programmatore cazzone! while ( size-- > 0 ) { XinEvent ev; MEMCLEAR( ev ); ev.type = XinEventCharacter; ev.v.character.ch = ( unsigned char ) *p++; xi_event( win, &ev ); XinWindowPaintForce( win ); } */ if (size) // Molto meglio cosi! { XinEvent ev; MEMCLEAR( ev ); ev.type = XinEventCharacter; while ( size-- > 0 ) { ev.v.character.ch = ( unsigned char ) *p++; xi_event( win, &ev ); } } itf->v.itf->pasting = FALSE; XinMemoryFree( cb ); } } update_menus( ); break; } } } } /* count the number of children of xi_obj that have rectangles that will be completely filled in when the child is drawn. */ static int count_children( XI_OBJ * xi_obj ) { int idx; int count = 0; XI_OBJ **child; for ( idx = 0, child = xi_obj->children; idx < xi_obj->nbr_children; ++idx, ++child ) { XI_OBJ_TYPE type = ( *child )->type; if ( xi_get_attrib( *child ) & XI_ATR_VISIBLE ) { /* do not count groups, lines, static texts, or columns, nor their * children */ if ( type != XIT_GROUP && type != XIT_LINE && type != XIT_TEXT && type != XIT_COLUMN ) { /* count the children of containers, forms, and the interface, but not * containers, forms, and interfaces */ if ( ( *child )->type != XIT_LIST && ( *child )->children ) count += count_children( *child ); if ( type != XIT_CONTAINER && type != XIT_FORM && type != XIT_ITF && type != XIT_TEXT && type != XIT_BTN && type != XIT_FIELD ) ++count; } } } return count; } static void add_rects( XI_OBJ * xi_obj, XinRect * ra, int *ra_count ) { int idx; XI_OBJ **child; for ( idx = 0, child = xi_obj->children; idx < xi_obj->nbr_children; ++idx, ++child ) { XI_OBJ_TYPE type = ( *child )->type; if ( xi_get_attrib( *child ) & XI_ATR_VISIBLE ) { /* do not add rects for groups, lines, static texts, or columns, nor * their children */ if ( type != XIT_GROUP && type != XIT_LINE && type != XIT_TEXT && type != XIT_COLUMN ) { /* add rects for the children of containers, forms, and the interface, * but not containers, forms, and interfaces */ if ( ( *child )->type != XIT_LIST && ( *child )->children ) add_rects( *child, ra, ra_count ); if ( type != XIT_CONTAINER && type != XIT_FORM && type != XIT_ITF && type != XIT_TEXT && type != XIT_BTN && type != XIT_FIELD ) { xi_get_rect( ( *child ), &ra[*ra_count] ); ++*ra_count; } } } } } #if XIWS == XIWS_PM static int _Optlink #else static int #endif compare( const void *arg1, const void *arg2 ) { if ( *( int * ) arg1 == *( int * ) arg2 ) return 0; if ( *( int * ) arg1 < *( int * ) arg2 ) return -1; return 1; } static int elim_dups( int *int_array, int int_count ) { int index = 0; int top = int_count - 1; int *iap = int_array; while ( index < top ) { if ( *iap == *( iap + 1 ) ) { if ( top > index ) memmove( iap + 1, iap + 2, ( top - index - 1 ) * sizeof( int ) ); --top; } else { ++index; ++iap; } } return top; } static void draw_all_rects( XI_OBJ * itf ) { XinRect *ra, *rap; XI_ITF_DATA *itf_data; int count; int cur_delta_x, cur_delta_y; int num_rects; int ra_count; int *hml, *hmlp; int hml_count, hml_top; int *vml, *vmlp; int vml_count, vml_top; int int_count; int rect_count; XinRect client_rect; XinWindow win = xi_get_window( itf ); XI_BITMAP *bitmap; itf_data = itf->v.itf; bitmap = itf_data->bitmap; cur_delta_x = itf_data->delta_x; cur_delta_y = itf_data->delta_y; num_rects = count_children( itf ); XinWindowRectGet( win, &client_rect ); if ( !num_rects ) { if ( bitmap != NULL ) xi_bitmap_draw( bitmap, win, &client_rect, NULL, TRUE ); else XinWindowRectDraw( win, &client_rect ); return; } ra = xi_tree_malloc( sizeof( XinRect ) * num_rects, itf ); ra_count = 0; add_rects( itf, ra, &ra_count ); int_count = num_rects * 2 + 2; /* hml is an acronym for horizontal mathmatical lines */ /* vml is an acronym for vertical mathmatical lines */ hml = xi_tree_malloc( sizeof( int ) * int_count, itf ); vml = xi_tree_malloc( sizeof( int ) * int_count, itf ); hmlp = hml; vmlp = vml; *hmlp = 0; ++hmlp; *vmlp = 0; ++vmlp; *hmlp = 9999; ++hmlp; *vmlp = 9999; ++vmlp; for ( count = 0, rap = ra; count < num_rects; ++count, ++rap ) { *hmlp = rap->left; ++hmlp; *hmlp = rap->right; ++hmlp; *vmlp = rap->top; ++vmlp; *vmlp = rap->bottom; ++vmlp; } qsort( ( void * ) hml, ( size_t ) int_count, sizeof( int ), compare ); qsort( ( void * ) vml, ( size_t ) int_count, sizeof( int ), compare ); hml_top = elim_dups( hml, int_count ); vml_top = elim_dups( vml, int_count ); for ( hml_count = 0, hmlp = hml; hml_count < hml_top; ++hml_count, ++hmlp ) { for ( vml_count = 0, vmlp = vml; vml_count < vml_top; ++vml_count, ++vmlp ) { /* use static for rect and new_rect, to allow the compiler to generate * more efficient code */ static XinRect rect; rect.left = *hmlp; rect.right = *( hmlp + 1 ); rect.top = *vmlp; rect.bottom = *( vmlp + 1 ); for ( rect_count = 0, rap = ra; rect_count < ra_count; ++rect_count, ++rap ) { static XinRect new_rect; new_rect = *rap; if ( new_rect.top < rect.top ) new_rect.top = rect.top; if ( new_rect.left < rect.left ) new_rect.left = rect.left; if ( new_rect.bottom > rect.bottom ) new_rect.bottom = rect.bottom; if ( new_rect.right > rect.right ) new_rect.right = rect.right; /* if the intersection is not empty, then skip this rectangle */ if ( new_rect.bottom > new_rect.top && new_rect.right > new_rect.left ) break; } /* if we made it through all rectangles, then no rectangle intersected, * and we should draw rect */ if ( ra_count && rect_count == ra_count ) { rect.left -= cur_delta_x; rect.right -= cur_delta_x; rect.top -= cur_delta_y; rect.bottom -= cur_delta_y; if ( bitmap != NULL ) xi_bitmap_draw( bitmap, win, &client_rect, &rect, TRUE ); else XinWindowRectDraw( win, &rect ); } } } xi_tree_free( ra ); xi_tree_free( hml ); xi_tree_free( vml ); } static void draw_background( XI_OBJ * itf ) { XI_ITF_DATA *itf_data = itf->v.itf; XinWindow win = itf_data->xin_win; if ( itf_data->back_color ) { XinDrawTools t; XinBrush cbrush; XinWindowDrawToolsNormalGet( &t ); XinWindowDrawToolsSet( win, &t ); XinWindowPenSet( win, &hollow_cpen ); cbrush.pattern = XinBrushSolid; cbrush.fore_color = itf_data->back_color; XinWindowBrushSet( win, &cbrush ); xi_set_clip( win, NULL ); draw_all_rects( itf ); } else if ( itf_data->bitmap != NULL ) { xi_set_clip( win, NULL ); draw_all_rects( itf ); } } static void do_post_event( XI_OBJ * itf, XinEvent * ep ) { XI_EVENT xiev; if ( xi_is_itf( itf ) ) { MEMCLEAR( xiev ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { xiev.type = XIE_XIN_POST_EVENT; xiev.v.xin_event = *ep; } #ifdef XI_USE_XVT else { if ( ep->type != XinEventCharacter || !ep->v.character.alt ) { xiev.type = XIE_XVT_POST_EVENT; XinXvtEventGet( &xiev.v.xvte ); } } #endif xiev.refused = FALSE; if ( !call_cb( itf, &xiev ) ) return; } } /* ------------------------------------------------------------------------ */ /* get_text_ctools */ /* ------------------------------------------------------------------------ */ static XinDrawTools * get_text_ctools( XI_ITF_DATA * itf_data, XinDrawTools * ct, XinFont ** p_font ) { XinWindowDrawToolsNormalGet( ct ); ct->pen.fore_color = ct->text_fore_color = XI_COLOR_BLACK; ct->opaque_text = FALSE; if ( itf_data->font ) *p_font = itf_data->font; else *p_font = xi_get_system_font( ); return ( ct ); } /* ------------------------------------------------------------------------ */ /* xi_draw_obj */ /* ------------------------------------------------------------------------ */ static void xi_draw_obj( XI_OBJ * xi_obj ) { XinWindow win; XI_ITF_DATA *itf_data; itf_data = xi_obj->itf->v.itf; win = itf_data->xin_win; switch ( xi_obj->type ) { case XIT_TEXT: { XI_TEXT_DATA *text; XinDrawTools ct; XinFont *font; text = xi_obj->v.text; get_text_ctools( itf_data, &ct, &font ); ct.text_back_color = itf_data->back_color; ct.text_fore_color = XI_COLOR_BLACK; if ( text->fore_color ) ct.text_fore_color = text->fore_color; if ( text->back_color ) { ct.opaque_text = TRUE; ct.text_back_color = text->back_color; } XinWindowDrawToolsSet( win, &ct ); if ( text->font ) font = text->font; if ( ( text->attrib & XI_ATR_ENABLED ) ) XinWindowColorTextForeSet( win, ct.text_fore_color ); else XinWindowColorTextForeSet( win, ( XinColor ) xi_get_pref( XI_PREF_COLOR_DISABLED ) ); XinWindowColorTextBackSet( win, ct.text_back_color ); xi_draw_clipped_text( win, font, text->text, &text->rct, &text->rct, text->attrib | XI_ATR_VCENTER, FALSE, 0, -1, text->mnemonic, text->mnemonic_instance, NULL ); break; } case XIT_LINE: { XI_LINE_DATA *line; XinPoint pnt1, pnt2; XinWindowClipSet( win, NULL ); line = xi_obj->v.line; if ( line->attrib & XI_ATR_VISIBLE ) { pnt1 = line->pnt1; pnt2 = line->pnt2; if ( ( BOOLEAN ) xi_get_pref( XI_PREF_3D_LOOK ) ) xi_draw_3d_line( win, pnt1, pnt2, line->well ); else { XinPen cpen; cpen = black_cpen; if ( line->fore_color ) cpen.fore_color = line->fore_color; XinWindowPenSet( win, &cpen ); if ( line->back_color ) XinWindowColorTextBackSet( win, line->back_color ); xi_move_to( win, pnt1 ); xi_draw_line( win, pnt2 ); } } break; } case XIT_RECT: { XI_RECT_DATA *rect; XinRect rct; XinWindowClipSet( win, NULL ); rect = xi_obj->v.rect; if ( rect->attrib & XI_ATR_VISIBLE ) { rct = rect->rct; if ( ( BOOLEAN ) xi_get_pref( XI_PREF_3D_LOOK ) ) { xi_draw_3d_rect( win, &rct, rect->well, 1, rect->hilight_color, rect->back_color, rect->shadow_color ); if ( rect->ridge ) { xi_inflate_rect( &rct, -1 ); xi_draw_3d_rect( win, &rct, ( BOOLEAN ) ( !rect->well ), 1, rect->hilight_color, rect->back_color, rect->shadow_color ); } } else { XinPen cpen = black_cpen; XinBrush cbrush = white_cbrush; if ( rect->fore_color ) cpen.fore_color = rect->fore_color; if ( rect->back_color ) cbrush.fore_color = rect->back_color; XinWindowBrushSet( win, &cbrush ); if ( rect->ridge ) { XinWindowPenSet( win, &hollow_cpen ); xi_draw_rect( win, &rct ); XinWindowPenSet( win, &cpen ); xi_draw_roundrect( win, &rct, 4, 4 ); } else { XinWindowPenSet( win, &cpen ); xi_draw_rect( win, &rct ); } } if ( rect->bitmap != NULL ) { xi_inflate_rect( &rct, -1 ); xi_bitmap_draw( rect->bitmap, win, &rct, NULL, FALSE ); } } break; } default: break; } } /* ------------------------------------------------------------------------ */ /* xi_draw_field_button */ /* ------------------------------------------------------------------------ */ void xi_draw_field_button( XI_OBJ * xi_obj ) { XI_FIELD_DATA *fd; unsigned long attrib; STX_DATA *stxd; const XinColor color_light = aga_get_pref(AGA_PREF_BTN_COLOR_LIGHT); const XinColor color_ctrl = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL); const XinColor color_dark = aga_get_pref(AGA_PREF_BTN_COLOR_DARK); const int button_depth = 1; #if XIWS != XIWS_WM XinRect cr, r; #endif XinWindow win; attrib = xi_get_attrib( xi_obj ); if ( !( attrib & XI_ATR_VISIBLE ) ) return; fd = xi_obj->v.field; stxd = ( STX_DATA * ) fd->stx; win = xi_obj->itf->v.itf->xin_win; XinWindowDrawModeSet( win, XinDrawModeCopy ); xi_set_clip( win, NULL ); #if XIWS != XIWS_WM r = fd->btn_rct; xi_inflate_rect( &r, -1 ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_3D_LOOK ) ) xi_draw_3d_rect(win, &r, fd->down, button_depth, color_light, color_ctrl, color_dark); else { XinWindowBrushSet( win, &white_cbrush ); XinWindowPenSet( win, &hollow_cpen ); xi_draw_rect( win, &r ); } cr = r; xi_inflate_rect( &cr, -button_depth ); xi_set_clip( win, &cr ); if ( fd->button_bitmap != NULL ) xi_bitmap_draw( fd->button_bitmap, win, &cr, &cr, FALSE ); else { XinColor color = ( BOOLEAN ) xi_get_pref( XI_PREF_3D_LOOK ) ? color_ctrl : xi_get_pref( XI_PREF_COLOR_CTRL ); // Guy was here: center icon in button int x = (r.left+r.right-XinMetricGet(XinMetricIconWidth))/2; // x = r.left + 3; int y = (r.top+r.bottom-XinMetricGet(XinMetricIconHeight))/2; // y = r.top + 2; int icon_rid = fd->icon_rid; if ( icon_rid == 0 ) icon_rid = ( int ) xi_get_pref( XI_PREF_COMBO_ICON ); if ( fd->down ) xi_draw_icon( win, x, y + 1, icon_rid, XI_COLOR_BLACK, color ); else xi_draw_icon( win, x, y, icon_rid, XI_COLOR_BLACK, color ); } xi_set_clip( win, NULL ); XinWindowPenSet( win, &black_cpen ); XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_rect( win, &fd->btn_rct ); #endif #if XIWS == XIWS_WM NOREF( stxd ); { XinBrush black_cbrush; black_cbrush = white_cbrush; black_cbrush.fore_color = XI_COLOR_BLACK; xi_set_clip( win, NULL ); XinWindowPenSet( win, &hollow_cpen ); XinWindowBrushSet( win, &black_cbrush ); xi_draw_rect( win, &fd->btn_rct ); } #endif } /* ------------------------------------------------------------------------ */ /* field_event */ /* ------------------------------------------------------------------------ */ static void field_event( XI_OBJ * xi_obj, XinEvent * ep ) { XI_FIELD_DATA *field_data; XinRect rct; field_data = xi_obj->v.field; rct = field_data->btn_rct; switch ( ep->type ) { case XinEventCharacter: if ( field_data->button ) { long button_key; BOOLEAN shift, control, alt; button_key = xi_get_pref( XI_PREF_BUTTON_KEY ); shift = ( BOOLEAN ) ( ( button_key & XI_MOD_SHIFT ) != 0 ); control = ( BOOLEAN ) ( ( button_key & XI_MOD_CONTROL ) != 0 ); alt = ( BOOLEAN ) ( ( button_key & XI_MOD_ALT ) != 0 ); button_key &= 0xffffffL; if ( button_key == ep->v.character.ch && shift == ep->v.character.shift && control == ep->v.character.control && alt == ep->v.character.alt ) { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; itf = xi_obj->itf; call_cb( itf, &xiev ); } } break; case XinEventPaint: if ( field_data->button ) xi_draw_field_button( xi_obj ); break; case XinEventMouseDown: { unsigned long attrib; attrib = stx_get_attrib( xi_obj->v.field->stx ); attrib &= ( XI_ATR_ENABLED | XI_ATR_VISIBLE ); if ( field_data->button && attrib == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) { if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) ) { field_data->down = TRUE; field_data->down_in_btn = TRUE; xi_draw_field_button( xi_obj ); xi_set_trap_obj( xi_obj ); XinWindowMouseTrap( xi_obj->itf->v.itf->xin_win, TRUE ); } } break; } case XinEventMouseMove: if ( field_data->button && field_data->down_in_btn ) { if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) && !field_data->down ) { field_data->down = TRUE; xi_draw_field_button( xi_obj ); } if ( !xi_pt_in_rect( &rct, ep->v.mouse.where ) && field_data->down ) { field_data->down = FALSE; xi_draw_field_button( xi_obj ); } } break; case XinEventMouseUp: if ( field_data->button && field_data->down_in_btn ) { XinWindowMouseRelease( ); if ( field_data->down ) { field_data->down = FALSE; xi_draw_field_button( xi_obj ); } field_data->down_in_btn = FALSE; if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) ) { if ( xi_move_focus( xi_obj ) ) { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; itf = xi_obj->itf; call_cb( itf, &xiev ); } } } break; default: break; } } void xi_draw_foc_and_dflt( XI_OBJ * xi_obj ) { XI_OBJ *dflt_obj, *foc_obj; XI_BTN_DATA *bd; BOOLEAN enabled; BOOLEAN visible; BOOLEAN focus; BOOLEAN dflt; unsigned long attrib; if ( xi_get_native_controls( xi_obj ) ) return; dflt_obj = xi_get_default( xi_obj ); if ( dflt_obj ) { bd = dflt_obj->v.btn; attrib = xi_get_attrib( dflt_obj ); enabled = ( ( attrib & XI_ATR_ENABLED ) != 0 ); visible = ( ( attrib & XI_ATR_VISIBLE ) != 0 ); focus = ( xi_get_focus( dflt_obj->itf ) == dflt_obj ); dflt = bd->dflt; xi_draw_button( dflt_obj, &bd->rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, TRUE ); } foc_obj = xi_get_focus( xi_obj ); if ( foc_obj && foc_obj->type == XIT_BTN && foc_obj != dflt_obj ) { bd = foc_obj->v.btn; attrib = xi_get_attrib( foc_obj ); enabled = ( ( attrib & XI_ATR_ENABLED ) != 0 ); visible = ( ( attrib & XI_ATR_VISIBLE ) != 0 ); focus = TRUE; dflt = bd->dflt; xi_draw_button( foc_obj, &bd->rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, TRUE ); } } /* ------------------------------------------------------------------------ */ /* form_event */ /* ------------------------------------------------------------------------ */ static BOOLEAN form_event( XI_OBJ * xi_obj, XinEvent * ep ) { BOOLEAN retval = FALSE; XI_OBJ *focus_obj = xi_obj->itf->v.itf->focus_obj; XI_OBJ *itf = xi_obj->itf; BOOLEAN focus_is_cell = (focus_obj != NULL && focus_obj->type == XIT_CELL); switch ( ep->type ) { case XinEventMenuCommand: /* TODO -- navigation */ break; case XinEventCharacter: { long c = event_to_longchar( ep ); XI_OBJ *next_obj = NULL; /* navigation character event */ if ( ( c == '\r' || c == '\n' ) && xi_obj->itf->v.itf->tab_on_enter && xi_obj->type != XIT_BTN ) c = xi_get_pref( XI_PREF_FORM_TAB_CHAR ); if ( c == xi_get_pref( XI_PREF_FORM_TAB_CHAR ) || c == XI_KEY_DOWN ) { next_obj = xi_find_next_obj( focus_obj, XI_NEXT_FORM_TAB, c ); } else if ( c == xi_get_pref( XI_PREF_FORM_BACKTAB_CHAR ) || c == XI_KEY_UP ) { next_obj = focus_obj; do { next_obj = xi_find_next_obj( next_obj, XI_NEXT_FORM_BACKTAB, c ); } while ( next_obj != NULL && next_obj != focus_obj && ( next_obj->type == XIT_FORM || next_obj->type == XIT_CONTAINER ) ); } if ( next_obj != NULL ) { xi_move_focus_internal( next_obj, TRUE, TRUE, ( ( c == xi_get_pref( XI_PREF_FORM_TAB_CHAR ) ) || ( c == XI_KEY_DOWN ) ) ? 1 : 2 ); retval = TRUE; } if ( next_obj && (focus_is_cell || xi_is_obj( focus_obj, itf )) ) xi_draw_foc_and_dflt_if_necessary( focus_obj, next_obj ); break; } default: break; } return retval; } /* ------------------------------------------------------------------------ */ /* invalidate_button_rect */ /* ------------------------------------------------------------------------ */ static BOOLEAN invalidate_button_rect( XI_OBJ * xi_obj, XI_BTN_DATA * bd, XinRect * rct ) { // if (( bd->type == XIBT_BUTTON || bd->type == XIBT_BUTTON_CHECKBOX || // bd->type == XIBT_RADIOBTN ) && bd->drawable || bd->type == XIBT_TABBTN) if ((( bd->type == XIBT_BUTTON || bd->type == XIBT_BUTTON_CHECKBOX || bd->type == XIBT_RADIOBTN ) && bd->drawable) || bd->type == XIBT_TABBTN) { XinRect r; XinWindow win; r = *rct; xi_inflate_rect( &r, -4 ); win = xi_get_window( xi_obj->itf ); xi_invalidate_rect( win, &r ); XinWindowPaintForce( win ); return TRUE; } return FALSE; } /* ------------------------------------------------------------------------ */ /* btn_event */ /* ------------------------------------------------------------------------ */ static BOOLEAN btn_event( XI_OBJ * xi_obj, XinEvent * ep ) { BOOLEAN enabled; BOOLEAN visible; BOOLEAN focus; BOOLEAN dflt; BOOLEAN send_to_form = TRUE; BOOLEAN ret_val; XinRect rct; unsigned long attrib; XI_BTN_DATA *bd; if ( !xi_get_native_controls( xi_obj ) ) { attrib = xi_get_attrib( xi_obj ); enabled = ( ( attrib & XI_ATR_ENABLED ) != 0 ); visible = ( ( attrib & XI_ATR_VISIBLE ) != 0 ); focus = ( xi_get_focus( xi_obj->itf ) == xi_obj ); bd = xi_obj->v.btn; dflt = bd->dflt; rct = bd->rct; switch ( ep->type ) { case XinEventTimer: return FALSE; case XinEventCharacter: if ( ep->v.character.ch == ' ' && focus ) { XI_EVENT xiev; XI_OBJ *itf; int obj_cid; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; itf = xi_obj->itf; obj_cid = xi_obj->cid; call_cb( itf, &xiev ); if ( !xi_is_itf( itf ) || xi_get_obj( itf, obj_cid ) == NULL ) send_to_form = FALSE; } break; case XinEventPaint: xi_draw_button( xi_obj, &rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, TRUE ); break; case XinEventMouseDouble: if ( !xi_get_pref( XI_PREF_DBL_PRESSES_BUTTON ) ) break; /* else fall through */ case XinEventMouseDown: { XinRect hit_rct; if ( ( enabled == FALSE ) || ( visible == FALSE ) ) break; hit_rct = rct; if ( bd->packed == TRUE ) xi_inflate_rect( &hit_rct, -( ( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ) ) ); if ( xi_pt_in_rect( &hit_rct, ep->v.mouse.where ) ) { bd->down = TRUE; bd->down_in_btn = TRUE; if ( !invalidate_button_rect( xi_obj, bd, &rct ) ) xi_draw_button( xi_obj, &rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, FALSE ); xi_set_trap_obj( xi_obj ); XinWindowMouseTrap( xi_get_window( xi_obj->itf ), TRUE ); } break; } case XinEventMouseMove: if ( bd->down_in_btn ) { if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) && !bd->down ) { bd->down = TRUE; if ( !invalidate_button_rect( xi_obj, bd, &rct ) ) xi_draw_button( xi_obj, &rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, FALSE ); } else if ( !xi_pt_in_rect( &rct, ep->v.mouse.where ) && bd->down ) { bd->down = FALSE; if ( !invalidate_button_rect( xi_obj, bd, &rct ) ) xi_draw_button( xi_obj, &rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, FALSE ); } } break; case XinEventMouseUp: if ( bd->down_in_btn ) { bd->down_in_btn = FALSE; if ( bd->down ) { bd->down = FALSE; if ( !invalidate_button_rect( xi_obj, bd, &rct ) ) xi_draw_button( xi_obj, &rct, enabled, visible, focus, bd->down, dflt, bd->checked, FALSE, FALSE ); } XinWindowMouseRelease( ); if ( ep->type == XinEventMouseUp && xi_pt_in_rect( &rct, ep->v.mouse.where ) ) { XI_EVENT xiev; XI_OBJ *itf; int obj_cid; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; itf = xi_obj->itf; obj_cid = xi_obj->cid; call_cb( itf, &xiev ); if ( !xi_is_itf( itf ) || xi_get_obj( itf, obj_cid ) == NULL ) send_to_form = FALSE; } } break; default: break; } } ret_val = TRUE; if ( send_to_form ) ret_val = form_event( xi_obj, ep ); return ret_val; } /* ------------------------------------------------------------------------ */ /* draw_list_button */ /* ------------------------------------------------------------------------ */ #define P_OFFSET 3 static void draw_list_button( XinWindow win, XinRect * rct, BOOLEAN down ) { #if XIWS != XIWS_WM int x, y, plus_width, plus_height; XinPoint p; XinRect r; BOOLEAN x2; r = *rct; xi_set_clip( win, NULL ); // XI forgot this! XinWindowPenSet( win, &black_cpen ); XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_rect( win, &r ); r.top++; r.left++; r.bottom--; r.right--; if ( ( BOOLEAN ) xi_get_pref( XI_PREF_3D_LOOK ) ) { const XinColor color_light = aga_get_pref(AGA_PREF_BTN_COLOR_LIGHT); const XinColor color_ctrl = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL); const XinColor color_dark = aga_get_pref(AGA_PREF_BTN_COLOR_DARK); xi_draw_3d_rect(win, &r, down, 2, color_light, color_ctrl, color_dark); } else { XinWindowBrushSet( win, &white_cbrush ); xi_draw_rect( win, &r ); } p.h = rct->left; p.v = rct->top - 1; XinWindowPenSet( win, &black_cpen ); xi_move_to( win, p ); p.h = rct->right; xi_draw_line( win, p ); plus_width = r.right - r.left; plus_height = plus_width + 4; x = r.left + plus_width / 2; y = r.top + plus_height / 2; x2 = !( ( r.right + r.left ) % 2 ); if ( x2 ) x--; y--; XinWindowPenSet( win, &black_cpen ); /* draw vertical lines */ p.h = x; p.v = r.top + P_OFFSET + down; xi_move_to( win, p ); p.v = r.top + plus_height - P_OFFSET + down; xi_draw_line( win, p ); p.h = x + 1; p.v = r.top + P_OFFSET + down; xi_move_to( win, p ); p.v = r.top + plus_height - P_OFFSET + down; xi_draw_line( win, p ); /* draw horizontal lines */ p.v = y + down; p.h = r.left + P_OFFSET; xi_move_to( win, p ); p.h = r.left + plus_width - P_OFFSET; xi_draw_line( win, p ); p.v = y + down + 1; p.h = r.left + P_OFFSET; xi_move_to( win, p ); p.h = r.left + plus_width - P_OFFSET; xi_draw_line( win, p ); #else NOREF( rct ); NOREF( down ); NOREF( win ); #endif } /* ------------------------------------------------------------------------ */ /* list_event */ /* ------------------------------------------------------------------------ */ static void list_event( XI_OBJ * xi_obj, XinEvent * ep ) { XI_LIST_DATA *list_data; XinRect rct; LM_DATA *lmp; list_data = xi_obj->v.list; lmp = ( LM_DATA * ) list_data->lm; if ( lmp->attrib & XI_ATR_VISIBLE ) { rct = list_data->sbb_rct; switch ( ep->type ) { case XinEventPaint: if ( list_data->scroll_bar_button ) draw_list_button( lmp->win, &rct, list_data->down ); break; case XinEventMouseDown: if ( list_data->scroll_bar_button ) { if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) ) { list_data->down = TRUE; list_data->down_in_btn = TRUE; draw_list_button( lmp->win, &rct, TRUE ); xi_set_trap_obj( xi_obj ); XinWindowMouseTrap( xi_obj->itf->v.itf->xin_win, TRUE ); } } break; case XinEventMouseMove: if ( list_data->scroll_bar_button && list_data->down_in_btn ) { if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) && !list_data->down ) { list_data->down = TRUE; draw_list_button( lmp->win, &rct, TRUE ); } if ( !xi_pt_in_rect( &rct, ep->v.mouse.where ) && list_data->down ) { list_data->down = FALSE; draw_list_button( lmp->win, &rct, FALSE ); } } break; case XinEventMouseUp: if ( list_data->scroll_bar_button && list_data->down_in_btn ) { XinWindowMouseRelease( ); if ( list_data->down ) { list_data->down = FALSE; draw_list_button( lmp->win, &rct, FALSE ); } list_data->down_in_btn = FALSE; if ( xi_pt_in_rect( &rct, ep->v.mouse.where ) ) { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = xi_obj; itf = xi_obj->itf; call_cb( itf, &xiev ); } } break; default: break; } } } /* ------------------------------------------------------------------------ */ /* itf_event */ /* ------------------------------------------------------------------------ */ static BOOLEAN itf_event( XI_OBJ * xi_obj, XinEvent * ep ) { BOOLEAN retval = FALSE; XI_ITF_DATA *itf_data; XI_OBJ *focus_obj; itf_data = xi_obj->itf->v.itf; focus_obj = itf_data->focus_obj; switch ( ep->type ) { case XinEventMenuCommand: /* TODO -- navigation */ break; case XinEventResize: if ( itf_data->bitmap != NULL && xi_bitmap_draw_all_on_resize( itf_data->bitmap ) ) XinWindowRectInvalidate( xi_get_window( xi_obj ), NULL ); break; case XinEventCharacter: { long c = event_to_longchar( ep ); XI_OBJ *next_obj = NULL; if ( focus_obj->itf != xi_obj ) XinError( 20030, XinSeverityFatal, 0L ); /* navigation character event */ if ( c == xi_get_pref( XI_PREF_ITF_TAB_CHAR ) ) next_obj = xi_find_next_obj( focus_obj, XI_NEXT_ITF_TAB, c ); else if ( c == xi_get_pref( XI_PREF_ITF_BACKTAB_CHAR ) ) next_obj = xi_find_next_obj( focus_obj, XI_NEXT_ITF_BACKTAB, c ); else if ( c == xi_get_pref( XI_PREF_FORM_TAB_CHAR ) && focus_obj->type == XIT_ITF ) next_obj = xi_search_itf( focus_obj, XI_SEARCH_FOR_FOCUSABLE, 0 ); if ( c == '\r' || c == '\n' ) { XI_OBJ *dflt_obj; dflt_obj = xi_get_default( xi_obj->itf ); if ( dflt_obj && ( xi_get_attrib( dflt_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = dflt_obj; itf = xi_obj->itf; call_cb( itf, &xiev ); retval = TRUE; } } if ( c == '\033' ) { XI_OBJ *cancel_obj; cancel_obj = xi_get_cancel( xi_obj->itf ); if ( cancel_obj && ( xi_get_attrib( cancel_obj ) & ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) == ( XI_ATR_ENABLED | XI_ATR_VISIBLE ) ) { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = cancel_obj; itf = xi_obj->itf; call_cb( itf, &xiev ); retval = TRUE; } } if ( ep->v.character.alt ) { XI_OBJ *obj; obj = xi_get_obj_from_mnemonic( xi_obj->itf, ( char ) ep->v.character.ch ); if ( obj ) { switch ( obj->type ) { case XIT_BTN: { XI_EVENT xiev; XI_OBJ *itf; MEMCLEAR( xiev ); xiev.type = XIE_BUTTON; xiev.v.xi_obj = obj; itf = xi_obj->itf; call_cb( itf, &xiev ); ep->v.character.consumed = TRUE; break; } case XIT_FIELD: xi_move_focus( obj ); ep->v.character.consumed = TRUE; break; default: break; } } } if ( next_obj != NULL ) { xi_move_focus_internal( next_obj, TRUE, FALSE, 0 ); retval = TRUE; } /* if the last focus was a button, and the current focus is not, or if * the last focus was not a button, and the current focus is, then draw * the default button, followed by the focus button. */ if ( xi_is_itf( xi_obj ) ) { xi_draw_foc_and_dflt_if_necessary( focus_obj, next_obj ); } break; } default: break; } return ( retval ); } /* ------------------------------------------------------------------------ */ /* draw_rectangles */ /* ------------------------------------------------------------------------ */ static void draw_rectangles( XI_OBJ* itf ) { int num, num_members, num_rects, sorted_rects, rect_num; XI_OBJ** objlist; XI_OBJ** cur_obj; XI_OBJ** rect_list; /* Count the rectangles in the interface */ objlist = xi_get_member_list( itf, &num_members ); num_rects = 0; for ( num = 0, cur_obj = objlist; num < num_members; num++, cur_obj++ ) if ( (*cur_obj)->type == XIT_RECT ) num_rects++; if ( num_rects == 0 ) return; /* Sort rectangles into proper drawing order */ rect_list = (XI_OBJ**)xi_tree_malloc( num_rects * sizeof(XI_OBJ*), NULL ); sorted_rects = 0; for ( num = 0, cur_obj = objlist; num < num_members; num++, cur_obj++ ) if ( (*cur_obj)->type == XIT_RECT ) { for ( rect_num = 0; rect_num < sorted_rects; rect_num++ ) { XinRect intersect; XinRect* sort_rect = &rect_list[ rect_num ]->v.rect->rct; XinRectIntersect( &intersect, sort_rect, &(*cur_obj)->v.rect->rct ); if ( intersect.top == sort_rect->top && intersect.bottom == sort_rect->bottom && intersect.left == sort_rect->left && intersect.right == sort_rect->right ) break; } if ( rect_num == sorted_rects ) rect_list[ sorted_rects++ ] = *cur_obj; else { memmove( rect_list + rect_num + 1, rect_list + rect_num, ( sorted_rects - rect_num ) * sizeof(XI_OBJ*) ); rect_list[ rect_num ] = *cur_obj; sorted_rects++; } } /* Draw rectangles in sorted order */ for ( num = 0; num < num_rects; num++ ) xi_draw_obj( rect_list[ num ] ); } /* ------------------------------------------------------------------------ */ /* xi_send_event */ /* ------------------------------------------------------------------------ */ static int xi_send_event( XI_OBJ * xi_obj, XinEvent * ep, BOOLEAN do_subtree ) { int n; XI_OBJ **objlist; BOOLEAN send_to_parent = FALSE; int retval = 0; switch ( xi_obj->type ) { case XIT_TEXT: case XIT_LINE: if ( ep->type == XinEventPaint ) xi_draw_obj( xi_obj ); break; case XIT_FIELD: field_event( xi_obj, ep ); retval = stx_event( xi_obj->v.field->stx, ep ); send_to_parent = !retval; /* don't send any character events (for navigation to the parent if * pasting */ if ( ep->type == XinEventCharacter && xi_obj->itf->v.itf->pasting ) send_to_parent = FALSE; break; case XIT_CONTAINER: send_to_parent = TRUE; break; case XIT_FORM: send_to_parent = !form_event( xi_obj, ep ); break; case XIT_BTN: send_to_parent = !btn_event( xi_obj, ep ); break; case XIT_LIST: { XI_OBJ *itf; itf = xi_obj->itf; if ( xi_obj->itf->v.itf->update_obj ) { lm_event( itf, xi_obj->v.list->lm, ep ); send_to_parent = FALSE; do_subtree = FALSE; } else { list_event( xi_obj, ep ); retval = lm_event( itf, xi_obj->v.list->lm, ep ); send_to_parent = !retval; /* Don't broadcast events to columns */ do_subtree = FALSE; } if ( xi_is_itf( itf ) ) if ( xi_obj->itf->v.itf->pasting ) send_to_parent = FALSE; break; } case XIT_ITF: itf_event( xi_obj, ep ); break; case XIT_CELL: /* Send events to list as there is no handler for individual cells */ send_to_parent = TRUE; break; case XIT_COLUMN: default: /* ignored */ break; } if ( do_subtree && xi_obj->type != XIT_GROUP ) { int retval; XI_OBJ *itf = xi_obj->itf; if ( xi_obj->type == XIT_ITF && ep->type == XinEventPaint ) draw_rectangles( xi_obj ); /* loop over sub-objects */ objlist = xi_get_member_list( xi_obj, &n ); for ( ; n > 0; n--, objlist++ ) { retval = xi_send_event( *objlist, ep, do_subtree ); if (!xi_is_itf( itf )) return retval; /* after everything else is drawn, then if focus is on a button, draw it, * and if there is a default button, draw it. */ if ( retval ) { if ( xi_obj->type == XIT_ITF && ep->type == XinEventPaint ) xi_draw_foc_and_dflt( xi_obj ); return retval; } } if ( xi_obj->type == XIT_ITF && ep->type == XinEventPaint ) xi_draw_foc_and_dflt( xi_obj ); } if ( send_to_parent ) { retval = xi_send_event( xi_obj->parent, ep, FALSE ); return retval; } return retval; } void xi_event( XinWindow win, XinEvent * ep ) { XI_OBJ *itf; XI_EVENT xiev; XI_ITF_DATA *itf_data; BOOLEAN retval; XinCursor new_cursor; if ( win == XI_NULL_WINDOW ) win = XinWindowFocusGet( ); if ( win == XI_NULL_WINDOW ) return; if ( ( itf = xi_get_itf( win ) ) == NULL ) { if ( ep->type == XinEventCreate && xi_creating_itf != NULL ) { xi_finish_interface_create( win ); xi_creating_itf = NULL; if ( ( itf = xi_get_itf( win ) ) == NULL ) return; if ( itf->v.itf->dequeue == XI_DEQUEUE_INIT && itf->v.itf->modal_wait ) { xi_dequeue( ); itf->v.itf->dequeue = XI_DEQUEUE_COMPLETE; } } else return; } itf_data = itf->v.itf; MEMCLEAR( xiev ); if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { xiev.type = XIE_XIN_EVENT; xiev.v.xin_event = *ep; } #ifdef XI_USE_XVT else { xiev.type = XIE_XVT_EVENT; XinXvtEventGet( &xiev.v.xvte ); } #endif xiev.refused = FALSE; if ( !call_cb( itf, &xiev ) ) return; if ( xiev.refused ) return; /* RGM: Do we need to allow the event to change with R3 support? */ if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) *ep = xiev.v.xin_event; if ( ep->type == XinEventMouseUp ) XinWindowMouseRelease( ); if ( !xi_eh( win, ep ) ) return; if ( itf_data->dequeue == XI_DEQUEUE_CALL && !itf_data->modal_wait ) { xi_dequeue( ); itf_data->dequeue = XI_DEQUEUE_COMPLETE; if (itf_data->needs_update) XinWindowRectInvalidate( itf_data->xin_win, NULL ); } MEMCLEAR( xiev ); switch ( ep->type ) { case XinEventTimer: { xi_send_event( itf, ep, TRUE ); break; } case XinEventPaint: { if ( itf_data->dequeue != XI_DEQUEUE_COMPLETE ) { itf_data->needs_update = TRUE; do_post_event( itf, ep ); return; } if ( itf_data->update_obj ) { xi_send_event( itf_data->update_obj, ep, FALSE ); itf_data->update_obj = NULL; } else { itf->v.itf->half_baked = FALSE; draw_background( itf ); xi_send_event( itf, ep, TRUE ); } break; } case XinEventMouseDown: case XinEventMouseDouble: { XI_OBJ *itf2; itf2 = itf; itf_data->mouse_is_down = TRUE; xi_send_event( itf, ep, TRUE ); if ( xi_is_itf( itf2 ) ) if ( !itf_data->trap_explicit ) itf_data->trap_obj = itf_data->focus_obj; break; } case XinEventCharacter: if ( ep->v.character.ch == XI_KEY_BTAB ) ep->v.character.shift = FALSE; if ( itf_data->focus_obj != NULL ) xi_send_event( itf_data->focus_obj, ep, FALSE ); update_menus( ); break; case XinEventResize: xi_send_event( itf, ep, TRUE ); break; case XinEventMouseUp: #ifndef NO_PRIMARY_SELECTION #if XIWS == XIWS_XM if ( ep->v.mouse.button == 2 ) get_primary_selection( itf, win ); #endif #endif itf_data->mouse_is_down = FALSE; if ( xi_get_drag_list_obj( ) ) lm_event( itf, xi_get_drag_list_obj( )->v.list->lm, ep ); else if ( itf_data->trap_obj != NULL ) xi_send_event( itf_data->trap_obj, ep, FALSE ); if ( xi_is_itf( itf ) ) { itf_data->trap_obj = NULL; itf_data->trap_explicit = FALSE; update_menus( ); } break; case XinEventMouseMove: if ( xi_get_drag_list_obj( ) ) lm_event( itf, xi_get_drag_list_obj( )->v.list->lm, ep ); else if ( itf_data->trap_obj != NULL ) xi_send_event( itf_data->trap_obj, ep, FALSE ); else { if ( !itf_data->mouse_is_down ) { retval = xi_send_event( itf, ep, TRUE ); switch ( retval ) { case 0: new_cursor = XI_CURSOR_ARROW; break; case 1: new_cursor = XI_CURSOR_IBEAM; break; case 2: new_cursor = ( XinCursor) xi_get_pref( XI_PREF_SIZE_CURSOR_RID ); break; case 3: new_cursor = ( XinCursor ) xi_get_pref( XI_PREF_HAND_CURSOR_RID ); break; case 4: new_cursor = XI_CURSOR_CROSS; break; case 5: new_cursor = XI_CURSOR_ARROW; break; case 6: new_cursor = ( XinCursor ) xi_get_pref( XI_PREF_VSIZE_CURSOR_RID ); break; default: new_cursor = XI_CURSOR_ARROW; break; } if ( itf_data->cursor != new_cursor && !itf_data->cursor_override ) { XinWindowCursorSet( itf_data->xin_win, new_cursor ); itf_data->cursor = new_cursor; } } } break; case XinEventMenuCommand: { XinWindow win; xiev.v.cmd.tag = ep->v.menu_command.tag; xiev.v.cmd.shift = ep->v.menu_command.shift; xiev.v.cmd.control = ep->v.menu_command.control; xiev.type = XIE_COMMAND; win = itf_data->xin_win; call_cb( itf, &xiev ); if ( xi_is_window( win ) ) if ( itf_data->focus_obj != NULL ) xi_send_event( itf_data->focus_obj, ep, FALSE ); } if ( xi_is_itf( itf ) ) do_edit_menu( itf, ep ); break; case XinEventFocus: update_menus( ); break; case XinEventDestroy: { itf->v.itf->in_event_destroy = TRUE; destroy_controls( itf ); #ifdef XI_USE_TX_SUPPORT if ( xi_get_pref( XI_PREF_USE_TX_SUPPORT ) ) xi_xvt_tx_event( win, ep ); #endif xiev.type = XIE_CLEANUP; xiev.v.xi_obj = itf; call_cb( itf, &xiev ); xi_remove_window_from_list( win ); /* free the whole interface tree */ xi_tree_free( ( char * ) itf ); break; } case XinEventCloseButton: xiev.type = XIE_CLOSE; xiev.v.xi_obj = itf; call_cb( itf, &xiev ); if ( xi_is_itf( itf ) && !xiev.refused ) xi_delete( itf ); break; case XinEventQuit: if ( ep->v.quit.query ) XinAppQuitOk( ); else XinAppTerminate( ); break; case XinEventHScroll: case XinEventVScroll: /* handle XinEventHScroll, etc if list is using window scroll bars */ break; case XinEventControl: control_event( itf, win, ep ); update_menus( ); break; case XinEventHelp: { XI_OBJ *focus = xi_get_focus( itf ); if (focus != NULL && focus->help_key != NULL) XinNativeHelp( win, focus->help_key ); else if ( itf->help_key != NULL ) XinNativeHelp( win, itf->help_key ); break; } default: break; } if ( ep->type == XinEventPaint ) { /* send XVT event */ MEMCLEAR( xiev ); xiev.type = XIE_UPDATE; xiev.v.xin_event = *ep; xiev.refused = FALSE; call_cb( itf, &xiev ); xi_set_clip( xi_get_window( itf ), NULL ); } do_post_event( itf, ep ); } long xi_get_app_data( XI_OBJ * xi_obj ) { return ( xi_obj->app_data ); } long xi_get_app_data2( XI_OBJ * xi_obj ) { return ( xi_obj->app_data2 ); } unsigned long xi_get_attrib( XI_OBJ * xi_obj ) { switch ( xi_obj->type ) { case XIT_COLUMN: return ( lm_get_attrib( xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), 0, FALSE ) ); case XIT_LIST: return ( lm_get_attrib( xi_obj->v.list->lm, LM_LIST, 0, 0, FALSE ) ); case XIT_ROW: return ( lm_get_attrib( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0, FALSE ) ); case XIT_CELL: return ( lm_get_attrib( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled ) ); case XIT_BTN: return ( xi_obj->v.btn->attrib ); case XIT_CONTAINER: /* pretend that containers have attributes, and that they are always * visible and enabled */ return XI_ATR_ENABLED | XI_ATR_VISIBLE; case XIT_FORM: return ( xi_obj->v.form->attrib ); case XIT_FIELD: return ( stx_get_attrib( xi_obj->v.field->stx ) ); case XIT_TEXT: return ( xi_obj->v.text->attrib ); case XIT_LINE: return ( xi_obj->v.line->attrib ); case XIT_RECT: return ( xi_obj->v.rect->attrib ); case XIT_GROUP: return 0L; default: XinError( 20018, XinSeverityFatal, 0L ); } return 0L; } XI_OBJ * xi_get_focus( XI_OBJ * itf ) { XinWindow win; if ( itf != NULL ) return ( itf->v.itf->focus_obj ); else if ( ( win = XinWindowFocusGet( ) ) == XI_NULL_WINDOW ) return ( NULL ); else if ( xi_is_window( win ) ) { XI_OBJ *itf; itf = xi_get_itf( win ); return ( itf->v.itf->focus_obj ); } else return ( NULL ); } long * xi_get_list_info( XI_OBJ * xi_obj, int *nbr_recs ) { if ( xi_obj->type != XIT_LIST ) XinError( 20020, XinSeverityFatal, 0L ); return lm_get_list_info( xi_obj->v.list->lm, nbr_recs ); } XI_OBJ ** xi_get_member_list( XI_OBJ * xi_obj, int *nbr_members ) { int i; XI_OBJ *obj; XI_GROUP_DATA *groupdata; if ( xi_obj->type == XIT_GROUP ) { groupdata = xi_obj->v.group; if ( groupdata->objlist != NULL ) xi_tree_free( groupdata->objlist ); groupdata->objlist = ( XI_OBJ * * ) xi_tree_malloc( sizeof( XI_OBJ * ) * groupdata->nbr_cids, xi_obj ); *nbr_members = 0; for ( i = 0; i < groupdata->nbr_cids; i++ ) { obj = xi_get_obj( xi_obj->itf, groupdata->cidlist[i] ); if ( obj != NULL ) { groupdata->objlist[*nbr_members] = obj; ( *nbr_members )++; } } return ( groupdata->objlist ); } else { *nbr_members = xi_obj->nbr_children; return ( xi_obj->children ); } } /* xi_get_obj: retrieve an XI_OBJ from the interface tree given its cid. Although externally documented to work only on XIT_ITF, this will start searching at any point in the interface tree. xi_get_obj will ignore NULL objects so it can be used in the middle of creating an interface tree. */ XI_OBJ * xi_get_obj( XI_OBJ * obj, int cid ) { XI_OBJ **objlist; XI_OBJ *temp; int n; if ( obj->cid == cid ) return ( obj ); switch ( obj->type ) { case XIT_GROUP: case XIT_CELL: case XIT_ROW: if ( ( BOOLEAN ) xi_get_pref( XI_PREF_ASSERT_ON_NULL_CID ) ) XinError( 30207, XinSeverityFatal, 0L ); return ( NULL ); default: break; } /* search in child list */ objlist = xi_get_member_list( obj, &n ); for ( ; n > 0; n--, objlist++ ) { /* call recursively for generality in future versions */ if ( ( temp = xi_get_obj( *objlist, cid ) ) != NULL ) return ( temp ); } return ( NULL ); } XinRect * xi_get_rect( XI_OBJ * xi_obj, XinRect * rctp ) { return xi_get_rect_internal( xi_obj, rctp, NULL, NULL ); } XinRect * xi_get_rect_internal( XI_OBJ * xi_obj, XinRect * rctp, XinRect * old_win_rct, XinRect * new_win_rct ) { XI_OBJ **objp; XinRect rct; int i, n; switch ( xi_obj->type ) { case XIT_CONTAINER: *rctp = xi_obj->v.container->rct; break; case XIT_BTN: *rctp = xi_obj->v.btn->rct; break; case XIT_COLUMN: lm_get_rect( xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), rctp ); break; case XIT_ROW: if ( xi_obj->v.row_data.is_vert_scrolled ) memset( ( char * ) rctp, 0, sizeof( *rctp ) ); else { lm_get_rect( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, rctp ); } break; case XIT_LIST: lm_get_rect( xi_obj->v.list->lm, LM_LIST, 0, rctp ); if ( xi_obj->v.list->scroll_bar ) { xi_get_sb_rect( xi_obj, &rct ); rctp->right = rct.right; } if ( xi_obj->v.list->width ) { xi_get_hsb_rect( xi_obj, &rct ); rctp->bottom = rct.bottom; } if ( old_win_rct ) { rctp->bottom = ( int ) ( ( long ) rctp->bottom * new_win_rct->bottom / old_win_rct->bottom ); rctp->right = ( int ) ( ( long ) rctp->right * new_win_rct->right / old_win_rct->right ); } break; case XIT_ITF: case XIT_FORM: { BOOLEAN first_rect = TRUE; objp = xi_obj->children; n = xi_obj->nbr_children; for ( i = 0; i < n; objp++, i++ ) { if ( xi_get_rect_internal( *objp, &rct, old_win_rct, new_win_rct ) != NULL ) { if ( first_rect ) { first_rect = FALSE; *rctp = rct; } else XinRectEnclose( rctp, &rct, rctp ); } } break; } case XIT_FIELD: { XI_FIELD_DATA *fd; fd = xi_obj->v.field; stx_get_rect( fd->stx, rctp ); if ( fd->button ) { if ( fd->button_on_left ) rctp->left = fd->btn_rct.left; else rctp->right = fd->btn_rct.right; } break; } case XIT_TEXT: *rctp = xi_obj->v.text->rct; break; case XIT_RECT: *rctp = xi_obj->v.rect->rct; break; case XIT_LINE: { XI_LINE_DATA *line; line = xi_obj->v.line; rctp->top = min( line->pnt1.v, line->pnt2.v ); rctp->bottom = max( line->pnt1.v, line->pnt2.v ); rctp->left = min( line->pnt1.h, line->pnt2.h ); rctp->right = max( line->pnt1.h, line->pnt2.h ); break; } case XIT_GROUP: /* bounding rect is undefined */ return ( NULL ); case XIT_CELL: { XI_OBJ row; XI_OBJ *col; XI_OBJ **members; int nbr_members; int row_nbr, col_nbr; XinRect row_rct, col_rct; if ( xi_obj->v.cell.is_vert_scrolled ) memset( ( char * ) rctp, 0, sizeof( *rctp ) ); else { row_nbr = xi_obj->v.cell.row; col_nbr = xi_obj->v.cell.column; XI_MAKE_ROW( &row, xi_obj->parent, row_nbr ); xi_get_rect_internal( &row, &row_rct, old_win_rct, new_win_rct ); members = xi_get_member_list( xi_obj->parent, &nbr_members ); col = members[col_nbr]; xi_get_rect_internal( col, &col_rct, old_win_rct, new_win_rct ); xi_rect_intersect( rctp, &row_rct, &col_rct ); } break; } default: XinError( 20021, XinSeverityFatal, 0L ); } return ( rctp ); } void xi_set_rect_internal( XI_OBJ * xi_obj, XinRect * rctp ) { switch ( xi_obj->type ) { case XIT_CONTAINER: { xi_container_set_rect_internal( xi_obj, rctp ); break; } case XIT_BTN: xi_obj->v.btn->rct = *rctp; break; case XIT_LIST: lm_set_rect( xi_obj->v.list->lm, rctp ); break; case XIT_FIELD: { xi_field_set_rect_internal( xi_obj, rctp ); break; } case XIT_TEXT: xi_obj->v.text->rct = *rctp; break; case XIT_RECT: xi_obj->v.rect->rct = *rctp; break; case XIT_LINE: { /* We generate a point which is the change between old and new. */ XI_LINE_DATA *line; XinPoint point; line = xi_obj->v.line; point.v = min( line->pnt1.v, line->pnt2.v ); point.v = rctp->top - point.v; point.h = min( line->pnt1.h, line->pnt2.h ); point.h = rctp->left - point.h; line->pnt1.v += point.v; line->pnt1.h += point.h; line->pnt2.v += point.v; line->pnt2.h += point.h; break; } default: XinError( 20032, XinSeverityFatal, 0L ); } } void xi_set_rect( XI_OBJ * xi_obj, XinRect * rctp, BOOLEAN do_invalidates ) { XinRect old_rect; XinWindow win = 0L; if (do_invalidates) { win = xi_get_window( xi_obj ); xi_get_rect_internal( xi_obj, &old_rect, NULL, NULL ); XinWindowRectInvalidate( win, &old_rect ); } xi_set_rect_internal( xi_obj, rctp ); if (do_invalidates) { xi_get_rect_internal( xi_obj, &old_rect, NULL, NULL ); XinWindowRectInvalidate( win, &old_rect ); } } void xi_get_sel( XI_OBJ * xi_obj, int *selstart, int *selstop ) { XI_OBJ *focus_obj; BOOLEAN is_focus; focus_obj = xi_get_focus( xi_obj->itf ); /* check if the passed object is the focus object */ if ( focus_obj == NULL ) is_focus = FALSE; /* no focus */ else if ( focus_obj == xi_obj ) is_focus = TRUE; /* object is the focus object */ else if ( focus_obj->type != XIT_CELL || xi_obj->type != XIT_CELL ) is_focus = FALSE; /* objects are not both cells */ else /* both objects are temporary cell objects */ is_focus = ( xi_obj->v.cell.row == focus_obj->v.cell.row && xi_obj->v.cell.column == focus_obj->v.cell.column ); /* it's the focus if the row & column are */ /* the same */ if ( !is_focus ) { /* selection is only valid for focus object */ *selstart = *selstop = 0; return; } switch ( xi_obj->type ) { case XIT_CELL: if ( focus_obj->v.cell.is_vert_scrolled ) lm_focus_cell_selection_get( ( LM_DATA * ) xi_obj->parent->v.list->lm, selstart, selstop ); else lm_get_sel( xi_obj->parent->v.list->lm, selstart, selstop ); break; case XIT_FIELD: stx_get_sel( xi_obj->v.field->stx, selstart, selstop ); break; case XIT_COLUMN: case XIT_ITF: case XIT_LIST: case XIT_ROW: case XIT_BTN: case XIT_FORM: case XIT_GROUP: case XIT_TEXT: XinError( 20022, XinSeverityFatal, 0L ); break; default: break; } } char * xi_get_text( XI_OBJ * xi_obj, char *s, int len ) { char *b; b = NULL; switch ( xi_obj->type ) { case XIT_CELL: b = lm_get_text( xi_obj->parent->v.list->lm, s, len, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled ); break; case XIT_COLUMN: b = lm_get_text( xi_obj->parent->v.list->lm, s, len, LM_HEADING_TEXT, xi_obj_to_idx( xi_obj ), FALSE ); break; case XIT_ITF: b = XinWindowTitleGet( xi_obj->v.itf->xin_win ); break; case XIT_ROW: XinError( 20023, XinSeverityFatal, 0L ); case XIT_BTN: b = xi_obj->v.btn->text; break; case XIT_FIELD: b = stx_get_text( xi_obj->v.field->stx, s, len ); break; case XIT_TEXT: { XI_TEXT_DATA *text_data; text_data = xi_obj->v.text; b = text_data->text; } break; case XIT_LIST: case XIT_GROUP: case XIT_FORM: if ( s ) *s = '\0'; break; default: break; } if ( s && b ) tstrncpy( s, b, len ); return b; } XinWindow xi_get_window( XI_OBJ * xi_obj ) { return ( xi_obj->itf->v.itf->xin_win ); } /*------------------------------------------------------------------------- function: xi_scroll_rec xi_obj: list object to scroll. Must be a list object. rec: first record to go to color: color of row attrib: attribute of row -------------------------------------------------------------------------*/ int xi_scroll_rec( XI_OBJ * xi_obj, long rec, XinColor color, unsigned long attrib, int row_height ) { LM_SCROLL_ARG arg; if ( xi_obj->type != XIT_LIST ) XinError( 20024, XinSeverityFatal, 0L ); xi_obj->v.list->done_initial_xi_scroll = TRUE; MEMCLEAR( arg ); arg.lm = xi_obj->v.list->lm; /* arg.nbr_lines = 0; arg.percent = 0; arg.same_cell = 0; */ arg.rec = rec; arg.have_rec = TRUE; arg.color = color; arg.attrib = attrib; arg.row_height = row_height; arg.rec_at_top = TRUE; return lm_scroll( &arg ); } /* typedef struct _xi_scroll_record_arg { XI_OBJ* xi_obj; long record; COLOR row_color; unsigned long attrib; int row_height; BOOLEAN rec_at_top; } XI_SCROLL_RECORD_ARG; */ int xi_scroll_record( XI_SCROLL_RECORD_ARG * arg ) { LM_SCROLL_ARG lm_scroll_arg; XI_OBJ *xi_obj = arg->xi_obj; xi_obj->v.list->done_initial_xi_scroll = TRUE; MEMCLEAR( lm_scroll_arg ); lm_scroll_arg.lm = xi_obj->v.list->lm; /* lm_scroll_arg.nbr_lines = 0; lm_scroll_arg.percent = 0; * lm_scroll_arg.same_cell = 0; */ lm_scroll_arg.rec = arg->record; lm_scroll_arg.have_rec = TRUE; lm_scroll_arg.color = arg->row_color; lm_scroll_arg.attrib = arg->attrib; lm_scroll_arg.row_height = arg->row_height; lm_scroll_arg.rec_at_top = arg->rec_at_top; return lm_scroll( &lm_scroll_arg ); } /*------------------------------------------------------------------------- function: xi_scroll_internal xi_obj: list object to scroll. Must be a list object. nbr_lines: nbr of lines to scroll, may be positive or negative, may be set to XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDN percent: passed with XI_SCROLL_FIRST event same_cell: sometimes the focus goes back onto the same cell. In other cases, for instance, XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, and XI_SCROLL_PGDN, we don't want to put the focus back on the same cell, but instead, want to put the focus on the first or last fully visible row. invalidate: indicates whether to invalidate the list. This is only set to FALSE when xi_scroll_internal is called when the interface is created. -------------------------------------------------------------------------*/ int xi_scroll_internal( XI_OBJ * xi_obj, int nbr_lines, int percent, BOOLEAN same_cell ) { LM_SCROLL_ARG arg; if ( xi_obj->type != XIT_LIST ) XinError( 20037, XinSeverityFatal, 0L ); xi_obj->v.list->done_initial_xi_scroll = TRUE; MEMCLEAR( arg ); arg.lm = xi_obj->v.list->lm; arg.nbr_lines = nbr_lines; arg.percent = percent; arg.same_cell = same_cell; arg.rec_at_top = TRUE; /* arg.rec = 0; arg.have_rec = FALSE; arg.color = 0L; arg.attrib = 0L; * arg.row_height = 0; */ return lm_scroll( &arg ); } BOOLEAN xi_delete_row( XI_OBJ * xi_obj ) { int row; XI_OBJ *list_obj; BOOLEAN rv; if ( xi_obj->type != XIT_ROW ) XinError( 20025, XinSeverityFatal, 0L ); list_obj = xi_obj->parent; row = xi_obj->v.row; rv = lm_delete_row( list_obj->v.list->lm, row ); return rv; } BOOLEAN xi_insert_row( XI_OBJ * list, int row ) { BOOLEAN rv; if ( list->type != XIT_LIST ) XinError( 20026, XinSeverityFatal, 0L ); rv = lm_insert_row( list->v.list->lm, row ); return rv; } int xi_scroll( XI_OBJ * xi_obj, int nbr_lines ) { return ( xi_scroll_internal( xi_obj, nbr_lines, 0, ( BOOLEAN ) ( nbr_lines < 1000 ) ) ); } int xi_scroll_percent( XI_OBJ * xi_obj, int percent ) { return ( xi_scroll_internal( xi_obj, XI_SCROLL_FIRST, percent, FALSE ) ); } void xi_set_app_data( XI_OBJ * xi_obj, long app_data ) { xi_obj->app_data = app_data; } void xi_set_app_data2( XI_OBJ * xi_obj, long app_data ) { xi_obj->app_data2 = app_data; } void xi_set_fore_color( XI_OBJ * xi_obj, XinColor color ) { XinRect rct; switch ( xi_obj->type ) { case XIT_ROW: lm_set_color( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0, FALSE, color, FALSE ); break; case XIT_CELL: { LM_DATA *lmp = LMP( xi_obj->parent->v.list->lm ); int idx = xi_obj->v.cell.row; int idx2 = xi_obj->v.cell.column; BOOLEAN do_redraw = ( lmp->cell_data[idx][idx2].color != color ); lm_set_color( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, color, FALSE ); if ( do_redraw ) { xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); } break; } default: break; } } void xi_set_attrib( XI_OBJ * xi_obj, unsigned long attrib ) { int n; XI_OBJ **objlist; unsigned long attrib_diff; XinWindow win = xi_obj->itf->v.itf->xin_win; attrib_diff = xi_get_attrib( xi_obj ) ^ attrib; if ( !( attrib & XI_ATR_VISIBLE ) ) { XI_OBJ *focus_obj, *next_obj; focus_obj = xi_get_focus( xi_obj->itf ); if ( focus_obj == xi_obj || ( focus_obj != NULL && focus_obj->type == XIT_CELL && focus_obj->parent == xi_obj ) ) { if ( xi_obj->itf->v.itf->moving_focus ) return; next_obj = xi_find_next_obj( focus_obj, XI_NEXT_ITF_TAB, XI_PREF_ITF_TAB_CHAR ); if ( next_obj == focus_obj || ( focus_obj->type == XIT_CELL && focus_obj->parent == next_obj ) ) next_obj = next_obj->itf; xi_move_focus( next_obj ); } } switch ( xi_obj->type ) { case XIT_BTN: if ( !xi_get_native_controls( xi_obj ) ) { XI_BTN_DATA *bd; XinRect r; bd = xi_obj->v.btn; r = bd->rct; if ( bd->type == XIBT_TABBTN ) r.bottom += 2; xi_invalidate_rect( win, &r ); } else { if ( attrib_diff & XI_ATR_VISIBLE ) { XinWindow btn_win; btn_win = xi_obj->v.btn->btnctl; XinWindowShow( btn_win, ( BOOLEAN ) ( ( attrib & XI_ATR_VISIBLE ) != 0 ) ); xi_invalidate_rect( win, &xi_obj->v.btn->rct ); } if ( attrib_diff & XI_ATR_ENABLED ) XinWindowEnable( xi_obj->v.btn->btnctl, ( BOOLEAN ) ( ( attrib & XI_ATR_ENABLED ) != 0 ) ); } xi_obj->v.btn->attrib = attrib; break; case XIT_FORM: /* loop over sub-objects */ objlist = xi_get_member_list( xi_obj, &n ); for ( ; n > 0; n--, objlist++ ) xi_set_attrib( *objlist, attrib ); break; case XIT_FIELD: { XinRect rct; XI_FIELD_DATA *fd; stx_set_attrib( xi_obj->v.field->stx, attrib ); fd = xi_obj->v.field; rct = fd->rct; if ( fd->button ) if ( !fd->button_on_left ) rct.right = fd->btn_rct.right; xi_invalidate_rect( win, &rct ); break; } case XIT_GROUP: /* it is not clear how to get the proper behaviour here */ break; case XIT_LINE: { XinRect rct; XI_LINE_DATA *ld; ld = xi_obj->v.line; rct.top = min( ld->pnt1.v, ld->pnt2.v ); rct.bottom = max( ld->pnt1.v, ld->pnt2.v ); rct.left = min( ld->pnt1.h, ld->pnt2.h ); rct.right = max( ld->pnt1.h, ld->pnt2.h ); --rct.top; rct.bottom += 3; --rct.left; rct.right += 3; xi_obj->v.line->attrib = attrib; xi_invalidate_rect( win, &rct ); break; } case XIT_RECT: xi_obj->v.rect->attrib = attrib; xi_invalidate_rect( win, &xi_obj->v.rect->rct ); break; case XIT_TEXT: xi_obj->v.text->attrib = attrib; xi_invalidate_rect( win, &xi_obj->v.text->rct ); break; case XIT_ITF: /* it is not clear how to get the proper behaviour here */ break; case XIT_COLUMN: lm_set_attrib( xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), 0, FALSE, attrib, FALSE ); break; case XIT_LIST: { XI_LIST_DATA *ld; ld = xi_obj->v.list; if ( attrib & XI_ATR_VISIBLE && !ld->done_initial_xi_scroll ) { ld->done_initial_xi_scroll = TRUE; xi_scroll_internal( xi_obj, XI_SCROLL_FIRST, ld->start_percent, FALSE ); } lm_set_attrib( ld->lm, LM_LIST, 0, 0, FALSE, attrib, FALSE ); if ( ld->sb_win ) { XinWindowShow( ld->sb_win, ( BOOLEAN ) ( ( attrib & XI_ATR_VISIBLE ) != 0 ) ); XinWindowEnable( ld->sb_win, ( BOOLEAN ) ( ( attrib & XI_ATR_ENABLED ) != 0 ) ); } if ( ld->hsb_win ) { XinWindowShow( ld->hsb_win, ( BOOLEAN ) ( ( attrib & XI_ATR_VISIBLE ) != 0 ) ); XinWindowEnable( ld->hsb_win, ( BOOLEAN ) ( ( attrib & XI_ATR_ENABLED ) != 0 ) ); } break; } case XIT_ROW: lm_set_attrib( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0, FALSE, attrib, FALSE ); break; case XIT_CELL: lm_set_attrib( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, attrib, FALSE ); break; default: XinError( 20027, XinSeverityFatal, 0L ); break; } } void xi_set_bufsize( XI_OBJ * xi_obj, int size ) { XI_OBJ **objp; int i; switch ( xi_obj->type ) { case XIT_FIELD: stx_set_bufsize( xi_obj->v.field->stx, ( short ) size ); break; case XIT_COLUMN: lm_set_buf_size( xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), size ); break; case XIT_LIST: case XIT_FORM: objp = xi_obj->children; for ( i = xi_obj->nbr_children; i > 0; i--, objp++ ) xi_set_bufsize( *objp, size ); break; default: break; } } void xi_set_sel( XI_OBJ * xi_obj, int selstart, int selstop ) { switch ( xi_obj->type ) { case XIT_CELL: xi_set_focus( xi_obj ); lm_set_sel( xi_obj->parent->v.list->lm, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, selstart, selstop ); break; case XIT_FIELD: xi_set_focus( xi_obj ); stx_set_sel( xi_obj->v.field->stx, selstart, selstop ); break; case XIT_BTN: case XIT_FORM: case XIT_GROUP: case XIT_TEXT: case XIT_COLUMN: case XIT_ITF: case XIT_LIST: case XIT_ROW: XinError( 20028, XinSeverityFatal, 0L ); break; default: break; } } void xi_set_text( XI_OBJ * xi_obj, char *s ) { char *buf; size_t buf_size = 256; BOOLEAN ddd; BOOLEAN do_compare = TRUE; if ( xi_obj == xi_obj->itf->v.itf->focus_obj ) xi_obj->itf->v.itf->chg_flag = FALSE; buf = XinMemoryAlloc( buf_size ); if (xi_obj->type == XIT_CELL) { XI_OBJ *list = xi_obj->parent; int row = xi_obj->v.cell.row; int column = xi_obj->v.cell.column; LM_DATA *lmp = LMP(list->v.list->lm); LM_CELL_DATA col_data = lmp->cell_data[row][column]; if (!col_data.valid_data) do_compare = FALSE; } if (do_compare) { xi_get_text( xi_obj, buf, buf_size ); if ( !strcmp( s, buf ) ) { XinMemoryFree( buf ); return; } } XinMemoryFree( buf ); ddd = !xi_get_native_controls( xi_obj ); switch ( xi_obj->type ) { case XIT_BTN: { XI_BTN_DATA *btn; btn = xi_obj->v.btn; btn->text = ( char * ) xi_tree_realloc( btn->text, strlen( s ) + 1 ); strcpy( btn->text, s ); if ( ddd ) { if ( ( xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE ) != 0 ) xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &btn->rct ); } else XinWindowTitleSet( btn->btnctl, s ); break; } case XIT_CELL: lm_set_text( xi_obj->parent->v.list->lm, s, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled ); break; case XIT_COLUMN: lm_set_text( xi_obj->parent->v.list->lm, s, LM_HEADING_TEXT, xi_obj_to_idx( xi_obj ), FALSE ); break; case XIT_FIELD: { /* XinRect rct; */ stx_set_text( xi_obj->v.field->stx, s ); /* TODO change approach, simply draw text xi_get_rect(xi_obj, &rct); * xi_invalidate_rect(xi_obj->itf->v.itf->xin_win, &rct); */ break; } case XIT_ITF: XinWindowTitleSet( xi_obj->v.itf->xin_win, s ); break; case XIT_ROW: XinError( 20029, XinSeverityFatal, 0L ); case XIT_TEXT: { XI_TEXT_DATA *text_data; XinRect rct; text_data = xi_obj->v.text; text_data->text = ( char * ) xi_tree_realloc( text_data->text, strlen( s ) + 1 ); strcpy( text_data->text, s ); if ( ( xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE ) != 0 ) { xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &rct ); } break; } case XIT_GROUP: case XIT_FORM: case XIT_LIST: break; default: break; } } void xi_set_override_cursor( XI_OBJ* itf, XinCursor cursor, BOOLEAN flag ) { itf->v.itf->cursor_override = flag; if ( xi_is_itf( itf ) && flag && itf->v.itf->cursor != cursor ) { XinWindowCursorSet( itf->v.itf->xin_win, cursor ); itf->v.itf->cursor = cursor; } } XinColor xi_get_underlying_color( XI_OBJ * itf, XinPoint point ) { XinColor back_color = itf->v.itf->back_color; int num, num_members; XI_OBJ** objlist; XI_OBJ** cur_obj; XinRect* back_rect = NULL; objlist = xi_get_member_list( itf, &num_members ); /* Determine if the point is contained on any rectangles in the itf */ for ( num = 0, cur_obj = objlist; num < num_members; num++, cur_obj++ ) if ( (*cur_obj)->type == XIT_RECT ) { XinRect intersect; XinRect* cur_rct = &(*cur_obj)->v.rect->rct; if (XinRectPointContained( cur_rct, &point ) ) { if ( back_rect != NULL ) { XinRectIntersect( &intersect, back_rect, cur_rct ); if ( intersect.top == cur_rct->top && intersect.bottom == cur_rct->bottom && intersect.left == cur_rct->left && intersect.right == cur_rct->right ) { if ( (*cur_obj)->v.rect->back_color != 0 ) { back_color = (*cur_obj)->v.rect->back_color; back_rect = &(*cur_obj)->v.rect->rct; } } } else { if ( (*cur_obj)->v.rect->back_color != 0 ) { back_color = (*cur_obj)->v.rect->back_color; back_rect = &(*cur_obj)->v.rect->rct; } } } } return back_color; } void xi_draw_button( XI_OBJ * xi_obj, XinRect * rct, BOOLEAN enabled, BOOLEAN visible, BOOLEAN focus, BOOLEAN down, BOOLEAN dflt, BOOLEAN checked, BOOLEAN box_only, BOOLEAN draw_border ) { XI_BTN_DATA *bd; XinColor fore_color; XinColor border_color; XinPen fore_cp; XinWindow win; XI_OBJ *itf; XI_ITF_DATA *id; int leading, ascent, descent; XI_OBJ *focus_obj; XinColor color_light = 0L; XinColor color_ctrl = 0L; XinColor color_dark = 0L; if ( !visible ) return; itf = xi_obj->itf; id = itf->v.itf; if ( id->half_baked ) return; win = xi_get_window( itf ); xi_set_clip( win, NULL ); bd = xi_obj->v.btn; fore_color = XI_COLOR_BLACK; if (bd->type == XIBT_BUTTON) { color_light = aga_get_pref(AGA_PREF_BTN_COLOR_LIGHT); color_ctrl = aga_get_pref(AGA_PREF_BTN_COLOR_CTRL); color_dark = aga_get_pref(AGA_PREF_BTN_COLOR_DARK); } fore_cp = black_cpen; if ( bd->fore_color ) { fore_cp.fore_color = bd->fore_color; fore_color = bd->fore_color; } switch ( bd->type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: { int grid_width; int bline = -1; XinRect r; XinPen back_pen; BOOLEAN cr_ok; XinPoint pnt; XinColor underlying_color; pnt.h = rct->left; pnt.v = rct->top; underlying_color = xi_get_underlying_color ( itf, pnt ); r = *rct; back_pen = black_cpen; back_pen.fore_color = underlying_color; XinWindowPenSet( win, &back_pen ); XinWindowBrushSet( win, &hollow_cbrush ); if ( draw_border ) xi_draw_rect( win, &r ); xi_inflate_rect( &r, -1 ); xi_draw_rect( win, &r ); r = *rct; if ( xi_obj->v.btn->packed == TRUE ) { grid_width = ( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ); xi_inflate_rect( &r, -grid_width ); } else { XI_BTN_TYPE bt; bt = xi_obj->v.btn->type; if ( bt == XIBT_BUTTON || bt == XIBT_BUTTON_CHECKBOX || bt == XIBT_BUTTON_RADIOBTN ) xi_inflate_rect( &r, -3 ); } XinWindowDrawModeSet( win, XinDrawModeCopy ); xi_draw_3d_rect( win, &r, ( BOOLEAN ) ( down || bd->checked ), 2, color_light, color_ctrl, color_dark ); if ( bd->up_icon_rid ) { int x, y; XinRect r2; x = r.left + 2 + bd->icon_x; y = r.top + 2 + bd->icon_y; r2 = r; xi_inflate_rect( &r2, -2 ); xi_set_clip( win, &r2 ); if ( down || bd->checked) // Guy added bd->checked xi_draw_icon( win, x, y + 1, bd->down_icon_rid, XI_COLOR_BLACK, color_ctrl ); else { if ( enabled || !bd->disabled_icon_rid ) xi_draw_icon( win, x, y, bd->up_icon_rid, XI_COLOR_BLACK, color_ctrl ); else xi_draw_icon( win, x, y, bd->disabled_icon_rid, XI_COLOR_BLACK, color_ctrl ); } xi_set_clip( win, NULL ); } else if ( bd->up_bitmap != NULL ) { XinRect r2; r2 = r; xi_inflate_rect( &r2, -2 ); if ( down ) xi_bitmap_draw( bd->down_bitmap, win, &r2, &r2, FALSE ); else if ( enabled || bd->disabled_bitmap == NULL ) xi_bitmap_draw( bd->up_bitmap, win, &r2, &r2, FALSE ); else xi_bitmap_draw( bd->disabled_bitmap, win, &r2, &r2, FALSE ); xi_set_clip( win, NULL ); } else { unsigned long attrib; XinRect text_rect; // XinColor color; XinFont *fontp; attrib = XI_ATR_VCENTER | XI_ATR_HCENTER | XI_ATR_VISIBLE; if ( enabled ) XinWindowColorTextForeSet( win, fore_color ); else XinWindowColorTextForeSet( win, ( XinColor ) xi_get_pref( XI_PREF_COLOR_DISABLED ) ); text_rect = r; if ( down ) text_rect.top += 2; fontp = xi_obj->v.btn->font; if ( fontp == NULL ) fontp = xi_obj->itf->v.itf->font; if ( fontp == NULL ) fontp = xi_get_system_font( ); XinWindowColorTextBackSet( win, color_ctrl ); XinWindowTextOpaqueSet( win, FALSE ); XinWindowFontMap( win, fontp ); XinFontMetricsGet( fontp, &leading, &ascent, &descent ); xi_draw_clipped_text( win, fontp, bd->text, &text_rect, &text_rect, attrib, FALSE, 0, -1, bd->mnemonic, bd->mnemonic_instance, &bline ); } /* draw the solid line around the button that shows that it will be * pressed if the user presses cr */ focus_obj = xi_get_focus( itf ); cr_ok = FALSE; if ( focus_obj && focus_obj->type != XIT_BTN && !xi_cr_is_ok( focus_obj ) ) cr_ok = TRUE; if ( ( dflt && cr_ok ) || focus ) border_color = XI_COLOR_BLACK; else border_color = underlying_color; if ( draw_border ) { XinRect rct2; XinPen pen; rct2 = r; xi_inflate_rect( &rct2, 1 ); pen.width = 1; pen.fore_color = border_color; pen.pattern = XinPenSolid; XinWindowPenSet( win, &pen ); XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_rect( win, &rct2 ); } /* draw the dashed line inside the button that shows focus */ if ( focus && bd->up_icon_rid == 0 && bd->up_bitmap == NULL ) { XinRect rct2; /* int middle; int font_height; int font_top; */ XinPen pen; rct2 = r; xi_inflate_rect( &rct2, -3 ); /* middle = ( rct2.top + rct2.bottom ) / 2; font_height = ascent + descent + leading; font_top = middle - font_height / 2; rct2.top = middle - font_height / 2 - 3; rct2.bottom = font_top + font_height + 2; if ( bline != -1 ) rct2.bottom = bline + descent + 2; rct2.top = max( rct2.top, r.top + 3 ); rct2.bottom = min( rct2.bottom, r.bottom ); */ pen.width = 1; pen.fore_color = XI_COLOR_BLACK; pen.pattern = XinPenSolid; XinWindowPenSet( win, &pen ); XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_dotted_rect( win, &rct2 ); } break; } case XIBT_RADIOBTN: { XinRect rbrct, rct2; unsigned long attrib; XinRect text_rect; XinColor color; rbrct = *rct; rbrct.bottom -= 4; rct2 = rbrct; rct2.right = rct2.left + ( rct2.bottom - rct2.top ); XinWindowDrawModeSet( win, XinDrawModeCopy ); XinWindowPenSet( win, &hollow_cpen ); if ( id->back_color && !box_only ) { XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_rect( win, rct ); } xi_draw_3d_diamond( win, &rct2, checked, down, down ? 2 : 1, down ? bd->fore_color : 0L ); if ( checked ) { XinRect rct; rct = rct2; rct.top += 4; rct.left += 4; rct.bottom -= 4; rct.right -= 4; xi_draw_3d_diamond( win, &rct, FALSE, TRUE, rct.right - rct.left, enabled ? bd->fore_color : xi_get_pref( XI_PREF_COLOR_DISABLED ) ); } if ( !box_only ) { XinPen cpen; XinFont *fontp; attrib = XI_ATR_VCENTER | XI_ATR_VISIBLE; if ( enabled ) XinWindowColorTextForeSet( win, fore_color ); else XinWindowColorTextForeSet( win, ( XinColor ) xi_get_pref( XI_PREF_COLOR_DISABLED ) ); text_rect = *rct; text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 2; fontp = xi_obj->v.btn->font; if ( fontp == NULL ) fontp = xi_obj->itf->v.itf->font; if ( fontp == NULL ) fontp = xi_get_system_font( ); color = ( XinColor ) xi_get_pref( XI_PREF_COLOR_CTRL ); XinWindowColorTextBackSet( win, color ); XinWindowTextOpaqueSet( win, FALSE ); XinWindowFontMap( win, fontp ); xi_draw_clipped_text( win, fontp, bd->text, &text_rect, &text_rect, attrib, FALSE, 0, -1, bd->mnemonic, bd->mnemonic_instance, NULL ); if ( focus ) { cpen = black_cpen; cpen.pattern = XinPenSolid; XinWindowPenSet( win, &cpen ); XinWindowBrushSet( win, &hollow_cbrush ); text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 4; xi_draw_dotted_rect( win, &text_rect ); } else { /* if ( id->back_color ) { cpen = black_cpen; cpen.fore_color = id->back_color; XinWindowPenSet( win, &cpen ); XinWindowBrushSet( win, &hollow_cbrush ); text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 4; xi_draw_rect( win, &text_rect ); } */ } } break; } case XIBT_TABBTN: { XinRect tab_rect, rect; XinBrush back_brush; XinPen highlight_pen; XinPen shadow_pen; BOOLEAN checked_is_to_right; BOOLEAN checked_is_to_left; int index, baseline; XinFont *fontp; unsigned long attrib; back_brush.pattern = XinBrushSolid; back_brush.fore_color = ( XinColor ) xi_get_pref( XI_PREF_COLOR_CTRL ); XinWindowBrushSet( win, &back_brush ); xi_set_clip( win, NULL ); XinWindowDrawModeSet( win, XinDrawModeCopy ); XinWindowPenSet( win, &hollow_cpen ); highlight_pen = black_cpen; highlight_pen.fore_color = xi_get_pref( XI_PREF_COLOR_LIGHT ); shadow_pen = black_cpen; shadow_pen.fore_color = xi_get_pref( XI_PREF_COLOR_DARK ); index = xi_obj_to_idx( xi_obj ); if ( index < xi_obj->parent->nbr_children - 1 ) checked_is_to_right = xi_obj->parent->children[index + 1]->v.btn->checked; else checked_is_to_right = FALSE; if ( index > 0 ) checked_is_to_left = xi_obj->parent->children[index - 1]->v.btn->checked; else checked_is_to_left = FALSE; tab_rect = *rct; ++tab_rect.bottom; if ( xi_obj->v.btn->checked ) { XinPoint p1, p2; { XinRect temp = tab_rect; temp.top++; temp.left++; xi_draw_rect( win, &temp ); } XinWindowPenSet( win, &highlight_pen ); /* left line */ p1.h = tab_rect.left; p1.v = tab_rect.bottom - 1; xi_move_to( win, p1 ); p2.h = tab_rect.left; p2.v = tab_rect.top + 2; xi_draw_line( win, p2 ); /* diagonal line from left edge to top */ p1.h = tab_rect.left; p1.v = tab_rect.top + 3; xi_move_to( win, p1 ); p2.h = tab_rect.left + 3; p2.v = tab_rect.top; xi_draw_line( win, p2 ); /* top line */ p1.h = tab_rect.left + 2; p1.v = tab_rect.top; xi_move_to( win, p1 ); p2.h = tab_rect.right - 2; p2.v = tab_rect.top; xi_draw_line( win, p2 ); /* shadow and black lines on right */ XinWindowPenSet( win, &shadow_pen ); p1.h = tab_rect.right - 2; p1.v = tab_rect.top; xi_move_to( win, p1 ); p2.h = tab_rect.right - 2; p2.v = tab_rect.bottom; xi_draw_line( win, p2 ); XinWindowPenSet( win, &black_cpen ); p1.h = tab_rect.right - 1; p1.v = tab_rect.top + 1; xi_move_to( win, p1 ); p2.h = tab_rect.right - 1; p2.v = tab_rect.bottom; xi_draw_line( win, p2 ); } else { XinPoint p1, p2; { XinRect temp = tab_rect; temp.top += 4; if ( !checked_is_to_left ) temp.left++; xi_draw_rect( win, &temp ); } XinWindowPenSet( win, &highlight_pen ); /* draw line on left edge of tab */ if ( !checked_is_to_left ) { p1.h = tab_rect.left; p1.v = tab_rect.bottom - 2; xi_move_to( win, p1 ); p2.h = tab_rect.left; p2.v = tab_rect.top + 4; xi_draw_line( win, p2 ); } /* diagonal line from left edge to top */ if ( checked_is_to_left ) { p1.h = tab_rect.left; p1.v = tab_rect.top + 5; xi_move_to( win, p1 ); p2.h = tab_rect.left + 2; p2.v = tab_rect.top + 3; xi_draw_line( win, p2 ); } else { p1.h = tab_rect.left; p1.v = tab_rect.top + 6; xi_move_to( win, p1 ); p2.h = tab_rect.left + 3; p2.v = tab_rect.top + 3; xi_draw_line( win, p2 ); } /* top line */ p1.h = tab_rect.left + 2; p1.v = tab_rect.top + 3; xi_move_to( win, p1 ); p2.h = tab_rect.right - 2; p2.v = tab_rect.top + 3; xi_draw_line( win, p2 ); /* shadow line on right */ XinWindowPenSet( win, &shadow_pen ); p1.h = tab_rect.right - 2; p1.v = tab_rect.top + 3; xi_move_to( win, p1 ); p2.h = tab_rect.right - 2; p2.v = tab_rect.bottom - 2; xi_draw_line( win, p2 ); /* black line on right */ if ( !checked_is_to_right ) { XinWindowPenSet( win, &black_cpen ); p1.h = tab_rect.right - 1; p1.v = tab_rect.top + 4; xi_move_to( win, p1 ); p2.h = tab_rect.right - 1; p2.v = tab_rect.bottom - 2; xi_draw_line( win, p2 ); } XinWindowPenSet( win, &highlight_pen ); p1.h = tab_rect.left; p1.v = tab_rect.bottom - 1; xi_move_to( win, p1 ); p2.h = tab_rect.right; p2.v = tab_rect.bottom - 1; xi_draw_line( win, p2 ); } fontp = xi_obj->v.btn->font; if ( !fontp ) fontp = xi_obj->itf->v.itf->font; if ( !fontp ) fontp = xi_get_system_font( ); if ( checked ) { XinFont *font; XinFontCopy( &font, fontp ); XinFontBoldSet( font, TRUE ); fontp = font; } XinWindowFontMap( win, fontp ); XinFontMetricsGet( fontp, &leading, &ascent, &descent ); attrib = XI_ATR_HCENTER | XI_ATR_VCENTER | XI_ATR_VISIBLE; rect = tab_rect; ++rect.left; rect.right -= 2; rect.top += 3; if ( enabled ) XinWindowColorTextForeSet( win, fore_cp.fore_color ); else XinWindowColorTextForeSet( win, ( XinColor ) xi_get_pref( XI_PREF_COLOR_DISABLED ) ); XinWindowTextOpaqueSet( win, FALSE ); xi_draw_clipped_text( win, fontp, bd->text, &rect, &rect, attrib, FALSE, 0, -1, bd->mnemonic, bd->mnemonic_instance, NULL ); #if XIWS == XIWS_WM NOREF( rule_and_space ); baseline = rect.top + 8; #else baseline = rect.top + leading + ascent + ( rect.bottom - rect.top - leading - ascent - descent ) / 2 - 1; #endif if ( focus ) { rect.top = baseline - leading - ascent; rect.bottom = baseline + descent - 1; ++rect.left; --rect.right; XinWindowPenSet( win, &black_cpen ); xi_draw_dotted_rect( win, &rect ); } break; } case XIBT_CHECKBOX: { XinRect cbrct, rct2; unsigned long attrib; XinRect text_rect; XinColor color; cbrct = *rct; cbrct.bottom -= 4; rct2 = cbrct; rct2.right = rct2.left + ( rct2.bottom - rct2.top ); XinWindowDrawModeSet( win, XinDrawModeCopy ); XinWindowPenSet( win, &hollow_cpen ); if ( id->back_color && !box_only ) { XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_rect( win, rct ); } if ( down ) { XinWindowPenSet( win, &fore_cp ); XinWindowBrushSet( win, &hollow_cbrush ); xi_draw_thick_rect( win, &rct2, 2 ); } else xi_draw_3d_rect( win, &rct2, down, 1, 0L, 0L, 0L ); if ( !enabled ) fore_cp.fore_color = xi_get_pref( XI_PREF_COLOR_DISABLED ); if ( checked ) { XinPoint pnt1, pnt2; XinWindowPenSet( win, &fore_cp ); pnt1.h = rct2.left + 2; pnt1.v = rct2.bottom - 7; xi_move_to( win, pnt1 ); pnt2.h = pnt1.h; pnt2.v = pnt1.v + 5; xi_draw_line( win, pnt2 ); pnt1.h++; pnt1.v--; xi_move_to( win, pnt1 ); pnt2.h++; xi_draw_line( win, pnt2 ); pnt1.h++; pnt1.v = rct2.bottom - 5; pnt2 = pnt1; pnt2.v += 2; while ( pnt1.v >= ( rct2.top + 3 ) && pnt1.h <= ( rct2.right - 4 ) ) { xi_move_to( win, pnt1 ); xi_draw_line( win, pnt2 ); pnt1.h++; pnt1.v--; pnt2.h++; pnt2.v--; } pnt1.v++; xi_move_to( win, pnt1 ); xi_draw_line( win, pnt2 ); } if ( !box_only ) { XinFont *fontp; attrib = XI_ATR_VCENTER | XI_ATR_VISIBLE; if ( enabled ) XinWindowColorTextForeSet( win, fore_color ); else XinWindowColorTextForeSet( win, ( XinColor ) xi_get_pref( XI_PREF_COLOR_DISABLED ) ); text_rect = *rct; text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 2; fontp = xi_obj->v.btn->font; if ( !fontp ) fontp = xi_obj->itf->v.itf->font; if ( fontp == NULL ) fontp = xi_get_system_font( ); color = ( XinColor ) xi_get_pref( XI_PREF_COLOR_CTRL ); XinWindowColorTextBackSet( win, color ); XinWindowTextOpaqueSet( win, FALSE ); XinWindowFontMap( win, fontp ); xi_draw_clipped_text( win, fontp, bd->text, &text_rect, &text_rect, attrib, FALSE, 0, -1, bd->mnemonic, bd->mnemonic_instance, NULL ); xi_set_clip( win, NULL ); if ( focus ) { XinPen cpen; cpen = black_cpen; XinWindowPenSet( win, &cpen ); XinWindowBrushSet( win, &hollow_cbrush ); text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 4; xi_draw_dotted_rect( win, &text_rect ); } else { /* if ( id->back_color ) { XinPen cpen; cpen = black_cpen; cpen.fore_color = id->back_color; XinWindowPenSet( win, &cpen ); XinWindowBrushSet( win, &hollow_cbrush ); text_rect.left = rct2.right + ( rct2.right - rct2.left ) / 4; xi_draw_rect( win, &text_rect ); } */ } } break; } } } /* -------------------------------------------------------------------------*/ /* xi_set_fixed_columns */ /* -------------------------------------------------------------------------*/ void xi_set_fixed_columns( XI_OBJ * list, int new_fixed_count ) { if ( list->type != XIT_LIST ) XinError( 20031, XinSeverityFatal, 0L ); lm_set_fixed_columns( list->v.list->lm, new_fixed_count ); } /* -------------------------------------------------------------------------*/ /* xi_get_fixed_columns */ /* -------------------------------------------------------------------------*/ int xi_get_fixed_columns( XI_OBJ * list ) { if ( list->type != XIT_LIST ) XinError( 20038, XinSeverityFatal, 0L ); return lm_get_fixed_columns( list->v.list->lm ); } /* -------------------------------------------------------------------------*/ /* xi_get_handle */ /* -------------------------------------------------------------------------*/ long xi_get_handle( XI_OBJ * list, XI_OBJ * child ) { LM_DATA *lm_data; if ( list->type != XIT_LIST ) return -1L; lm_data = ( LM_DATA * ) list->v.list->lm; switch ( child->type ) { case XIT_ROW: { int row = child->v.row; if ( child->v.row_data.is_vert_scrolled ) return lm_focus_rec_get( lm_data ); if ( row >= 0 && row < lm_data->nbr_realized_rows ) return lm_data->recs[row]; break; } case XIT_CELL: { int row; if ( child->v.cell.is_vert_scrolled ) return lm_focus_rec_get( lm_data ); row = child->v.cell.row; if ( row >= 0 && row < lm_data->nbr_realized_rows ) return lm_data->recs[row]; break; } default: break; } return -1L; } /* -------------------------------------------------------------------------*/ /* xi_field_calc_height_font */ /* -------------------------------------------------------------------------*/ int xi_field_calc_height_font( XinFont * font ) { if ( font == 0 ) font = xi_get_system_font( ); return xi_get_fu_height_font( font ); } /* -------------------------------------------------------------------------*/ /* xi_button_calc_height_font */ /* -------------------------------------------------------------------------*/ int xi_button_calc_height_font( XinFont * font ) { return xi_field_calc_height_font( font ); } /* -------------------------------------------------------------------------*/ /* xi_field_calc_width_font */ /* -------------------------------------------------------------------------*/ int xi_field_calc_width_font( XinFont * font, char *string ) { int result; XinWindow win; XinRect rct = {-1000, -1000, -900, -900}; XinFont *calc_font; if ( font ) calc_font = font; else calc_font = xi_get_system_font( ); { XinWindowDef Def; MEMCLEAR( Def ); Def.type = XinWindowTypeDocument; Def.border_style = XinBorderFixed; Def.p_rect = &rct; Def.title = ""; win = XinWindowCreate( &Def ); } XinWindowFontMap( win, calc_font ); result = XinFontTextWidthGet( calc_font, string, -1 ) + 4; XinFontUnmap( calc_font ); /* RGM: Unmap hack */ XinWindowDestroy( win ); return result; } /* -------------------------------------------------------------------------*/ /* xi_list_def_get_rows */ /* -------------------------------------------------------------------------*/ int xi_list_def_get_rows( XI_OBJ_DEF * list_def ) { int pix_row_spacing, height, pix_row1_top, title_height; if ( list_def->v.list->one_row_list ) return 1; lm_get_vertical_metrics( list_def, &pix_row1_top, &pix_row_spacing, &height, &title_height ); return height / pix_row_spacing; } /* -------------------------------------------------------------------------*/ /* xi_list_def_get_height */ /* -------------------------------------------------------------------------*/ int xi_list_def_get_client_height( XI_OBJ_DEF * list_def, int rows ) { int pix_row_spacing, height, pix_row1_top, title_height; lm_get_vertical_metrics( list_def, &pix_row1_top, &pix_row_spacing, &height, &title_height ); return title_height + rows * pix_row_spacing + ( BORDER_WIDTH - RULE_WIDTH_H ); } /* -------------------------------------------------------------------------*/ /* xi_list_def_get_height */ /* -------------------------------------------------------------------------*/ int xi_list_def_get_outer_height( XI_OBJ_DEF * list_def, int rows ) { int result; result = xi_list_def_get_client_height( list_def, rows ); return result + ( int ) xi_get_pref( XI_PREF_SB_HEIGHT ); } /* -------------------------------------------------------------------------*/ /* button_get_horz_padding */ /* -------------------------------------------------------------------------*/ static int button_get_horz_padding( int type, int height, BOOLEAN packed ) { switch ( type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: if ( packed ) return ( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ) * 2; return 6; case XIBT_RADIOBTN: return height + height / 2 - 6; case XIBT_TABBTN: return height + 4; case XIBT_CHECKBOX: return height + height / 2 - 6; } return 0; } /* -------------------------------------------------------------------------*/ /* xi_button_calc_height */ /* -------------------------------------------------------------------------*/ int xi_button_calc_pixel_height( int height ) { return height + 6; } /* -------------------------------------------------------------------------*/ /* xi_button_calc_height */ /* -------------------------------------------------------------------------*/ int xi_button_calc_pixel_width( int width ) { return width + 6; } /* -------------------------------------------------------------------------*/ /* xi_button_def_get_width */ /* -------------------------------------------------------------------------*/ int xi_button_def_get_width( XI_OBJ_DEF * obj_def ) { XinFont *font; XinRect rct = {-1000, -1000, -900, -900}; XinWindow win; int width; XI_BTN_DEF *button; if ( obj_def->type != XIT_BTN ) return 0; font = xi_def_get_font( obj_def ); { XinWindowDef Def; MEMCLEAR( Def ); Def.type = XinWindowTypeDocument; Def.border_style = XinBorderFixed; Def.p_rect = &rct; Def.title = ""; win = XinWindowCreate( &Def ); } XinWindowFontMap( win, font ); button = obj_def->v.btn; width = XinFontTextWidthGet( font, button->text, -1 ); width += button_get_horz_padding( button->type, xi_get_fu_height_font( font ), FALSE ); XinFontDestroy( font ); XinWindowDestroy( win ); return width; } /* -------------------------------------------------------------------------*/ /* xi_container_def_get_btn_width */ /* -------------------------------------------------------------------------*/ int xi_container_def_get_btn_width( XI_OBJ_DEF * obj_def ) { int i; XinFont *font; XinRect rct = {-1000, -1000, -900, -900}; XinWindow win; int max_width; XI_CONTAINER_DEF *container; BOOLEAN packed; if ( obj_def->type != XIT_CONTAINER || obj_def->nbr_children <= 0 ) return 0; font = xi_def_get_font( obj_def ); max_width = 0; { XinWindowDef Def; MEMCLEAR( Def ); Def.type = XinWindowTypeDocument; Def.border_style = XinBorderFixed; Def.p_rect = &rct; Def.title = ""; win = XinWindowCreate( &Def ); } XinWindowFontMap( win, font ); for ( i = 0; i < obj_def->nbr_children; ++i ) { XI_BTN_DEF *button; int width; button = obj_def->children[i]->v.btn; width = XinFontTextWidthGet( font, button->text, -1 ); max_width = max( width, max_width ); } container = obj_def->v.container; packed = ( ( container->orientation == XI_GRID_HORIZONTAL || container->orientation == XI_GRID_VERTICAL ) && container->packed ); max_width += button_get_horz_padding( obj_def->children[0]->v.btn->type, xi_get_fu_height_font( font ), packed ); XinFontDestroy( font ); XinWindowDestroy( win ); return max_width; } /* -------------------------------------------------------------------------*/ /* xi_container_def_get_width */ /* -------------------------------------------------------------------------*/ int xi_container_def_get_width( XI_OBJ_DEF * obj_def ) { XI_CONTAINER_DEF *container; container = obj_def->v.container; switch ( container->orientation ) { case XI_STACK_HORIZONTAL: { int horz_spacing; if ( container->packed ) horz_spacing = 0; else if ( ( horz_spacing = ( int ) xi_get_pref( XI_PREF_HORZ_PIXEL_SPACING ) ) == 0 ) { XinFont *font; font = xi_def_get_font( obj_def ); horz_spacing = ( short ) ( ( xi_get_pref( XI_PREF_HORZ_SPACING ) * xi_get_fu_width_font( font ) ) / XI_FU_MULTIPLE ); XinFontDestroy( font ); } return xi_container_def_get_btn_width( obj_def ) * obj_def->nbr_children + ( obj_def->nbr_children - 1 ) * horz_spacing; } case XI_STACK_VERTICAL: return xi_container_def_get_btn_width( obj_def ); default: break; } return 0; } /* -------------------------------------------------------------------------*/ /* xi_container_def_get_height */ /* -------------------------------------------------------------------------*/ int xi_container_def_get_height( XI_OBJ_DEF * obj_def ) { XI_CONTAINER_DEF *container; XinFont *font; int height; int vert_spacing; int top_offset; if ( obj_def->nbr_children == 0 ) return 0; container = obj_def->v.container; font = xi_def_get_font( obj_def ); height = xi_button_calc_height_font( font ); XinFontDestroy( font ); if ( container->orientation == XI_STACK_HORIZONTAL ) return height; if ( container->orientation != XI_STACK_VERTICAL ) return 0; switch ( obj_def->children[0]->v.btn->type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: case XIBT_TABBTN: if ( container->packed ) vert_spacing = 0; else if ( ( vert_spacing = ( int ) xi_get_pref( XI_PREF_VERT_PIXEL_SPACING ) ) == 0 ) vert_spacing = ( int ) ( ( xi_get_pref( XI_PREF_VERT_SPACING ) * height ) / XI_FU_MULTIPLE ); top_offset = vert_spacing / 2; break; case XIBT_CHECKBOX: case XIBT_RADIOBTN: vert_spacing = 0; top_offset = 0; break; default: vert_spacing = 0; top_offset = 0; break; } return height * obj_def->nbr_children + vert_spacing * ( obj_def->nbr_children - 1 ) + top_offset; } void xi_force_focus_cell_visible( XI_OBJ * list ) { int row, column; BOOLEAN v_scrolled; LM_FOCUS_CELL_VISIBLE_FORCE_ARGS args; LM_DATA *lmp = ( LM_DATA * ) list->v.list->lm; lm_focus_cell_get( lmp, &row, &column, &v_scrolled ); MEMCLEAR( args ); args.lmp = ( LM_DATA * ) list->v.list->lm; args.row = row; args.column = column; args.vert_scrolled = v_scrolled; lm_focus_cell_visible_force( &args ); } BOOLEAN xi_cell_data_valid( XI_OBJ * cell ) { XI_OBJ * list = cell->parent; LM_DATA *lmp = ( LM_DATA * ) list->v.list->lm; if (lmp->nbr_realized_rows <= cell->v.cell.row || lmp->nbr_columns <= cell->v.cell.column) return FALSE; return lmp->cell_data[cell->v.cell.row][cell->v.cell.column].valid_data; }