/******************************************************************************* * 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 "xiutils.h" #include "xitext.h" #include "xistx.h" #include "xilm.h" #include "xilmst.h" #if XIWS == XIWS_WM #define STX_VERT_FUDGE 0 #define BORDER_WIDTH 8 #define EDIT_BORDER_WIDTH_Y 0 #define EDIT_BORDER_SPACE_Y 0 #define BORDER_WIDTH_X 8 #define BORDER_WIDTH_Y 0 #define BORDER_SPACE_X 0 #define BORDER_SPACE_Y 0 #else #define STX_VERT_FUDGE 6 #define BORDER_WIDTH 2 #define EDIT_BORDER_WIDTH_Y 1 #define EDIT_BORDER_SPACE_Y 1 #define BORDER_WIDTH_X 1 #define BORDER_WIDTH_Y 1 #define BORDER_SPACE_X 1 #define BORDER_SPACE_Y 1 #endif XinFont *xi_sysfont = NULL; static XI_OBJ *xi_drag_list_obj = NULL; #define MAX_RADIO_BUTTONS 30 XinBrush ltgray_cbrush = {XinBrushSolid, XI_COLOR_LTGRAY}; XinBrush gray_cbrush = {XinBrushSolid, XI_COLOR_GRAY}; XinBrush hollow_cbrush = {XinBrushHollow, XI_COLOR_WHITE}; XinPen hollow_cpen = {0, XinPenHollow, XI_COLOR_WHITE}; XinPen black_cpen = {1, XinPenSolid, XI_COLOR_BLACK}; XinPen rubber_cpen = {1, XinPenDashed, XI_COLOR_BLACK}; XinBrush white_cbrush = {XinBrushSolid, XI_COLOR_WHITE}; static XinWindow cur_window; static XI_OBJ *cur_itf; static int cur_delta_x; static int cur_delta_y; static BOOLEAN font_set = FALSE; static BOOLEAN update_pending = FALSE; static int xi_sysvals[XI_NBR_SYSVALS]; static long xi_preferences[XI_NBR_PREFERENCES] = { 1, /* XI_PREF_OVERLAP */ '\t', /* XI_PREF_FORM_TAB_CHAR */ XI_KEY_BTAB, /* XI_PREF_FORM_BACKTAB_CHAR */ 1, /* XI_PREF_SCROLL_INC */ TRUE, /* XI_PREF_3D_LOOK */ FALSE, /* XI_PREF_USE_APP_DATA */ FALSE, /* XI_PREF_AUTOSEL_ON_MOUSE */ 1, /* XI_PREF_CELL_BTN_ICON_X */ 1, /* XI_PREF_CELL_BTN_ICON_Y */ FALSE, /* XI_PREF_R4_API */ '#', /* XI_PREF_PASSWORD_CHAR */ FALSE, /* XI_PREF_USE_TX_SUPPORT */ FALSE, /* XI_PREF_SINGLE_CLICK_COL_SELECT */ #if XIWS == XIWS_WM 0, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 8, /* XI_PREF_SB_WIDTH */ 8, /* XI_PREF_SB_HEIGHT */ 0, /* XI_PREF_SIZE_CURSOR_RID */ 0, /* XI_PREF_HAND_CURSOR_RID */ 0, /* XI_PREF_VSIZE_CURSOR_RID */ 0, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DARK */ FALSE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ K_F2, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 24, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 0, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 16, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE, /* XI_PREF_NO_BUTTON_SPACE */ #elif XIWS == XIWS_PM 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 16, /* XI_PREF_SB_WIDTH */ 16, /* XI_PREF_SB_HEIGHT */ XI_CURSOR_RESIZE, /* XI_PREF_SIZE_CURSOR_RID */ XI_CURSOR_HAND, /* XI_PREF_HAND_CURSOR_RID */ XI_CURSOR_VRESIZE, /* XI_PREF_VSIZE_CURSOR_RID */ COMBO_ICON, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ 0, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 2, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 24, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE, /* XI_PREF_NO_BUTTON_SPACE */ #elif XIWS == XIWS_MAC 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 16, /* XI_PREF_SB_WIDTH */ 16, /* XI_PREF_SB_HEIGHT */ XI_CURSOR_RESIZE, /* XI_PREF_SIZE_CURSOR_RID */ XI_CURSOR_HAND, /* XI_PREF_HAND_CURSOR_RID */ XI_CURSOR_VRESIZE, /* XI_PREF_VSIZE_CURSOR_RID */ COMBO_ICON, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ 0, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 2, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 40, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE /* XI_PREF_NO_BUTTON_SPACE */ /* Some compiler on the Mac won't accept a comma on the last entry, so don't * put one. This means you have to put a comma after the old last entry when * you add a new one. */ #elif XIWS == XIWS_XM 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 16, /* XI_PREF_SB_WIDTH */ 16, /* XI_PREF_SB_HEIGHT */ XI_CURSOR_RESIZE, /* XI_PREF_SIZE_CURSOR_RID */ XI_CURSOR_HAND, /* XI_PREF_HAND_CURSOR_RID */ XI_CURSOR_VRESIZE, /* XI_PREF_VSIZE_CURSOR_RID */ COMBO_ICON, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_DKGRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ 0, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 2, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 0, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE, /* XI_PREF_NO_BUTTON_SPACE */ #elif XIWS == XIWS_WIN 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 16, /* XI_PREF_SB_WIDTH */ 16, /* XI_PREF_SB_HEIGHT */ XI_CURSOR_RESIZE, /* XI_PREF_SIZE_CURSOR_RID */ XI_CURSOR_HAND, /* XI_PREF_HAND_CURSOR_RID */ XI_CURSOR_VRESIZE, /* XI_PREF_VSIZE_CURSOR_RID */ COMBO_ICON, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ XI_KEY_DOWN | XI_MOD_ALT, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 2, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 30, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE, /* XI_PREF_NO_BUTTON_SPACE */ #else 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 16, /* XI_PREF_SB_WIDTH */ 16, /* XI_PREF_SB_HEIGHT */ 0, /* XI_PREF_SIZE_CURSOR_RID */ 0, /* XI_PREF_HAND_CURSOR_RID */ 0, /* XI_PREF_VSIZE_CURSOR_RID */ 0, /* XI_PREF_COMBO_ICON */ XI_COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ XI_COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ 0, /* XI_PREF_BUTTON_KEY */ TRUE, /* XI_PREF_LIMIT_MIN_WIN_SIZE */ 5, /* XI_PREF_DEFAULT_MAX_LINES_IN_CELL */ FALSE, /* XI_PREF_KEEP_FOCUS_FIXED */ TRUE, /* XI_PREF_NATIVE_CTRLS */ XI_KEY_F3, /* XI_PREF_ITF_TAB_CHAR */ XI_KEY_F4, /* XI_PREF_ITF_BACKTAB_CHAR */ 16, /* XI_PREF_ITF_WS_RIGHT */ 4, /* XI_PREF_ITF_WS_BOTTOM */ 40, /* XI_PREF_VIR_SP_H */ 20, /* XI_PREF_VIR_SP_V */ TRUE, /* XI_PREF_DBL_PRESSES_BUTTON */ 1, /* XI_PREF_CONTAINER_GRID_WIDTH */ TRUE, /* XI_PREF_MULTILINE_QUICK_PASTE */ XI_COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* XI_PREF_BUTTON_HEIGHT */ 32, /* XI_PREF_BUTTON_PAD */ 16, /* XI_PREF_HORZ_SPACING */ 2, /* XI_PREF_VERT_SPACING */ 0, /* XI_PREF_HORZ_PIXEL_SPACING */ 0, /* XI_PREF_VERT_PIXEL_SPACING */ 0, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ FALSE, /* XI_PREF_NO_BUTTON_SPACE */ #endif }; static long aga_preferences[AGA_NBR_PREFERENCES] = { XI_COLOR_LTGRAY, XI_COLOR_GRAY, XI_COLOR_DKGRAY}; XinRect big_clip = { 0, 0, 10000, 10000}; typedef struct { XinFont *font; int leading; int ascent; int descent; int char_width; } FONT_INFO; static FONT_INFO* font_info = NULL; static int font_info_cnt = 0; static void xi_caret_suspend( XinWindow win ); static void xi_caret_restore( XinWindow win ); static void recalc_metrics( XI_OBJ * xi_obj ); char * tstrncpy( char *dst, char *src, int n ) { gstrncpy( dst, src, n ); dst[n - 1] = '\0'; return ( dst ); } char * gstrncpy( char *dst, char *src, int n ) { char *p = dst; while ( n > 0 && *src != 0 ) { *p++ = *src++; n--; } if ( n != 0 ) *p++ = '\0'; return ( dst ); } void order_ints( int *ip1, int *ip2 ) { int temp; if ( *ip1 > *ip2 ) { temp = *ip1; *ip1 = *ip2; *ip2 = temp; } } XinRect * xi_inflate_rect( XinRect * rct, int amount ) { rct->bottom += amount; rct->right += amount; rct->left -= amount; rct->top -= amount; return ( rct ); } void xi_offset_rect( XinRect * rct, int delta_x, int delta_y ) { rct->top += delta_y; rct->bottom += delta_y; rct->right += delta_x; rct->left += delta_x; } int clip( int val, int mn, int mx ) { return ( val < mn ? mn : ( val > mx ? mx : val ) ); } void xi_realloc_array( void **ptr, int nbr, size_t sz, void *parent ) { BOOLEAN is_zero = ( nbr * sz ) == 0; if ( !*ptr ) { if ( is_zero ) *ptr = NULL; else *ptr = ( void * ) xi_tree_malloc( nbr * sz, parent ); } else { if ( is_zero ) { xi_tree_free( *ptr ); *ptr = NULL; } else *ptr = ( void * ) xi_tree_realloc( *ptr, nbr * sz ); } } static void do_vir_pan_event( XI_OBJ * itf, int h, int v, BOOLEAN before ) { XI_EVENT xiev; MEMCLEAR( xiev ); xiev.type = XIE_VIR_PAN; xiev.v.vir_pan.before_pan = before; xiev.v.vir_pan.delta_x = h; xiev.v.vir_pan.delta_y = v; ( *( XI_EH_TYPE ) itf->v.itf->xi_eh ) ( itf, &xiev ); } static void set_sb_positions( XI_OBJ * itf ) { XI_ITF_DATA *itf_data; XinWindow win; int ps; itf_data = itf->v.itf; win = xi_get_window( itf ); if ( itf_data->max_xi_pnt.v - itf_data->win_xi_pnt.v ) ps = ( int ) ( 100L * ( long ) ( itf_data->phys_xi_pnt.v ) / ( ( long ) itf_data->max_xi_pnt.v - ( long ) itf_data->win_xi_pnt.v ) ); else ps = 0; XinScrollBarPositionSet( win, XinScrollBarTypeVertical, ps ); if ( itf_data->max_xi_pnt.h - itf_data->win_xi_pnt.h ) ps = ( int ) ( 100L * ( long ) ( itf_data->phys_xi_pnt.h ) / ( ( long ) itf_data->max_xi_pnt.h - ( long ) itf_data->win_xi_pnt.h ) ); else ps = 0; XinScrollBarPositionSet( win, XinScrollBarTypeHorizontal, ps ); } void xi_get_hsb_rect( XI_OBJ * xi_obj, XinRect * rctp ) { XI_LIST_DATA *list_data; LM_DATA *lmp; XinRect rct1, rct3; XI_OBJ **members; int nbr_members; #if XIWS == XIWS_WIN XinRect r; #endif list_data = xi_obj->v.list; lmp = ( LM_DATA * ) list_data->lm; if ( list_data->have_hsb_rct ) { *rctp = list_data->hsb_rct; return; } #if XIWS == XIWS_WIN if ( list_data->hsb_win ) XinWindowRectGet( list_data->hsb_win, &r ); #endif members = xi_get_member_list( xi_obj, &nbr_members ); if ( !lmp->nbr_columns ) { rct3.left = lmp->rct.left; rct1 = lmp->rct; } else { if ( lmp->fixed_columns ) { xi_get_rect( members[lmp->fixed_columns - 1], &rct1 ); rct3.left = rct1.right; } else { xi_get_rect( members[0], &rct1 ); rct3.left = lmp->rct.left; } } /* subtract one so that the top of the horizontal scroll bar overlaps the * bottom of the list by one pixel. */ #if XIWS != XIWS_WM rct3.top = rct1.bottom - 1; rct3.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH; #else rct3.top = rct1.bottom; rct3.right = lmp->rct.left + lmp->pixel_width; #endif rct3.bottom = rct3.top + ( int ) xi_get_pref( XI_PREF_SB_HEIGHT ); #if XIWS == XIWS_WIN if ( list_data->hsb_win ) rct3.bottom = rct3.top + r.bottom; #endif if ( rct3.left >= rct3.right ) rct3.right = rct3.left + 1; *rctp = rct3; list_data->hsb_rct = rct3; list_data->have_hsb_rct = TRUE; } void xi_get_sb_rect( XI_OBJ * xi_obj, XinRect * rctp ) { XinRect rct; int offset, width; XI_LIST_DATA *list_data; LM_DATA *lmp; #if XIWS == XIWS_WIN XinRect r; #endif list_data = xi_obj->v.list; lmp = ( LM_DATA * ) list_data->lm; if ( list_data->have_sb_rct ) { *rctp = list_data->sb_rct; return; } #if XIWS == XIWS_WIN if ( list_data->sb_win ) XinWindowRectGet( list_data->sb_win, &r ); #endif lm_get_rect( list_data->lm, LM_LIST, 0, &rct ); list_data->sb_offset = offset = ( int ) xi_get_pref( XI_PREF_SB_OFFSET ); list_data->sb_width = width = ( int ) xi_get_pref( XI_PREF_SB_WIDTH ); /* subtract one from the left of the scroll bar rectangle, so that the left * edge of the scroll bar overlaps the right double wide line, by one pixel. */ #if XIWS != XIWS_WM if ( list_data->width ) rct.left = rct.left + lmp->pixel_width + offset + 2 * BORDER_WIDTH - 1; else rct.left = rct.right + offset - 1; #else if ( list_data->width ) rct.left = rct.left + lmp->pixel_width + offset; else rct.left = rct.right + offset; #endif rct.right = rct.left + width; #if XIWS == XIWS_WIN if ( list_data->sb_win ) rct.right = rct.left + r.right; #endif if ( list_data->scroll_bar_button ) { LM_DATA *lm_data; lm_data = ( LM_DATA * ) list_data->lm; list_data->sbb_rct.top = rct.top + 1; /* Add one, so that there is * room for the double line * border */ list_data->sbb_rct.bottom = lm_data->pix_row1_top - BORDER_WIDTH + 1; list_data->sbb_rct.left = rct.left; list_data->sbb_rct.right = rct.right; #if XIWS == XIWS_WIN if ( list_data->sb_win ) list_data->sbb_rct.right = list_data->sbb_rct.left + r.right; #endif #if XIWS == XIWS_WM rct.top = lm_data->pix_row1_top; #else rct.top = list_data->sbb_rct.bottom; #endif } *rctp = rct; list_data->sb_rct = rct; list_data->have_sb_rct = TRUE; } void xi_move_list_scroll_bar( XI_OBJ * xi_obj ) { XinRect rct; XinWindow win = xi_obj->itf->v.itf->xin_win; XinWindow sb_win; XI_LIST_DATA *list_data; XI_ITF_DATA *itf_data; list_data = xi_obj->v.list; if ( list_data->scroll_bar_button ) xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &list_data->sbb_rct ); xi_get_sb_rect( xi_obj, &rct ); itf_data = xi_obj->itf->v.itf; xi_offset_rect( &rct, -itf_data->delta_x, -itf_data->delta_y ); sb_win = list_data->sb_win; if ( sb_win && rct.left < rct.right && rct.top < rct.bottom ) XinWindowRectSet( sb_win, &rct ); if ( list_data->scroll_bar_button ) xi_invalidate_rect( win, &list_data->sbb_rct ); } void xi_move_list_hscroll_bar( XI_OBJ * xi_obj ) { XinRect rct; XinWindow hsb_win; XI_LIST_DATA *list_data; XI_ITF_DATA *itf_data; list_data = xi_obj->v.list; xi_get_hsb_rect( xi_obj, &rct ); itf_data = xi_obj->itf->v.itf; xi_offset_rect( &rct, -itf_data->delta_x, -itf_data->delta_y ); hsb_win = list_data->hsb_win; if (hsb_win && rct.left < rct.right && rct.top < rct.bottom) XinWindowRectSet( hsb_win, &rct ); } BOOLEAN xi_half_baked( XinWindow win ) { XI_OBJ *itf; itf = xi_get_itf( win ); if ( itf ) return itf->v.itf->half_baked; return FALSE; } XinFont * xi_get_system_font( void ) { return xi_sysfont; } XI_OBJ * xi_get_drag_list_obj( void ) { return xi_drag_list_obj; } int xi_get_sysval( XI_SV_TYPE valtype ) { return ( xi_sysvals[valtype] ); } void xi_set_sysval( XI_SV_TYPE valtype, int value ) { xi_sysvals[valtype] = value; } void xi_clean_up( ) { FONT_INFO* fi; int num; #ifndef NO_PRIMARY_SELECTION #if XIWS == XIWS_XM clean_primesel( ); #endif #endif if ( xi_sysfont != NULL ) XinFontDestroy( xi_sysfont ); for ( num = 0, fi = font_info; num < font_info_cnt; num++, fi++ ) XinFontDestroy( fi->font ); if ( font_info != NULL ) xi_tree_free( font_info ); font_info = NULL; font_info_cnt = 0; } long xi_get_pref( XI_PREF_TYPE pref_type ) { long pref; pref = xi_preferences[pref_type]; return pref; } void xi_set_pref( XI_PREF_TYPE preftype, long value ) { xi_preferences[preftype] = value; } long aga_get_pref(AGA_PREF_TYPE preftype) { return aga_preferences[preftype]; } void aga_set_pref(AGA_PREF_TYPE preftype, long value) { aga_preferences[preftype] = value; } void xi_set_font( XinFont * font ) { font_set = TRUE; if ( xi_sysfont != NULL ) XinFontDestroy( xi_sysfont ); XinFontCopy( &xi_sysfont, font ); } void xi_set_drag_list_obj( XI_OBJ * obj ) { xi_drag_list_obj = obj; } void xi_set_font_id( void *font_id ) { #ifdef XI_USE_XVT font_set = TRUE; if ( xi_sysfont != NULL ) XinFontDestroy( xi_sysfont ); xi_sysfont = XinFontXvtConvert( font_id ); #endif } void xi_init_sysvals( void ) { int ascent, descent, leading, height, char_width; if ( !font_set ) { xi_sysfont = XinFontCreate( ); XinFontFamilySet( xi_sysfont, XinFontFamilyHelvetica ); XinFontSizeSet( xi_sysfont, 9 ); } xi_get_font_metrics_font( xi_sysfont, &leading, &ascent, &descent, &char_width ); xi_set_sysval( XI_SV_SYSFONT_ASCENT, ascent ); xi_set_sysval( XI_SV_SYSFONT_DESCENT, descent ); xi_set_sysval( XI_SV_SYSFONT_LEADING, leading ); height = ascent + descent + leading; xi_set_sysval( XI_SV_FU_HEIGHT, height + STX_VERT_FUDGE ); xi_set_sysval( XI_SV_FU_WIDTH, char_width ); xi_set_sysval( XI_SV_SYSFONT_HEIGHT, height ); } void xi_fu_to_pu( XI_OBJ * itf, XinPoint * pnts, int nbr_pnts ) { NOREF( itf ); while ( nbr_pnts != 0 ) { pnts->v = ( short ) ( ( ( long ) pnts->v * ( long ) xi_get_fu_height( itf ) ) / ( long ) XI_FU_MULTIPLE ); pnts->h = ( short ) ( ( ( long ) pnts->h * ( long ) xi_get_fu_width( itf ) ) / ( long ) XI_FU_MULTIPLE ); pnts++; nbr_pnts--; } } void xi_pu_to_fu( XI_OBJ * itf, XinPoint * pnts, int nbr_pnts ) { long fu_h, fu_w; NOREF( itf ); fu_h = ( long ) xi_get_fu_height( itf ); fu_w = ( long ) xi_get_fu_width( itf ); while ( nbr_pnts != 0 ) { pnts->v = ( short ) ( ( ( long ) pnts->v * ( long ) XI_FU_MULTIPLE ) / fu_h ); pnts->h = ( short ) ( ( ( long ) pnts->h * ( long ) XI_FU_MULTIPLE ) / fu_w ); pnts++; nbr_pnts--; } } /* * xi_tree_realloc2() handles the degenerate case of passing in a NULL * pointer for the old pointer. */ #ifdef TREEDEBUG char * xi_tree_realloc_d2( char *oldp, size_t size, char *parent, int line, char *filename ) { if ( oldp == NULL ) return ( ( char * ) xi_tree_malloc_d( size, parent, line, filename ) ); else return ( ( char * ) xi_tree_realloc_d( oldp, size, line, filename ) ); } #else char * xi_tree_realloc2( char *oldp, size_t size, char *parent ) { if ( oldp == NULL ) return ( ( char * ) xi_tree_malloc( size, parent ) ); else return ( ( char * ) xi_tree_realloc( oldp, size ) ); } #endif int xi_get_text_width( XinFont * font, char *s, int len, unsigned long attrib ) { char buf[4]; int pw_size; if ( len == -1 ) len = strlen( s ); if ( attrib & XI_ATR_PASSWORD ) { buf[0] = ( char ) xi_get_pref( XI_PREF_PASSWORD_CHAR ); buf[1] = '\0'; pw_size = XinFontTextWidthGet( font, buf, 1 ); return ( pw_size * len ); } else return ( XinFontTextWidthGet( font, s, len ) ); } static void xi_draw_mnemonic_line( XinWindow win, XinFont * font, char *buf, char mnemonic, int mnemonic_instance, int horizontal, int vertical ) { char *bufp; int left, right; if ( !mnemonic ) return; if ( mnemonic_instance == 0 ) mnemonic_instance = 1; for ( bufp = buf; *bufp != '\0'; ++bufp ) { if ( *bufp == mnemonic ) { --mnemonic_instance; if ( !mnemonic_instance ) { XinPen pen; XinDrawTools dt; XinPoint p1, p2; XinWindowDrawToolsGet( win, &dt ); left = XinFontTextWidthGet( font, buf, ( int ) ( bufp - buf ) ); right = XinFontTextWidthGet( font, buf, ( int ) ( bufp - buf + 1 ) ); pen = black_cpen; pen.fore_color = dt.text_fore_color; XinWindowPenSet( win, &pen ); XinWindowDrawModeSet( win, XinDrawModeCopy ); p1.h = horizontal + left; p1.v = vertical + 1; xi_move_to( win, p1 ); p2.h = horizontal + right; p2.v = p1.v; xi_draw_line( win, p2 ); return; } } } } void xi_draw_clipped_text( XinWindow win, XinFont * font, char *s, XinRect * bound_rctp, XinRect * clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen, int rule_and_space, int str_len, char mnemonic, short mnemonic_instance, int *bline ) { int ascent, descent, leading, wid; char *buf; int baseline; XinRect tmp_rct; if ( !( attrib & XI_ATR_VISIBLE ) ) return; XinWindowFontMap( win, font ); XinFontMetricsGet( font, &leading, &ascent, &descent ); tmp_rct = *clip_rctp; tmp_rct.bottom = tmp_rct.bottom - BORDER_WIDTH; xi_set_clip( win, &tmp_rct ); NOREF( set_the_cpen ); /* TODO ????? if (set_the_cpen) XinWindowPenSet(win, &black_cpen); */ buf = xi_get_text_string( s, attrib ); #if XIWS == XIWS_WM NOREF( rule_and_space ); baseline = bound_rctp->top + 8; #else if ( attrib & XI_ATR_VCENTER ) baseline = bound_rctp->top + leading + ascent + rule_and_space + ( bound_rctp->bottom - bound_rctp->top - leading - ascent - descent ) / 2 - 1; else baseline = bound_rctp->top + leading + ascent + rule_and_space - 1; #endif if ( bline ) *bline = baseline; if ( attrib & XI_ATR_RJUST ) { wid = XinFontTextWidthGet( font, buf, -1 ); xi_draw_text( win, font, bound_rctp->right - wid, baseline, buf, str_len ); xi_draw_mnemonic_line( win, font, buf, mnemonic, mnemonic_instance, bound_rctp->right - wid, baseline ); } else { if ( attrib & XI_ATR_HCENTER ) { int x; wid = XinFontTextWidthGet( font, buf, str_len ); x = ( bound_rctp->left + bound_rctp->right ) / 2 - wid / 2; if ( x < bound_rctp->left ) x = bound_rctp->left; xi_draw_text( win, font, x, baseline, buf, str_len ); xi_draw_mnemonic_line( win, font, buf, mnemonic, mnemonic_instance, x, baseline ); } else { xi_draw_text( win, font, bound_rctp->left, baseline, buf, str_len ); xi_draw_mnemonic_line( win, font, buf, mnemonic, mnemonic_instance, bound_rctp->left, baseline ); } } xi_set_clip( win, ( XinRect * ) NULL ); } void xi_draw_text_attrib( XinWindow win, XinFont * font, int x, int y, char *s, int len, unsigned long attrib ) { char *buf; NOREF( len ); if ( !( attrib & XI_ATR_VISIBLE ) ) return; buf = xi_get_text_string( s, attrib ); xi_draw_text( win, font, x, y, buf, -1 ); } void xi_draw_3d_rect( XinWindow win, XinRect * rctp, BOOLEAN well, int height, XinColor color_light, XinColor color_ctrl, XinColor color_dark ) { XinRect rct; XinPoint pnt, pnt2; XinPen cpen; XinBrush cbrush; if ( !color_light ) { color_light = xi_get_pref( XI_PREF_COLOR_LIGHT ); color_ctrl = xi_get_pref( XI_PREF_COLOR_CTRL ); color_dark = xi_get_pref( XI_PREF_COLOR_DARK ); } cpen = black_cpen; rct = *rctp; XinWindowDrawModeSet( win, XinDrawModeCopy ); /* draw upper left lines */ cpen.fore_color = well ? color_dark : color_light; XinWindowPenSet( win, &cpen ); pnt.h = rct.left; pnt.v = rct.top; xi_move_to( win, pnt ); pnt2.h = rct.left; pnt2.v = rct.bottom - 1; xi_draw_line( win, pnt2 ); xi_move_to( win, pnt ); pnt2.h = rct.right - 1; pnt2.v = rct.top; xi_draw_line( win, pnt2 ); if ( height == 2 ) { pnt.h++; pnt.v++; xi_move_to( win, pnt ); pnt2.h = pnt.h; pnt2.v = rct.bottom - 2; xi_draw_line( win, pnt2 ); xi_move_to( win, pnt ); pnt2.h = rct.right - 2; pnt2.v = pnt.v; xi_draw_line( win, pnt2 ); } /* draw lower right lines */ cpen.fore_color = well ? color_light : color_dark; XinWindowPenSet( win, &cpen ); pnt.h = rct.left; pnt.v = rct.bottom - 1; xi_move_to( win, pnt ); pnt2.h = rct.right - 1; pnt2.v = pnt.v; xi_draw_line( win, pnt2 ); pnt.h = rct.right - 1; pnt.v = rct.top; xi_move_to( win, pnt ); pnt2.h = pnt.h; pnt2.v = rct.bottom; xi_draw_line( win, pnt2 ); if ( height == 2 ) { pnt.h = rct.left + 1; pnt.v = rct.bottom - 2;; xi_move_to( win, pnt ); pnt2.h = rct.right - 1; pnt2.v = pnt.v; xi_draw_line( win, pnt2 ); pnt.h = rct.right - 2; pnt.v = rct.top + 1; xi_move_to( win, pnt ); pnt2.h = pnt.h; pnt2.v = rct.bottom; xi_draw_line( win, pnt2 ); } XinWindowPenSet( win, &hollow_cpen ); cbrush = white_cbrush; cbrush.fore_color = color_ctrl; XinWindowBrushSet( win, &cbrush ); if ( height == 2 ) { rct.top += 2; rct.left += 2; rct.bottom -= 2; rct.right -= 2; } else { rct.top++; rct.left++; rct.bottom--; rct.right--; } xi_draw_rect( win, &rct ); } void xi_draw_3d_line( XinWindow win, XinPoint pnt1, XinPoint pnt2, BOOLEAN well ) { XinColor color_light, color_dark; XinPoint pnt1x, pnt2x; XinPen cpen; color_light = xi_get_pref( XI_PREF_COLOR_LIGHT ); color_dark = xi_get_pref( XI_PREF_COLOR_DARK ); cpen = black_cpen; XinWindowDrawModeSet( win, XinDrawModeCopy ); cpen.fore_color = well ? color_dark : color_light; XinWindowPenSet( win, &cpen ); xi_move_to( win, pnt1 ); xi_draw_line( win, pnt2 ); pnt1x = pnt1; pnt2x = pnt2; if ( pnt1x.v == pnt2x.v ) { pnt1x.v++; pnt2x.v++; } else { pnt1x.h++; pnt2x.h++; } cpen.fore_color = well ? color_light : color_dark; XinWindowPenSet( win, &cpen ); xi_move_to( win, pnt1x ); xi_draw_line( win, pnt2x ); } void xi_draw_thick_rect( XinWindow win, XinRect * rctp, int width ) { XinRect mrct; int i; mrct = *rctp; for ( i = 0; i < width; ++i ) { xi_draw_rect( win, &mrct ); mrct.top++; mrct.left++; mrct.bottom--; mrct.right--; } } void xi_draw_diamond( XinWindow win, XinRect * rctp, BOOLEAN well, BOOLEAN black, BOOLEAN fill, XinColor color ) { XinPoint pnt1, pnt2; int half_width, width; XinRect rct; XinColor color_light, color_ctrl, color_dark; XinPen cpen; rct = *rctp; width = ( rct.right - rct.left ) / 2; width = width * 2 + 1; half_width = width / 2 + 1; rct.right = rct.left + width; rct.bottom = rct.top + width; color_light = xi_get_pref( XI_PREF_COLOR_LIGHT ); color_ctrl = xi_get_pref( XI_PREF_COLOR_CTRL ); color_dark = xi_get_pref( XI_PREF_COLOR_DARK ); cpen = black_cpen; cpen.fore_color = well ? color_dark : color_light; if ( black ) cpen.fore_color = XI_COLOR_BLACK; if ( color ) cpen.fore_color = color; XinWindowPenSet( win, &cpen ); XinWindowDrawModeSet( win, XinDrawModeCopy ); /* upper left */ pnt1.h = rct.left; pnt1.v = rct.top + half_width; xi_move_to( win, pnt1 ); pnt2.h = rct.left + half_width; pnt2.v = rct.top; xi_draw_line( win, pnt2 ); /* lower left */ pnt1.h = rct.left; pnt1.v = rct.top + half_width - 1; xi_move_to( win, pnt1 ); pnt2.h = rct.left + half_width - 1; pnt2.v = rct.bottom - 1; xi_draw_line( win, pnt2 ); cpen.fore_color = well ? color_light : color_dark; if ( black ) cpen.fore_color = XI_COLOR_BLACK; if ( color ) cpen.fore_color = color; XinWindowPenSet( win, &cpen ); /* upper right */ pnt1.h = rct.left + half_width; pnt1.v = rct.top + 1; xi_move_to( win, pnt1 ); pnt2.h = rct.right; pnt2.v = rct.top + half_width; xi_draw_line( win, pnt2 ); /* lower right */ pnt1.h = rct.left + half_width - 1; pnt1.v = rct.bottom; xi_move_to( win, pnt1 ); pnt2.h = rct.right; pnt2.v = rct.top + half_width - 1; xi_draw_line( win, pnt2 ); if ( fill ) { int h, v1, v2, hwm1; XinPoint pnt1, pnt2; v1 = rct.top + half_width - 1; v2 = rct.top + half_width; cpen.fore_color = color_ctrl; XinWindowPenSet( win, &cpen ); hwm1 = rct.left + half_width - 1; for ( h = rct.left + 1; h <= rct.right - 2; ++h ) { pnt1.h = h; pnt1.v = v1; xi_move_to( win, pnt1 ); pnt2.h = h; pnt2.v = v2; xi_draw_line( win, pnt2 ); if ( h < hwm1 ) { v1--; v2++; } else { v1++; v2--; } } } } void xi_draw_3d_diamond( XinWindow win, XinRect * rctp, BOOLEAN well, BOOLEAN black, int height, XinColor color ) { XinRect rct; int i; rct = *rctp; for ( i = 0; i < height; ++i ) { xi_draw_diamond( win, &rct, well, black, ( BOOLEAN ) ( i == height - 1 ), color ); rct.top++; rct.left++; rct.bottom--; rct.right--; if ( rct.top > rct.bottom || rct.left > rct.right ) break; } } #ifdef NEED_MEMMOVE char * memmove( register char *d, register char *s, long n ) { char *dst = d; /* remove when MEDIUM goes away */ if ( d < s ) while ( n-- > 0 ) *d++ = *s++; else { d += ( int ) n - 1; s += ( int ) n - 1; while ( n-- > 0 ) *d-- = *s--; } return dst; } #endif #if XIWS != XIWS_WM void dbg_rct( char *tag, XinRect * rct ) { char buf[100]; sprintf( buf, "%s: top %d left %d bottom %d right %d", tag, rct->top, rct->left, rct->bottom, rct->right ); xi_dbg( buf ); } #endif void xi_set_cur_window( XinWindow win ) { cur_window = win; cur_itf = xi_get_itf( win ); if ( cur_itf ) { cur_delta_x = cur_itf->v.itf->delta_x; cur_delta_y = cur_itf->v.itf->delta_y; } else { cur_delta_x = 0; cur_delta_y = 0; } } void xi_dbg( char *buf ) { XinDebugPrintf( buf ); } void xi_even_fu( int *f ) { *f = ( *f * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2 ) / XI_FU_MULTIPLE; } void xi_even_fu_pnt( XinPoint * p ) { p->h = ( p->h * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2 ) / XI_FU_MULTIPLE; p->v = ( p->v * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2 ) / XI_FU_MULTIPLE; } int xi_get_fu_width( XI_OBJ * itf ) { if ( itf ) return itf->v.itf->fu_width; else return xi_get_fu_width_font( xi_get_system_font( ) ); } int xi_get_fu_height( XI_OBJ * itf ) { if ( itf ) return itf->v.itf->fu_height; else return xi_get_fu_height_font( xi_get_system_font( ) ); } int xi_get_fu_width_font( XinFont * font ) { int leading, ascent, descent, char_width; xi_get_font_metrics_font( font, &leading, &ascent, &descent, &char_width ); return char_width; } int xi_get_fu_height_font( XinFont * font ) { int leading, ascent, descent, char_width; int height; xi_get_font_metrics_font( font, &leading, &ascent, &descent, &char_width ); height = leading + ascent + descent + STX_VERT_FUDGE; return height; } void xi_fu_to_pu_font( XinFont * font, XinPoint * pnts, int nbr_pnts ) { int leading, ascent, descent, char_width; int height; xi_get_font_metrics_font( font, &leading, &ascent, &descent, &char_width ); height = leading + ascent + descent + STX_VERT_FUDGE; while ( nbr_pnts != 0 ) { pnts->v = ( short ) ( ( ( long ) pnts->v * ( long ) height ) / ( long ) XI_FU_MULTIPLE ); pnts->h = ( short ) ( ( ( long ) pnts->h * ( long ) char_width ) / ( long ) XI_FU_MULTIPLE ); pnts++; nbr_pnts--; } } BOOLEAN font_compare( XinFont * f1, XinFont * f2 ) { return XinFontCompare( f1, f2 ); } void xi_get_font_metrics_font( XinFont * font, int *leading, int *ascent, int *descent, int *char_width ) { FONT_INFO* fi; int i; XinWindow win; BOOLEAN close_win = FALSE; XinRect rct; for ( i = 0, fi = font_info; i < font_info_cnt; ++i, ++fi ) { if ( font_compare( fi->font, font ) ) { *leading = fi->leading; *ascent = fi->ascent; *descent = fi->descent; *char_width = fi->char_width; return; } } ++font_info_cnt; if ( font_info ) font_info = ( FONT_INFO * ) xi_tree_realloc( font_info, sizeof( FONT_INFO ) * font_info_cnt ); else font_info = ( FONT_INFO * ) xi_tree_malloc( sizeof( FONT_INFO ) * font_info_cnt, ( void * ) NULL ); fi = &font_info[font_info_cnt - 1]; XinFontCopy( &fi->font, font ); if ( !XinFontIsMapped( fi->font ) ) { rct.top = -200; rct.left = -200; rct.bottom = -100; rct.right = -100; { XinWindowDef Def; MEMCLEAR( Def ); Def.type = XinWindowTypeDocument; Def.border_style = XinBorderFixed; Def.p_rect = &rct; Def.title = ""; Def.vertical_scroll_bar = FALSE; Def.horizontal_scroll_bar = FALSE; Def.close_button = FALSE; Def.visible = FALSE; Def.enabled = FALSE; Def.parent = XinWindowTaskGet( ); win = XinWindowCreate( &Def ); } close_win = TRUE; XinWindowFontMap( win, font ); } { int tl, ta, td; XinFontMetricsGet( font, &tl, &ta, &td ); fi->leading = tl; fi->ascent = ta; fi->descent = td; } fi->char_width = XinFontTextWidthGet( font, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", -1 ) / 52; if ( close_win ) { XinFontUnmap( font ); /* RGM: Font unmap hack */ XinWindowDestroy( win ); } *leading = fi->leading; *ascent = fi->ascent; *descent = fi->descent; *char_width = fi->char_width; } /********************************************************************/ /* FUNCTIONS THAT NEED TRANSPOSING */ static void ppnt_to_vpnt( XinWindow win, XinPoint * pnt ) { XI_OBJ *itf; XI_ITF_DATA *itf_data; itf = xi_get_itf( win ); if ( itf ) { itf_data = itf->v.itf; pnt->h += itf_data->delta_x; pnt->v += itf_data->delta_y; } } static void vpnt_to_ppnt( XinWindow win, XinPoint * pnt ) { XI_OBJ *itf; XI_ITF_DATA *itf_data; itf = xi_get_itf( win ); if ( itf ) { itf_data = itf->v.itf; pnt->h -= itf_data->delta_x; pnt->v -= itf_data->delta_y; } } static void vrct_to_prct( XinWindow win, XinRect * rct ) { XI_OBJ *itf; XI_ITF_DATA *itf_data; itf = xi_get_itf( win ); if ( itf ) { itf_data = itf->v.itf; rct->left -= itf_data->delta_x; rct->right -= itf_data->delta_x; rct->top -= itf_data->delta_y; rct->bottom -= itf_data->delta_y; } } static void move_controls( XI_OBJ * xi_obj ) { XI_OBJ **objlist; int n; XinRect rct; switch ( xi_obj->type ) { case XIT_ITF: if ( !xi_obj->v.itf->half_baked ) XinWindowPaintForce( xi_obj->v.itf->xin_win ); break; #ifdef XI_USE_TX_SUPPORT case XIT_FIELD: if ( xi_get_pref( XI_PREF_USE_TX_SUPPORT ) ) xi_tx_edit_move( xi_obj ); break; #endif case XIT_LIST: { XI_LIST_DATA *list_data; XI_ITF_DATA *itf_data; itf_data = xi_obj->itf->v.itf; list_data = xi_obj->v.list; if ( list_data->sb_win ) { xi_get_sb_rect( xi_obj, &rct ); xi_offset_rect( &rct, -itf_data->delta_x, -itf_data->delta_y ); XinWindowRectSet( list_data->sb_win, &rct ); } if ( list_data->hsb_win ) { xi_get_hsb_rect( xi_obj, &rct ); xi_offset_rect( &rct, -itf_data->delta_x, -itf_data->delta_y ); XinWindowRectSet( list_data->hsb_win, &rct ); } break; } case XIT_BTN: { XinRect rct; XI_ITF_DATA *itf_data; XI_BTN_DATA *btn_data; btn_data = xi_obj->v.btn; if ( btn_data->btnctl ) { itf_data = xi_obj->itf->v.itf; rct = btn_data->rct; xi_offset_rect( &rct, -itf_data->delta_x, -itf_data->delta_y ); XinWindowRectSet( btn_data->btnctl, &rct ); } break; } } objlist = xi_get_member_list( xi_obj, &n ); for ( ; n > 0; n--, objlist++ ) move_controls( *objlist ); if ( xi_obj->type == XIT_ITF ) xi_set_clip( xi_obj->v.itf->xin_win, NULL ); } void xi_adjust_sb_vir_itf( XinWindow win, XI_OBJ * itf ) { XinRect rct; XI_ITF_DATA *itf_data; itf_data = itf->v.itf; XinWindowRectGet( win, &rct ); itf_data->win_xi_pnt.v = rct.bottom - rct.top; itf_data->win_xi_pnt.h = rct.right - rct.left; xi_pu_to_fu( itf, &itf_data->win_xi_pnt, 1 ); xi_even_fu_pnt( &itf_data->win_xi_pnt ); if ( itf_data->win_xi_pnt.h + itf_data->phys_xi_pnt.h > itf_data->max_xi_pnt.h || itf_data->win_xi_pnt.v + itf_data->phys_xi_pnt.v > itf_data->max_xi_pnt.v ) { XinPoint p; int old_delta_x, old_delta_y; if ( itf_data->win_xi_pnt.h + itf_data->phys_xi_pnt.h > itf_data->max_xi_pnt.h ) itf_data->phys_xi_pnt.h = itf_data->max_xi_pnt.h - itf_data->win_xi_pnt.h; if ( itf_data->phys_xi_pnt.h < 0 ) itf_data->phys_xi_pnt.h = 0; if ( itf_data->win_xi_pnt.v + itf_data->phys_xi_pnt.v > itf_data->max_xi_pnt.v ) itf_data->phys_xi_pnt.v = itf_data->max_xi_pnt.v - itf_data->win_xi_pnt.v; if ( itf_data->phys_xi_pnt.v < 0 ) itf_data->phys_xi_pnt.v = 0; p.h = itf_data->phys_xi_pnt.h; p.v = itf_data->phys_xi_pnt.v; xi_fu_to_pu( itf, &p, 1 ); cur_delta_x = p.h; cur_delta_y = p.v; old_delta_x = itf_data->delta_x; old_delta_y = itf_data->delta_y; itf_data->delta_x = cur_delta_x; itf_data->delta_y = cur_delta_y; xi_caret_suspend( win ); if ( old_delta_x != cur_delta_x || old_delta_y != cur_delta_y ) xi_invalidate_rect( win, NULL ); move_controls( itf ); xi_caret_restore( win ); } set_sb_positions( itf ); } BOOLEAN xi_eh( XinWindow win, XinEvent * ep ) { switch ( ep->type ) { case XinEventPaint: update_pending = FALSE; break; case XinEventCharacter: if ( update_pending && ( ep->v.character.ch == XI_KEY_UP || ep->v.character.ch == XI_KEY_DOWN ) ) return FALSE; break; case XinEventResize: { XI_OBJ *itf; XI_ITF_DATA *itf_data; XinRect rct; itf = xi_get_itf( win ); if ( !itf ) break; itf_data = itf->v.itf; if ( itf_data->size_font_to_win ) { XinRect old_win_rct; int bottom, right; XinFont *itf_font; XinWindowRectGet( win, &rct ); old_win_rct = itf->v.itf->original_win_rct; bottom = old_win_rct.bottom; right = old_win_rct.right; itf_font = itf_data->font; if ( itf_font ) { int point_size, point_size2; point_size = itf->v.itf->original_font_size; point_size = ( point_size * rct.bottom + bottom / 2 ) / bottom; point_size2 = itf->v.itf->original_font_size; point_size2 = ( point_size2 * rct.right + right / 2 ) / right; XinFontSizeSet( itf_font, point_size2 - 1 ); recalc_metrics( itf ); xi_invalidate_rect( xi_get_window( itf ), NULL ); } break; } if ( itf_data->virtual_itf ) xi_adjust_sb_vir_itf( win, itf ); break; } case XinEventMouseDown: case XinEventMouseUp: case XinEventMouseDouble: case XinEventMouseMove: ppnt_to_vpnt( win, &ep->v.mouse.where ); break; case XinEventHScroll: { XI_OBJ *itf; XI_ITF_DATA *itf_data; int delta_x, old, d; itf = xi_get_itf( win ); if ( !itf ) break; itf_data = itf->v.itf; if ( !itf_data->virtual_itf ) break; switch ( ep->v.scroll.action ) { case XinScrollBarActionLineUp: delta_x = -4 * XI_FU_MULTIPLE; break; case XinScrollBarActionLineDown: delta_x = 4 * XI_FU_MULTIPLE; break; case XinScrollBarActionPageUp: delta_x = -10 * XI_FU_MULTIPLE; break; case XinScrollBarActionPageDown: delta_x = 10 * XI_FU_MULTIPLE; break; case XinScrollBarActionThumb: { int oldp, newp; oldp = itf_data->phys_xi_pnt.h; newp = ( int ) ( ( long ) ep->v.scroll.position * ( ( long ) itf_data->max_xi_pnt.h - ( long ) itf_data->win_xi_pnt.h ) / 100L ); xi_even_fu( &newp ); delta_x = newp - oldp; break; } case XinScrollBarActionThumbTrack: delta_x = 0; break; } old = itf_data->phys_xi_pnt.h; itf_data->phys_xi_pnt.h += delta_x; itf_data->phys_xi_pnt.h = min( itf_data->phys_xi_pnt.h, itf_data->max_xi_pnt.h - itf_data->win_xi_pnt.h ); itf_data->phys_xi_pnt.h = max( itf_data->phys_xi_pnt.h, 0 ); d = itf_data->phys_xi_pnt.h - old; /* d is now the delta in form units */ if ( d ) { XinRect client_rct; XinPoint pnt; XinWindowPaintForce( win ); XinWindowRectGet( win, &client_rct ); pnt.h = itf_data->phys_xi_pnt.h; xi_fu_to_pu( itf, &pnt, 1 ); cur_delta_x = pnt.h; pnt.h = d; xi_fu_to_pu( itf, &pnt, 1 ); xi_caret_suspend( win ); do_vir_pan_event( itf, pnt.h, 0, TRUE ); itf_data->delta_x += pnt.h; XinWindowRectScroll( win, &client_rct, -pnt.h, 0 ); set_sb_positions( itf ); move_controls( itf ); do_vir_pan_event( itf, pnt.h, 0, FALSE ); xi_caret_restore( win ); } break; } case XinEventVScroll: { XI_OBJ *itf; XI_ITF_DATA *itf_data; int delta_y, old, d; itf = xi_get_itf( win ); if ( !itf ) break; itf_data = itf->v.itf; if ( !itf_data->virtual_itf ) break; switch ( ep->v.scroll.action ) { case XinScrollBarActionLineUp: delta_y = -XI_FU_MULTIPLE; break; case XinScrollBarActionLineDown: delta_y = XI_FU_MULTIPLE; break; case XinScrollBarActionPageUp: delta_y = -10 * XI_FU_MULTIPLE; break; case XinScrollBarActionPageDown: delta_y = 10 * XI_FU_MULTIPLE; break; case XinScrollBarActionThumb: { int oldp, newp; oldp = itf_data->phys_xi_pnt.v; newp = ( int ) ( ( long ) ep->v.scroll.position * ( ( long ) itf_data->max_xi_pnt.v - ( long ) itf_data->win_xi_pnt.v ) / 100L ); xi_even_fu( &newp ); delta_y = newp - oldp; break; } case XinScrollBarActionThumbTrack: delta_y = 0; break; } old = itf_data->phys_xi_pnt.v; itf_data->phys_xi_pnt.v += delta_y; itf_data->phys_xi_pnt.v = min( itf_data->phys_xi_pnt.v, itf_data->max_xi_pnt.v - itf_data->win_xi_pnt.v ); itf_data->phys_xi_pnt.v = max( itf_data->phys_xi_pnt.v, 0 ); d = itf_data->phys_xi_pnt.v - old; if ( d ) { XinRect client_rct; XinPoint pnt; XinWindowPaintForce( win ); XinWindowRectGet( win, &client_rct ); pnt.v = itf_data->phys_xi_pnt.v; xi_fu_to_pu( itf, &pnt, 1 ); cur_delta_y = pnt.v; pnt.v = d; xi_fu_to_pu( itf, &pnt, 1 ); xi_caret_suspend( win ); do_vir_pan_event( itf, 0, pnt.v, TRUE ); itf_data->delta_y += pnt.v; XinWindowRectScroll( win, &client_rct, 0, -pnt.v ); set_sb_positions( itf ); move_controls( itf ); do_vir_pan_event( itf, 0, pnt.v, FALSE ); xi_caret_restore( win ); } break; } } return TRUE; } void xi_vir_pan( XI_OBJ * itf, int delta_x, int delta_y ) { XinRect cr; XinWindow win; XI_ITF_DATA *itf_data; XinPoint pf, p; int old; pf.h = delta_x; pf.v = delta_y; itf_data = itf->v.itf; win = xi_get_window( itf ); XinWindowRectGet( win, &cr ); XinWindowPaintForce( win ); /* clip y delta to appropriate bounding */ old = itf_data->phys_xi_pnt.v; itf_data->phys_xi_pnt.v += pf.v; itf_data->phys_xi_pnt.v = min( itf_data->phys_xi_pnt.v, itf_data->max_xi_pnt.v - itf_data->win_xi_pnt.v ); if ( itf_data->phys_xi_pnt.v < 0 ) itf_data->phys_xi_pnt.v = 0; pf.v = itf_data->phys_xi_pnt.v - old; /* clip x delta to appropriate bounding */ old = itf_data->phys_xi_pnt.h; itf_data->phys_xi_pnt.h += pf.h; itf_data->phys_xi_pnt.h = min( itf_data->phys_xi_pnt.h, itf_data->max_xi_pnt.h - itf_data->win_xi_pnt.h ); if ( itf_data->phys_xi_pnt.h < 0 ) itf_data->phys_xi_pnt.h = 0; pf.h = itf_data->phys_xi_pnt.h - old; /* convert to pixel coordinates */ p = pf; xi_fu_to_pu( itf, &p, 1 ); /* add to current delta x and y */ cur_delta_y += p.v; cur_delta_x += p.h; /* do the virtual pan */ xi_caret_suspend( win ); do_vir_pan_event( itf, p.h, p.v, TRUE ); itf_data->delta_y = cur_delta_y; itf_data->delta_x = cur_delta_x; XinWindowRectScroll( win, &cr, -p.h, -p.v ); set_sb_positions( itf ); move_controls( itf ); do_vir_pan_event( itf, p.h, p.v, FALSE ); xi_caret_restore( win ); } void xi_make_obj_visible( XI_OBJ * xi_obj ) { XinRect or, cr, cr2; XI_OBJ *itf; XI_ITF_DATA *itf_data; XinWindow win; int dt, db, dl, dr, dh, dv; XinPoint p, pf, pp; int pref_h, pref_v; switch ( xi_obj->type ) { case XIT_ITF: case XIT_GROUP: case XIT_FORM: case XIT_LIST: case XIT_COLUMN: case XIT_CONTAINER: return; } pref_h = ( int ) xi_get_pref( XI_PREF_VIR_SP_H ); pref_v = ( int ) xi_get_pref( XI_PREF_VIR_SP_V ); itf = xi_obj->itf; itf_data = itf->v.itf; win = xi_get_window( itf ); xi_set_cur_window( win ); XinWindowRectGet( win, &cr ); pp.v = itf_data->max_xi_pnt.v; pp.h = itf_data->max_xi_pnt.h; xi_fu_to_pu( xi_obj->itf, &pp, 1 ); xi_get_rect( xi_obj, &or ); or.top -= pref_v; if ( or.top < 0 ) or.top = 0; or.bottom += pref_v; if ( or.bottom > pp.v ) or.bottom = pp.v; or.left -= pref_h; if ( or.left < 0 ) or.left = 0; or.right += pref_h; if ( or.right > pp.h ) or.right = pp.h; cr2 = cr; cr2.left += itf_data->delta_x; cr2.right += itf_data->delta_x; cr2.top += itf_data->delta_y; cr2.bottom += itf_data->delta_y; dr = or.right - cr2.right; /* positive if not ok */ dr = max( 0, dr ); dr = min( dr, pp.h ); db = or.bottom - cr2.bottom; /* positive if not ok */ db = max( 0, db ); db = min( db, pp.v ); dl = cr2.left - or.left; /* positive if not ok */ dl = max( 0, dl ); dt = cr2.top - or.top; /* positive if not ok */ dt = max( 0, dt ); if ( dl && dr ) dr = 0; if ( db && dt ) db = 0; if ( dl ) dh = -dl; else dh = dr; if ( dt ) dv = -dt; else dv = db; p.h = dh; p.v = dv; xi_pu_to_fu( xi_obj->itf, &p, 1 ); xi_even_fu_pnt( &p ); pf = p; xi_fu_to_pu( xi_obj->itf, &p, 1 ); if ( p.h || p.v ) { XinWindowPaintForce( win ); itf_data->phys_xi_pnt.v += pf.v; itf_data->phys_xi_pnt.h += pf.h; cur_delta_y += p.v; cur_delta_x += p.h; xi_caret_suspend( win ); do_vir_pan_event( itf, p.h, p.v, TRUE ); itf_data->delta_y = cur_delta_y; itf_data->delta_x = cur_delta_x; XinWindowRectScroll( win, &cr, -p.h, -p.v ); set_sb_positions( itf ); move_controls( itf ); do_vir_pan_event( itf, p.h, p.v, FALSE ); xi_caret_restore( win ); } } void xi_scroll_rect( XinWindow win, XinRect * rctp, int dh, int dv ) { XinRect r; xi_set_cur_window( win ); r = *rctp; vrct_to_prct( win, &r ); if (dh == 0 && dv == 0) update_pending = FALSE; else update_pending = TRUE; XinWindowRectScroll( win, &r, dh, dv ); } static void xi_caret_suspend( XinWindow win ) { XI_ITF_DATA *itf_data; itf_data = xi_get_itf( win )->v.itf; if ( itf_data->caret_is_on ) { XinWindowCaretOff( win ); } } static void xi_caret_restore( XinWindow win ) { XI_ITF_DATA *itf_data; XinPoint p; XinDrawTools dt; itf_data = xi_get_itf( win )->v.itf; if ( itf_data->caret_is_on ) { int x, y; XinRect local_clip; p.h = itf_data->caret_x; p.v = itf_data->caret_y; vpnt_to_ppnt( win, &p ); x = p.h; y = p.v; local_clip = itf_data->caret_clip; vrct_to_prct( win, &local_clip ); XinWindowDrawToolsGet( win, &dt ); XinWindowCaretOn( win, x, y, itf_data->caret_height, dt.text_back_color, &local_clip ); } } void xi_invalidate_rect( XinWindow win, XinRect * rct ) { XinRect r, cr, dr; if ( rct != NULL && ( rct->top >= rct->bottom || rct->left >= rct->right ) ) return; if ( !rct ) { XinWindowRectInvalidate( win, NULL ); return; } r = *rct; vrct_to_prct( win, &r ); XinWindowRectGet( win, &cr ); if ( xi_rect_intersect( &dr, &r, &cr ) ) { update_pending = TRUE; XinWindowRectInvalidate( win, &r ); } } BOOLEAN xi_XinWindowPaintNeeds( XinWindow win, XinRect * rct ) { XinRect r; r = *rct; vrct_to_prct( win, &r ); return XinWindowPaintNeeds( win, &r ); } void xi_draw_icon( XinWindow win, int x, int y, int rid, XinColor fore_color, XinColor back_color ) { if ( rid ) { XinPoint p; xi_set_cur_window( win ); p.h = x; p.v = y; vpnt_to_ppnt( win, &p ); XinWindowIconDraw( win, p.h, p.v, rid, fore_color, back_color ); } } #if XIWS == XIWS_WM static void adjust_point( short *p ) { *p = ( ( *p + 4 ) / 8 ) * 8; } #endif void xi_draw_rect( XinWindow win, XinRect * rctp ) { if ( rctp->top >= rctp->bottom || rctp->left >= rctp->right ) return; { XinRect r; #if XIWS == XIWS_WM XinDrawTools ct; r = *rctp; adjust_point( &r.top ); adjust_point( &r.left ); adjust_point( &r.bottom ); adjust_point( &r.right ); xi_set_cur_window( win ); vrct_to_prct( win, &r ); XinWindowDrawToolsGet( win, &ct ); if ( ct.mode == XinDrawModeXor && !xi_is_rect_empty( &r ) ) ct.brush.color = XI_COLOR_BLACK; if ( ct.brush.pat == XinPatternHollow ) ct.brush.color = ct.back_color; XinWindowDrawToolsSet( win, &ct ); XinWindowRectDraw( win, &r ); #else r = *rctp; xi_set_cur_window( win ); vrct_to_prct( win, &r ); XinWindowRectDraw( win, &r ); #endif } } void xi_move_to( XinWindow win, XinPoint pnt ) { xi_set_cur_window( win ); vpnt_to_ppnt( win, &pnt ); XinWindowLineMoveTo( win, &pnt ); } void xi_draw_line( XinWindow win, XinPoint pnt ) { xi_set_cur_window( win ); vpnt_to_ppnt( win, &pnt ); XinWindowLineDraw( win, &pnt ); } static BOOLEAN xi_is_rect_empty( XinRect * r ) { BOOLEAN h_empty = ( r->left >= r->right ); BOOLEAN v_empty = ( r->top >= r->bottom ); return h_empty || v_empty; } BOOLEAN xi_rect_intersect( XinRect * rctp, XinRect * rctp1, XinRect * rctp2 ) { XinRect r, r2, *rpnt; if ( rctp == NULL ) rpnt = &r; else rpnt = rctp; rpnt->left = max( rctp1->left, rctp2->left ); rpnt->top = max( rctp1->top, rctp2->top ); rpnt->right = min( rctp1->right, rctp2->right ); rpnt->bottom = min( rctp1->bottom, rctp2->bottom ); r2 = *rpnt; return !xi_is_rect_empty( &r2 ); } /* Functions moved from XI.C because MPW cannot have too much code in one module. */ void xi_menu_enable( XI_OBJ * itf, int tag, BOOLEAN enable ) { XI_OBJ *xi_obj; XinWindow win; win = xi_get_window( itf ); XinWindowMenuItemEnable( win, ( short ) tag, enable ); xi_obj = xi_get_obj( itf, tag ); if ( xi_obj != NULL && xi_obj->type == XIT_BTN ) if ( enable ) xi_set_attrib( xi_obj, xi_get_attrib( xi_obj ) | XI_ATR_ENABLED ); else xi_set_attrib( xi_obj, xi_get_attrib( xi_obj ) & ~XI_ATR_ENABLED ); } void xi_set_bitmap( XI_OBJ* xi_obj, XI_BITMAP* bitmap ) { switch ( xi_obj->type ) { case XIT_CELL: if ( !xi_obj->v.cell.is_vert_scrolled ) lm_set_bitmap( xi_obj->parent->v.list->lm, bitmap, xi_obj->v.cell.row, xi_obj->v.cell.column ); break; case XIT_BTN: { XI_BTN_DATA *bd; XI_BITMAP* new_bitmap; bd = xi_obj->v.btn; new_bitmap = xi_bitmap_copy( bitmap ); xi_bitmap_destroy( bd->up_bitmap ); bd->up_bitmap = new_bitmap; xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &bd->rct ); break; } case XIT_COLUMN: lm_set_column_bitmap( xi_obj->parent->v.list->lm, bitmap, xi_obj->cid ); break; default: XinError( 20088, XinSeverityFatal, 0L ); break; } } void xi_set_down_bitmap( XI_OBJ * xi_obj, XI_BITMAP * bitmap ) { switch ( xi_obj->type ) { case XIT_BTN: { XI_BTN_DATA *bd; XI_BITMAP* new_bitmap; bd = xi_obj->v.btn; new_bitmap = xi_bitmap_copy( bitmap ); xi_bitmap_destroy( bd->down_bitmap ); bd->down_bitmap = new_bitmap; xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &bd->rct ); break; } default: XinError( 20088, XinSeverityFatal, 0L ); break; } } void xi_set_icon( XI_OBJ * xi_obj, int icon_rid, int down_icon_rid ) { switch ( xi_obj->type ) { case XIT_CELL: if ( !xi_obj->v.cell.is_vert_scrolled ) lm_set_icon( xi_obj->parent->v.list->lm, icon_rid, xi_obj->v.cell.row, xi_obj->v.cell.column ); break; case XIT_BTN: { XI_BTN_DATA *bd; bd = xi_obj->v.btn; bd->up_icon_rid = icon_rid; bd->down_icon_rid = down_icon_rid; xi_invalidate_rect( xi_obj->itf->v.itf->xin_win, &bd->rct ); break; } case XIT_COLUMN: { lm_set_column_icon( xi_obj->parent->v.list->lm, icon_rid, xi_obj->cid ); break; } default: XinError( 20088, XinSeverityFatal, 0L ); break; } } XinRect * xi_get_xi_rct( XI_OBJ * xi_obj, XinRect * xi_rct ) { int fu_width, fu_height; fu_width = xi_get_fu_width( xi_obj ); fu_height = xi_get_fu_height( xi_obj ); switch ( xi_obj->type ) { case XIT_ITF: { XinRect r; XinWindowRectGet( xi_get_window( xi_obj ), &r ); xi_rct->top = 0; xi_rct->left = 0; xi_rct->bottom = ( r.bottom / fu_height ) * XI_FU_MULTIPLE; xi_rct->right = ( r.right / fu_width ) * XI_FU_MULTIPLE; return xi_rct; } default: return NULL; } } static void recalc_metrics( XI_OBJ * xi_obj ) { int i; switch ( xi_obj->type ) { case XIT_ITF: { XI_ITF_DATA *itf_data; itf_data = xi_obj->v.itf; /* recalculate fu_width and fu_height */ itf_data->fu_height = xi_get_fu_height_font( itf_data->font ); itf_data->fu_width = xi_get_fu_width_font( itf_data->font ); break; } case XIT_TEXT: { XI_TEXT_DATA *text_data; text_data = xi_obj->v.text; text_data->rct = text_data->xi_rct; xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & text_data->rct, 2 ); break; } case XIT_RECT: { XI_RECT_DATA *rect_data; rect_data = xi_obj->v.rect; rect_data->rct = rect_data->xi_rct; xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & rect_data->rct, 2 ); break; } case XIT_LINE: { XI_LINE_DATA *line_data; line_data = xi_obj->v.line; line_data->pnt1 = line_data->xi_pnt1; line_data->pnt2 = line_data->xi_pnt2; xi_fu_to_pu( xi_obj->itf, &line_data->pnt1, 1 ); xi_fu_to_pu( xi_obj->itf, &line_data->pnt2, 1 ); break; } case XIT_LIST: lm_recalc_metrics( xi_obj->v.list->lm ); /* TODO recalc sbb_rct, sb_rct, hsb_rct */ break; case XIT_COLUMN: break; case XIT_FIELD: { XI_FIELD_DATA *field_data; int btn_dim_x, btn_dim_x2, fu_width, fu_height, edit_height, btn_space; XinWindow itf_win; STX_DATA *stxp; int leading, ascent, descent, font_height; field_data = xi_obj->v.field; stxp = ( STX_DATA * ) field_data->stx; if ( !field_data->font_set ) stxp->font = xi_obj->itf->v.itf->font; itf_win = xi_get_window( xi_obj->itf ); fu_width = xi_get_fu_width( xi_obj->itf ); fu_height = xi_get_fu_height( xi_obj->itf ); XinWindowFontMap( itf_win, stxp->font ); XinFontMetricsGet( stxp->font, &leading, &ascent, &descent ); font_height = ascent + leading + descent; edit_height = font_height + ( 2 * EDIT_BORDER_WIDTH_Y ) + ( 2 * EDIT_BORDER_SPACE_Y ); if ( field_data->xi_rct.top || field_data->xi_rct.left || field_data->xi_rct.bottom || field_data->xi_rct.right ) { stxp->rct = field_data->xi_rct; if ( ( stxp->rct.bottom - stxp->rct.top ) <= XI_FU_MULTIPLE ) { xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & stxp->rct, 2 ); stxp->rct.bottom = stxp->rct.top + edit_height; } else { xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & stxp->rct, 2 ); stxp->rct.bottom -= BORDER_SPACE_Y; /* TODO move text edit object */ } } else { XinPoint p; XinRect rct; p = field_data->xi_pnt; xi_fu_to_pu( xi_obj->itf, &p, 1 ); rct.left = p.h; rct.top = p.v; rct.right = p.h + ( field_data->field_width / XI_FU_MULTIPLE ) * fu_width + 2 * BORDER_WIDTH_X + 2 * BORDER_SPACE_X; rct.bottom = p.v + edit_height; stxp->rct = rct; } btn_dim_x = ( XI_FU_MULTIPLE * fu_height ) / fu_width; /* btn_dim_x is actual width of button */ #if XIWS != XIWS_WM /* make buttons 70% wide as high */ btn_dim_x = ( int ) ( ( long ) btn_dim_x * 83L / 100L ); #endif btn_space = btn_dim_x / 6; /* btn_dim_x2 is the button width + space, rounded up to the next even * form unit */ btn_dim_x2 = btn_dim_x + btn_space; btn_dim_x2 = ( ( btn_dim_x2 + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; if ( !( field_data->xi_rct.top || field_data->xi_rct.bottom || field_data->xi_rct.left || field_data->xi_rct.right ) ) { if ( field_data->button ) { int leading, ascent, descent, font_height; XinWindowFontMap( itf_win, stxp->font ); XinFontMetricsGet( stxp->font, &leading, &ascent, &descent ); font_height = ascent + leading + descent; edit_height = font_height + ( 2 * EDIT_BORDER_WIDTH_Y ) + ( 2 * EDIT_BORDER_SPACE_Y ); field_data->btn_rct.top = field_data->xi_pnt.v; if ( field_data->button_on_left ) { field_data->btn_rct.left = field_data->xi_pnt.h; field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; } else { #if XIWS == XIWS_WM BOOLEAN b; STX_DATA *stxp; stxp = ( STX_DATA * ) field_data->stx; b = ( BOOLEAN ) ( stxp->attrib & XI_ATR_BORDER ); field_data->btn_rct.left = stxp->rct.left + field_data->field_width + ( b ? 24 : 8 ); field_data->btn_rct.right = field_data->btn_rct.left + 8; #endif #if XIWS != XIWS_WM field_data->btn_rct.right = field_data->xi_pnt.h + field_data->field_width + btn_dim_x2; field_data->btn_rct.right = ( ( field_data->btn_rct.right + XI_FU_MULTIPLE ) / XI_FU_MULTIPLE ) * XI_FU_MULTIPLE; field_data->btn_rct.left = field_data->btn_rct.right - btn_dim_x; #endif } } } else { if ( field_data->button ) { field_data->btn_rct = field_data->xi_rct; if ( field_data->button_on_left ) { field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x2; } else { field_data->btn_rct.left = field_data->btn_rct.right; field_data->btn_rct.right += btn_dim_x2; } } } xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & field_data->btn_rct, 2 ); field_data->btn_rct.bottom = field_data->btn_rct.top + edit_height; if ( field_data->xi_pnt.h || field_data->xi_pnt.v ) { field_data->rct.top = field_data->xi_pnt.v; field_data->rct.left = field_data->xi_pnt.h; field_data->rct.right = field_data->rct.left + field_data->field_width; field_data->rct.bottom = field_data->rct.top + XI_FU_MULTIPLE; } else field_data->rct = field_data->xi_rct; xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & field_data->rct, 2 ); break; } case XIT_BTN: { XI_BTN_DATA *btn_data; if ( xi_obj->parent->type != XIT_CONTAINER ) { btn_data = xi_obj->v.btn; btn_data->rct = btn_data->xi_rct; xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & btn_data->rct, 2 ); } break; } case XIT_CONTAINER: { XI_CONTAINER_DATA *container_data; XinPoint p; int i, max_len, len; XI_OBJ *child; XI_BTN_TYPE btn_type; container_data = xi_obj->v.container; container_data->rct = container_data->xi_rct; xi_fu_to_pu( xi_obj->itf, ( XinPoint * ) & container_data->rct, 2 ); p.v = container_data->btn_height; p.h = container_data->btn_width; xi_fu_to_pu( xi_obj->itf, &p, 1 ); container_data->pix_height = p.v; container_data->pix_width = p.h; max_len = 0; for ( i = 0; i < xi_obj->nbr_children; ++i ) { child = xi_obj->children[i]; if ( ( len = ( int ) strlen( child->v.btn->text ) ) > max_len ) max_len = len; } btn_type = xi_obj->children[0]->v.btn->type; xi_container_rect_calc( xi_obj, max_len, btn_type ); for ( i = 0; i < xi_obj->nbr_children; ++i ) xi_button_rect_calc( xi_obj->children[i], i ); break; } } for ( i = 0; i < xi_obj->nbr_children; ++i ) recalc_metrics( xi_obj->children[i] ); } void xi_set_obj_font( XI_OBJ * xi_obj, XinFont * font ) { switch ( xi_obj->type ) { case XIT_ITF: { XI_ITF_DATA *itf_data; itf_data = xi_obj->v.itf; if ( itf_data->font ) XinFontDestroy( itf_data->font ); if ( font ) XinFontCopy( &itf_data->font, font ); else itf_data->font = NULL; recalc_metrics( xi_obj ); xi_invalidate_rect( xi_get_window( xi_obj ), NULL ); break; } case XIT_TEXT: { XinRect rct; if ( xi_obj->v.text->font != NULL ) XinFontDestroy( xi_obj->v.text->font ); XinFontCopy( &xi_obj->v.text->font, font ); xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); break; } case XIT_FIELD: { XinRect rct; stx_set_font( xi_obj->v.field->stx, font ); xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); break; } case XIT_COLUMN: { XI_OBJ *list; list = xi_obj->parent; lm_set_font( list->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), 0, font ); break; } case XIT_CELL: if ( !xi_obj->v.cell.is_vert_scrolled ) { XI_OBJ *list; XinRect rct; list = xi_obj->parent; lm_set_font( list->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column, font ); xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); } break; } } void xi_set_obj_font_id( XI_OBJ * xi_obj, void *font_id ) { #ifdef XI_USE_XVT XinFont *font = XinFontXvtConvert( font_id ); xi_set_obj_font( xi_obj, font ); XinFontDestroy( font ); #endif } XI_CELL_SPEC * xi_get_cell_selection( XI_OBJ * list, int *nbr_cellsp ) { int r, c, nbr_rows, nbr_columns, nbr_cells, cnt; XI_OBJ cell_obj, row_obj; XI_LIST_DATA *list_data; XI_OBJ **members; int nbr_members; members = xi_get_member_list( list, &nbr_members ); xi_get_list_info( list, &nbr_rows ); nbr_columns = list->nbr_children; nbr_cells = 0; for ( r = 0; r < nbr_rows; ++r ) for ( c = 0; c < nbr_columns; ++c ) { XI_MAKE_CELL( &cell_obj, list, ( unsigned char ) r, ( unsigned char ) c ); XI_MAKE_ROW( &row_obj, list, ( unsigned char ) r ); if ( ( xi_get_attrib( &cell_obj ) & XI_ATR_SELECTED ) || ( xi_get_attrib( members[c] ) & XI_ATR_SELECTED ) || ( xi_get_attrib( &row_obj ) & XI_ATR_SELECTED ) ) ++nbr_cells; } *nbr_cellsp = nbr_cells; list_data = list->v.list; if ( list_data->cell_spec ) list_data->cell_spec = ( XI_CELL_SPEC * ) xi_tree_realloc( list_data->cell_spec, ( size_t ) nbr_cells * sizeof( XI_CELL_SPEC ) ); else list_data->cell_spec = ( XI_CELL_SPEC * ) xi_tree_malloc( ( size_t ) nbr_cells * sizeof( XI_CELL_SPEC ), list_data ); cnt = 0; for ( r = 0; r < nbr_rows; ++r ) for ( c = 0; c < nbr_columns; ++c ) { XI_MAKE_CELL( &cell_obj, list, ( unsigned char ) r, ( unsigned char ) c ); XI_MAKE_ROW( &row_obj, list, ( unsigned char ) r ); if ( ( xi_get_attrib( &cell_obj ) & XI_ATR_SELECTED ) || ( xi_get_attrib( members[c] ) & XI_ATR_SELECTED ) || ( xi_get_attrib( &row_obj ) & XI_ATR_SELECTED ) ) { list_data->cell_spec[cnt].row = r; list_data->cell_spec[cnt].column = c; ++cnt; } } return list_data->cell_spec; } BOOLEAN xi_is_checked( XI_OBJ * xi_obj ) { BOOLEAN retval = FALSE; if ( xi_obj->type == XIT_BTN ) retval = xi_obj->v.btn->checked; return retval; } void xi_check( XI_OBJ * xi_obj, BOOLEAN check ) { XinWindow win; static BOOLEAN inside = FALSE; XI_BTN_DATA *btn; if ( check != 0 && check != 1 ) check = 1; if ( !xi_get_native_controls( xi_obj ) ) if ( xi_is_checked( xi_obj ) == check ) return; win = xi_obj->itf->v.itf->xin_win; btn = xi_obj->v.btn; xi_obj->v.btn->checked = check; if ( !xi_get_native_controls( xi_obj ) ) { switch ( btn->type ) { case XIBT_BUTTON: xi_invalidate_rect( win, &btn->rct ); break; case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: case XIBT_RADIOBTN: case XIBT_CHECKBOX: case XIBT_TABBTN: { BOOLEAN enabled, visible, focus; unsigned long attrib; 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 ); if ( btn->drawable || ( btn->type == XIBT_TABBTN && !check ) ) { XinRect temp = btn->rct; if ( btn->type == XIBT_TABBTN ) temp.bottom++; xi_invalidate_rect( win, &temp ); } else xi_draw_button( xi_obj, &btn->rct, enabled, visible, focus, btn->down, btn->dflt, btn->checked, TRUE, FALSE ); break; } } } #ifdef XI_USE_XVT else { switch ( btn->type ) { case XIBT_CHECKBOX: XinWindowCheckBox( btn->btnctl, check ); break; case XIBT_RADIOBTN: case XIBT_TABBTN: { XinWindow wins[MAX_RADIO_BUTTONS]; XI_BTN_TYPE type; XI_OBJ *parent; type = xi_obj->v.btn->type; parent = xi_obj->parent; if ( parent->type == XIT_CONTAINER && ( type == XIBT_RADIOBTN || type == XIBT_TABBTN ) ) { int i; if ( parent->nbr_children > MAX_RADIO_BUTTONS ) XinError( 20089, XinSeverityFatal, 0L ); for ( i = 0; i < parent->nbr_children; ++i ) wins[i] = parent->children[i]->v.btn->btnctl; XinWindowCheckRadioButton( btn->btnctl, wins, parent->nbr_children ); return; } if ( type == XIBT_RADIOBTN || type == XIBT_TABBTN ) { XinWindowCheckBox( btn->btnctl, check ); return; } break; } } } #endif if ( !inside && xi_obj->parent->type == XIT_CONTAINER && ( xi_obj->v.btn->type == XIBT_RADIOBTN || xi_obj->v.btn->type == XIBT_TABBTN || xi_obj->v.btn->type == XIBT_BUTTON_RADIOBTN ) ) { XI_OBJ **child; XI_OBJ *parent; int i; inside = TRUE; parent = xi_obj->parent; child = parent->children; for ( i = 0, child = parent->children; i < parent->nbr_children; ++i, ++child ) if ( *child != xi_obj ) if ( xi_is_checked( *child ) ) xi_check( *child, FALSE ); inside = FALSE; } } int xi_obj_to_idx( XI_OBJ * xi_obj ) { int column_idx; XI_OBJ **objp; int n; n = xi_obj->parent->nbr_children; objp = xi_obj->parent->children; for ( column_idx = 0; column_idx < n; objp++, ++column_idx ) { if ( ( *objp ) == xi_obj ) break; } return column_idx; } void xi_set_update_obj( XI_OBJ * xi_obj ) { /* Check to be sure that the object is visible */ if ( xi_obj != NULL ) { XinRect obj_r; XinRect client_r; XI_OBJ *itf; itf = xi_obj->itf; xi_get_rect( xi_obj, &obj_r ); XinWindowRectGet( itf->v.itf->xin_win, &client_r ); XinRectIntersect( &obj_r, &obj_r, &client_r ); if ( XinRectEmpty( &obj_r ) ) xi_obj = NULL; itf->v.itf->update_obj = xi_obj; } } int xi_get_visible_rows( XI_OBJ * xi_obj, int *first_vis, int *last_vis ) { return lm_get_visible_rows( xi_obj->v.list->lm, first_vis, last_vis ); } void xi_set_row_height( XI_OBJ * xi_obj, int height ) { XI_OBJ *list; list = xi_obj->parent; lm_set_row_height( list->v.list->lm, xi_obj->v.row, height, TRUE, 0, FALSE ); } #if 0 long xi_long_time( void ) { #if XVT_OS == XVT_OS_DOS struct time t; long l; gettime( &t ); l = t.ti_hund + t.ti_sec * 100 + t.ti_min * 6000 + t.ti_hour * 360000L; return l; #endif } #endif void xi_set_color( XI_OBJ * xi_obj, XI_COLOR_PART part, XinColor color ) { XinRect rct; BOOLEAN changed; changed = FALSE; switch ( xi_obj->type ) { case XIT_FIELD: { STX_DATA *stxp; stxp = ( STX_DATA * ) xi_obj->v.field->stx; switch ( part ) { case XIC_ENABLED: changed = ( stxp->enabled_color != color ); stxp->enabled_color = color; break; case XIC_BACK: changed = ( stxp->back_color != color ); stxp->back_color = color; break; case XIC_HILIGHT: changed = ( stxp->hilight_color != color ); stxp->hilight_color = color; break; case XIC_ACTIVE: changed = ( stxp->active_color != color ); stxp->active_color = color; break; case XIC_ACTIVE_BACK: changed = ( stxp->active_back_color != color ); stxp->active_back_color = color; break; case XIC_SHADOW: changed = ( stxp->shadow_color != color ); stxp->shadow_color = color; break; case XIC_DISABLED: changed = ( stxp->disabled_color != color ); stxp->disabled_color = color; break; case XIC_DISABLED_BACK: changed = ( stxp->disabled_back_color != color ); stxp->disabled_back_color = color; break; } if ( changed ) stx_update_colors( xi_obj->v.field->stx ); break; } case XIT_CELL: if ( !xi_obj->v.cell.is_vert_scrolled ) { LM_CELL_DATA *cell_data; XI_OBJ *list_obj; LM_DATA *lmp; int row = xi_obj->v.cell.row; int col = xi_obj->v.cell.column; list_obj = xi_obj->parent; lmp = ( LM_DATA * ) list_obj->v.list->lm; cell_data = &lmp->cell_data[row][col]; switch ( part ) { case XIC_ENABLED: changed = ( cell_data->color != color ); cell_data->color = color; break; case XIC_BACK: changed = ( cell_data->back_color != color ); cell_data->back_color = color; break; } } break; case XIT_ROW: if ( part == XIC_ENABLED ) lm_set_color( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0, FALSE, color, FALSE ); changed = TRUE; break; case XIT_TEXT: { XI_TEXT_DATA *xi_td; xi_td = ( XI_TEXT_DATA * ) xi_obj->v.text; switch ( part ) { case XIC_FORE: case XIC_ENABLED: changed = ( xi_td->fore_color != color ); xi_td->fore_color = color; break; case XIC_BACK: changed = ( xi_td->back_color != color ); xi_td->back_color = color; break; } break; } case XIT_LINE: { XI_LINE_DATA *xi_ld; xi_ld = ( XI_LINE_DATA * ) xi_obj->v.line; switch ( part ) { case XIC_FORE: case XIC_ENABLED: changed = ( xi_ld->fore_color != color ); xi_ld->fore_color = color; break; case XIC_BACK: changed = ( xi_ld->back_color != color ); xi_ld->back_color = color; break; } break; } case XIT_RECT: { XI_RECT_DATA *xi_rd; xi_rd = ( XI_RECT_DATA * ) xi_obj->v.rect; switch ( part ) { case XIC_FORE: case XIC_ENABLED: changed = ( xi_rd->fore_color != color ); xi_rd->fore_color = color; break; case XIC_BACK: changed = ( xi_rd->back_color != color ); xi_rd->back_color = color; break; case XIC_HILIGHT: changed = ( xi_rd->hilight_color != color ); xi_rd->hilight_color = color; break; case XIC_SHADOW: changed = ( xi_rd->shadow_color != color ); xi_rd->shadow_color = color; break; } break; } case XIT_ITF: { XI_ITF_DATA *xi_id; xi_id = ( XI_ITF_DATA * ) xi_obj->v.itf; if ( part == XIC_BACK ) changed = ( xi_id->back_color != color ); xi_id->back_color = color; break; } case XIT_LIST: { LM_DATA *lmp; lmp = ( LM_DATA * ) xi_obj->v.list->lm; switch ( part ) { case XIC_ENABLED: changed = ( lmp->enabled_color != color ); lmp->enabled_color = color; break; case XIC_BACK: changed = ( lmp->back_color != color ); lmp->back_color = color; break; case XIC_ACTIVE: changed = ( lmp->active_color != color ); lmp->active_color = color; break; case XIC_ACTIVE_BACK: changed = ( lmp->active_back_color != color ); lmp->active_back_color = color; break; case XIC_DISABLED: changed = ( lmp->disabled_color != color ); lmp->disabled_color = color; break; case XIC_DISABLED_BACK: changed = ( lmp->disabled_back_color != color ); lmp->disabled_back_color = color; break; case XIC_WHITE_SPACE: changed = ( lmp->white_space_color != color ); lmp->white_space_color = color; break; } break; } } if ( changed ) { if ( xi_obj->type == XIT_ITF ) { xi_get_rect( xi_obj, &rct ); xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); } else if ( ( xi_get_attrib( xi_obj ) & XI_ATR_VISIBLE ) != 0 ) { xi_get_rect( xi_obj, &rct ); /* Returned rectangle does not cause an update for a line. Adjust the * coordinates so it does. */ if ( xi_obj->type == XIT_LINE ) { rct.top = rct.top - 1; rct.bottom = rct.bottom + 1; } xi_invalidate_rect( xi_get_window( xi_obj->itf ), &rct ); } } } void xi_cell_request( XI_OBJ * xi_obj ) { switch ( xi_obj->type ) { case XIT_LIST: lm_cell_request( xi_obj->v.list->lm, LM_LIST, 0, 0 ); break; case XIT_COLUMN: lm_cell_request( xi_obj->parent->v.list->lm, LM_COLUMN, xi_obj_to_idx( xi_obj ), 0 ); break; case XIT_ROW: lm_cell_request( xi_obj->parent->v.list->lm, LM_ROW, xi_obj->v.row, 0 ); break; case XIT_CELL: if ( !xi_obj->v.cell.is_vert_scrolled ) lm_cell_request( xi_obj->parent->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column ); break; } } void xi_get_visible_columns( XI_OBJ * xi_obj, int *first_vis, int *last_vis ) { lm_get_visible_columns( xi_obj->v.list->lm, first_vis, last_vis ); } void xi_set_list_size( XI_OBJ * xi_obj, int height, int width ) { lm_set_list_size( xi_obj->v.list->lm, height, width ); } /*--------------------------------------------------------------------- function: xi_container_rect_calc cnt_obj: container object max_text_len: longest button text (only used for XI_STACK_HORIZONTAL) btn_type type of buttons in container process: Calculate the container size & button positioning parameters ---------------------------------------------------------------------*/ static void calc_horizontal_stack( XI_OBJ * itf, XI_CONTAINER_DATA * container, XI_BTN_TYPE btn_type, int max_text_len ) { int btn_width, max_width, horz_spacing, btn_height; long horz_form_unit; long vert_form_unit; BOOLEAN center; XinRect container_rect; container_rect = container->rct; btn_width = max_text_len; #if XIWS == XIWS_MAC btn_width *= ( XI_FU_MULTIPLE + 2 ); #elif XIWS == XIWS_WIN if ( xi_get_pref( XI_PREF_NATIVE_CTRLS ) ) btn_width *= ( XI_FU_MULTIPLE + 2 ); else btn_width *= XI_FU_MULTIPLE; #else btn_width *= XI_FU_MULTIPLE; #endif horz_form_unit = xi_get_fu_width( itf ); vert_form_unit = xi_get_fu_height( itf ); btn_width += ( int ) xi_get_pref( XI_PREF_BUTTON_PAD ); #if 0 /* old tabs */ if ( btn_type == XIBT_TABBTN ) btn_width += ( int ) xi_get_pref( XI_PREF_BUTTON_PAD ) / 2; #endif /* convert to pixels */ btn_width = ( int ) ( ( btn_width * horz_form_unit ) / XI_FU_MULTIPLE ); if ( container->packed || btn_type == XIBT_TABBTN ) horz_spacing = 0; else if ( ( horz_spacing = ( int ) xi_get_pref( XI_PREF_HORZ_PIXEL_SPACING ) ) == 0 ) horz_spacing = ( short ) ( ( xi_get_pref( XI_PREF_HORZ_SPACING ) * horz_form_unit ) / XI_FU_MULTIPLE ); /* If pix_width is larger, use it */ if ( container->pix_width > btn_width ) btn_width = container->pix_width; /* figure out if maximum width is too wide, and if so, truncate */ max_width = ( ( container_rect.right - container_rect.left ) - ( container->nbr_buttons - 1 ) * horz_spacing ) / container->nbr_buttons; if ( btn_width > max_width ) btn_width = max_width; switch ( btn_type ) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: if ( container->pix_height ) btn_height = container->pix_height; else btn_height = ( int ) ( ( xi_get_pref( XI_PREF_BUTTON_HEIGHT ) * vert_form_unit ) / XI_FU_MULTIPLE ); center = TRUE; break; case XIBT_TABBTN: btn_height = container_rect.bottom - container_rect.top; center = FALSE; break; case XIBT_CHECKBOX: case XIBT_RADIOBTN: btn_height = ( int ) vert_form_unit; center = TRUE; break; } if ( center == TRUE ) { container_rect.top += ( container_rect.bottom - container_rect.top - btn_height ) / 2; container_rect.bottom = container_rect.top + btn_height; } container->rct = container_rect; container->nbr_across = container->nbr_buttons; container->nbr_down = 1; container->pix_width = btn_width; container->pix_height = btn_height; container->step_across = btn_width + horz_spacing; container->step_down = 0; } static void calc_vertical_stack( XI_OBJ * itf, XI_CONTAINER_DATA * container, XI_BTN_TYPE btn_type ) { int btn_height, max_height, top_ofst, vert_spacing; XinRect container_rect; long vert_form_unit; vert_form_unit = xi_get_fu_height( itf ); container_rect = container->rct; switch ( 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 ) * vert_form_unit ) / XI_FU_MULTIPLE ); top_ofst = vert_spacing / 2; break; case XIBT_CHECKBOX: case XIBT_RADIOBTN: vert_spacing = 0; top_ofst = 0; break; } if ( container->pix_height ) btn_height = container->pix_height; else btn_height = ( int ) ( ( xi_get_pref( XI_PREF_BUTTON_HEIGHT ) * vert_form_unit ) / XI_FU_MULTIPLE ); max_height = ( container_rect.bottom - container_rect.top - top_ofst - ( ( container->nbr_buttons - 1 ) * vert_spacing ) ) / container->nbr_buttons; switch ( btn_type ) { case XIBT_CHECKBOX: case XIBT_RADIOBTN: btn_height = ( int ) vert_form_unit; break; } if ( btn_height > max_height ) btn_height = max_height; if ( btn_height < vert_form_unit ) XinError( 20014, XinSeverityFatal, 0L ); container_rect.top += top_ofst; container->rct = container_rect; container->nbr_across = 1; container->nbr_down = container->nbr_buttons; if ( container->pix_width == 0 ) container->pix_width = container->rct.right - container->rct.left; container->pix_height = btn_height; container->step_across = 0; container->step_down = btn_height + vert_spacing; } static void calc_grid( XI_OBJ * itf, XI_CONTAINER_DATA * container ) { int hz_pix_space, vt_pix_space, slack; XinPoint pnt; XinRect container_rect; container_rect = container->rct; if ( !( ( container->btn_width > 0 ) || ( container->btn_height > 0 ) ) ) XinError( 30208, XinSeverityFatal, 0L ); if ( container->pix_height == 0 || container->pix_width == 0 ) { pnt.v = container->btn_height; pnt.h = container->btn_width; xi_fu_to_pu( itf, &pnt, 1 ); if ( ( pnt.v == 0 ) || ( pnt.h == 0 ) ) { /* make it so that pnt.h and pnt.v are the same */ if ( pnt.v == 0 ) pnt.v = pnt.h; if ( pnt.h == 0 ) pnt.h = pnt.v; } container->pix_height = pnt.v; container->pix_width = pnt.h; } if ( container->pix_height > container_rect.bottom - container_rect.top ) XinError( 20032, XinSeverityFatal, 0L ); if ( container->pix_width > container_rect.right - container_rect.left ) XinError( 20033, XinSeverityFatal, 0L ); pnt.v = XI_FU_MULTIPLE; xi_fu_to_pu( itf, &pnt, 1 ); if ( ( container->pix_height < pnt.v ) ) XinError( 20034, XinSeverityFatal, 0L ); if ( container->packed == TRUE ) { /* note that if not native, the space is NEGATIVE */ vt_pix_space = ( ( BOOLEAN ) xi_get_pref( XI_PREF_NATIVE_CTRLS ) ) ? 0 : -( int ) xi_get_pref( XI_PREF_CONTAINER_GRID_WIDTH ); hz_pix_space = vt_pix_space; } else { pnt.v = ( int ) xi_get_pref( XI_PREF_VERT_SPACING ); pnt.h = ( int ) xi_get_pref( XI_PREF_HORZ_SPACING ); xi_fu_to_pu( itf, &pnt, 1 ); vt_pix_space = pnt.v; hz_pix_space = pnt.h; } container->step_down = container->pix_height + vt_pix_space; container->step_across = container->pix_width + hz_pix_space; if ( container->orientation == XI_GRID_HORIZONTAL ) { container->nbr_across = ( container_rect.right - container_rect.left + hz_pix_space ) / container->step_across; container->nbr_down = 1 + ( container->nbr_buttons - 1 ) / container->nbr_across; slack = ( container_rect.bottom - container_rect.top + vt_pix_space ) - ( container->nbr_down * container->step_down ); } else { container->nbr_down = ( container_rect.bottom - container_rect.top + vt_pix_space ) / container->step_down; container->nbr_across = 1 + ( container->nbr_buttons - 1 ) / container->nbr_down; slack = ( container_rect.right - container_rect.left + hz_pix_space ) - ( container->nbr_across * container->step_across ); } if ( slack < 0 ) XinError( 20035, XinSeverityFatal, 0L ); } void xi_container_rect_calc( XI_OBJ * cnt_obj, int max_text_len, XI_BTN_TYPE btn_type ) { XI_CONTAINER_DATA *container; container = cnt_obj->v.container; if ( container->rct.left == 0 && container->rct.top == 0 && container->rct.bottom == 0 && container->rct.right == 0 ) { XinRect rect; rect = container->xi_rct; xi_fu_to_pu( cnt_obj->itf, ( XinPoint * ) & rect, 2 ); container->rct = rect; } switch ( container->orientation ) { case XI_STACK_HORIZONTAL: calc_horizontal_stack( cnt_obj->itf, container, btn_type, max_text_len ); break; case XI_STACK_VERTICAL: calc_vertical_stack( cnt_obj->itf, container, btn_type ); break; case XI_GRID_HORIZONTAL: case XI_GRID_VERTICAL: calc_grid( cnt_obj->itf, container ); break; } } /*--------------------------------------------------------------------- function: xi_button_rect_calc btn_obj: Button object (with data structure complete except for rct) sequence: button sequence within parent (used for contained buttons only) process: Calculate the button rectangle size, either from the container information or the xi rectangle. ---------------------------------------------------------------------*/ void xi_button_rect_calc( XI_OBJ * btn_obj, int sequence ) { XinRect rct; BOOLEAN packed; /* button has no dflt or focus rects */ if ( btn_obj->parent->type == XIT_CONTAINER ) { int row, col; XI_CONTAINER_DATA *cdata; cdata = btn_obj->parent->v.container; switch ( cdata->orientation ) { case XI_STACK_HORIZONTAL: row = 0; col = sequence; packed = FALSE; break; case XI_STACK_VERTICAL: row = sequence; col = 0; packed = FALSE; break; case XI_GRID_HORIZONTAL: row = sequence / cdata->nbr_across; col = sequence - row * cdata->nbr_across; packed = cdata->packed; break; case XI_GRID_VERTICAL: col = sequence / cdata->nbr_down; row = sequence - col * cdata->nbr_down; packed = cdata->packed; break; } rct.top = cdata->rct.top + row * cdata->step_down; rct.left = cdata->rct.left + col * cdata->step_across; rct.bottom = rct.top + cdata->pix_height; rct.right = rct.left + cdata->pix_width; } else { rct = btn_obj->v.btn->rct; if ( rct.left == 0 && rct.top == 0 && rct.bottom == 0 && rct.right == 0 ) { rct = btn_obj->v.btn->xi_rct; xi_fu_to_pu( btn_obj->itf, ( XinPoint * ) & rct, 2 ); } if ( rct.top == rct.bottom ) { /* use default height */ rct.bottom = rct.top + ( int ) xi_get_pref( XI_PREF_BUTTON_HEIGHT ); } packed = FALSE; } btn_obj->v.btn->rct = rct; btn_obj->v.btn->packed = packed; } /*--------------------------------------------------------------------- function: xi_container_reorient cnt_obj: The EXISTING container object cnt_def: A revised definition of the container: XI_RCT xi_rct; new rectangle, if empty, use old XI_CONTAINER_ORIENTATION orientation; new value int tab_cid; NOT USED short btn_width; for grids, new value in form units short btn_height; for grids, new value in form units BOOLEAN packed; new value process: change the container position, orientation, etc. ---------------------------------------------------------------------*/ void xi_container_reorient( XI_OBJ * cnt_obj, XI_CONTAINER_DEF * cnt_def ) { int i, len, max_len; XI_CONTAINER_DATA *cdata; if ( cnt_obj->type != XIT_CONTAINER ) XinError( 20036, XinSeverityFatal, 0L ); cdata = cnt_obj->v.container; xi_invalidate_rect( xi_get_window( cnt_obj->itf ), &cdata->rct ); if ( ( cnt_def->xi_rct.bottom > cnt_def->xi_rct.top ) || ( cnt_def->xi_rct.right > cnt_def->xi_rct.left ) ) cdata->xi_rct = cnt_def->xi_rct; cdata->rct = cnt_def->pixel_rect; cdata->orientation = cnt_def->orientation; cdata->btn_height = cnt_def->btn_height; cdata->btn_width = cnt_def->btn_width; cdata->packed = cnt_def->packed; max_len = 0; for ( i = 0; i < cnt_obj->nbr_children; ++i ) { if ( ( len = ( int ) strlen( cnt_obj->children[i]->v.btn->text ) ) > max_len ) max_len = len; } xi_container_rect_calc( cnt_obj, max_len, cnt_obj->children[0]->v.btn->type ); for ( i = 0; i < cnt_obj->nbr_children; ++i ) { xi_button_rect_calc( cnt_obj->children[i], i ); } xi_invalidate_rect( xi_get_window( cnt_obj->itf ), &cdata->rct ); } /*--------------------------------------------------------------------------*/ /* xi_def_get_font */ /*--------------------------------------------------------------------------*/ XinFont * xi_def_get_font( XI_OBJ_DEF * obj_def ) { XinFont *font = NULL; if ( !obj_def ) { XinFontCopy( &font, xi_get_system_font( ) ); return font; } switch ( obj_def->type ) { case XIT_FIELD: if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { XinFontCopy( &font, obj_def->v.field->font ); } #ifdef XI_USE_XVT else { if ( obj_def->v.field->font_id != NULL ) font = XinFontXvtConvert( obj_def->v.field->font_id ); } #endif break; case XIT_TEXT: if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { XinFontCopy( &font, obj_def->v.text->font ); } #ifdef XI_USE_XVT else { if ( obj_def->v.text->font_id != NULL ) font = XinFontXvtConvert( obj_def->v.text->font_id ); } #endif break; case XIT_LIST: if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { XinFontCopy( &font, obj_def->v.list->font ); } #ifdef XI_USE_XVT else { if ( obj_def->v.list->font_id != NULL ) font = XinFontXvtConvert( obj_def->v.list->font_id ); } #endif break; case XIT_ITF: if ( ( BOOLEAN ) xi_get_pref( XI_PREF_R4_API ) ) { XinFontCopy( &font, obj_def->v.itf->font ); } #ifdef XI_USE_XVT else { if ( obj_def->v.itf->font_id != NULL ) font = XinFontXvtConvert( obj_def->v.itf->font_id ); } #endif break; } if ( font != NULL ) return font; return xi_def_get_font( obj_def->parent ); } /*--------------------------------------------------------------------------*/ /* xi_get_xil_pref */ /*--------------------------------------------------------------------------*/ BOOLEAN xi_get_xil_pref( XI_OBJ * obj ) { assert( obj->type == XIT_ITF ); if ( obj->v.itf->use_xil_win ) return TRUE; return ( BOOLEAN ) xi_get_pref( XI_PREF_XIL ); } BOOLEAN xi_def_get_xil_pref( XI_OBJ_DEF * obj_def ) { if ( obj_def != 0 ) { assert( obj_def->type == XIT_ITF ); if ( obj_def->v.itf->use_xil_win ) return TRUE; } return ( BOOLEAN ) xi_get_pref( XI_PREF_XIL ); } BOOLEAN xi_pt_in_rect( XinRect * rct, XinPoint pnt ) { return ( pnt.h >= rct->left && pnt.h < rct->right && pnt.v >= rct->top && pnt.v < rct->bottom ); } void xi_draw_text( XinWindow win, XinFont * font, int x, int y, char *string, int len ) { xi_set_cur_window( win ); x -= cur_delta_x; y -= cur_delta_y; #if XIWS == XIWS_WM y -= 8; { DRAW_CTOOLS ct; XinWindowDrawToolsGet( win, &ct ); if ( ct.mode == M_XOR ) XinWindowDrawModeSet( win, M_COPY ); } #endif XinWindowTextDraw( win, font, x, y, string, len ); } void xi_caret_on( XinWindow win, int x, int y, int height, XinRect * clip_rect ) { XI_ITF_DATA *itf_data; XinPoint p; XinRect local_clip; XinDrawTools dt; itf_data = xi_get_itf( win )->v.itf; #ifdef XI_USE_TX_SUPPORT if ( itf_data->caret_is_on ) { XinWindowCaretOff( win ); } #endif itf_data->caret_x = x; itf_data->caret_y = y; itf_data->caret_height = height; itf_data->caret_is_on = TRUE; itf_data->caret_clip = *clip_rect; p.h = x; p.v = y; vpnt_to_ppnt( win, &p ); x = p.h; y = p.v; local_clip = *clip_rect; vrct_to_prct( win, &local_clip ); XinWindowDrawToolsGet( win, &dt ); XinWindowCaretOn( win, x, y, height, dt.text_back_color, &local_clip ); } void xi_set_clip( XinWindow win, XinRect * rctp ) { XinRect r; if ( rctp ) { r = *rctp; vrct_to_prct( win, &r ); if ( r.right <= r.left ) r.right = r.left + 1; if ( r.top > r.bottom ) r.top = r.bottom; XinWindowClipSet( win, &r ); } else XinWindowClipSet( win, NULL ); } char * xi_get_text_string( char *src, unsigned long attrib ) { int len; static char buf[256]; char *dst; len = strlen( src ); len = min( len, sizeof( buf ) - 1 ); if ( attrib & XI_ATR_PASSWORD ) memset( buf, ( char ) xi_get_pref( XI_PREF_PASSWORD_CHAR ), len ); else gstrncpy( buf, src, len ); dst = buf; dst[len] = '\0'; return ( dst ); } BOOLEAN xi_cr_is_ok( XI_OBJ * xi_obj ) { if ( xi_obj == NULL ) return FALSE; switch ( xi_obj->type ) { case XIT_FIELD: return stx_cr_is_ok( xi_obj->v.field->stx ); case XIT_CELL: return lm_cr_is_ok( xi_obj->parent->v.list->lm, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled ); case XIT_BTN: return TRUE; default: return FALSE; } } void xi_draw_dotted_rect( XinWindow win, XinRect * rctp ) { XinPoint p1, p2, p3, p4; p1.v = rctp->top + 1; for ( p1.h = rctp->left + 1; p1.h < rctp->right - 1; p1.h += 2 ) { p2 = p1; ++p2.h; xi_move_to( win, p1 ); xi_draw_line( win, p2 ); p3 = p1; p3.v = rctp->bottom - 1; p4 = p3; ++p4.h; xi_move_to( win, p3 ); xi_draw_line( win, p4 ); } p1.h = rctp->left; for ( p1.v = rctp->top + 2; p1.v < rctp->bottom - 1; p1.v += 2 ) { p2 = p1; ++p2.v; xi_move_to( win, p1 ); xi_draw_line( win, p2 ); p3 = p1; p3.h = rctp->right - 1; p4 = p3; ++p4.v; xi_move_to( win, p3 ); xi_draw_line( win, p4 ); } } BOOLEAN xi_focus_obj_is_cell_button( XI_OBJ * focus_obj ) { if ( focus_obj->type != XIT_CELL ) return FALSE; return lm_is_button_full_cell( focus_obj->parent->v.list->lm, focus_obj->v.cell.row, focus_obj->v.cell.column ); } void xi_draw_foc_and_dflt_if_necessary( XI_OBJ * focus_obj, XI_OBJ * next_obj ) { int focus_obj_cr_ok, next_obj_cr_ok; focus_obj_cr_ok = xi_cr_is_ok( focus_obj ); next_obj_cr_ok = xi_cr_is_ok( next_obj ); if ( focus_obj_cr_ok != next_obj_cr_ok ) xi_draw_foc_and_dflt( focus_obj->itf ); } BOOLEAN xi_get_native_controls( XI_OBJ * obj ) { if ( obj->type != XIT_BTN ) return ( BOOLEAN ) xi_get_pref( XI_PREF_NATIVE_CTRLS ); switch ( obj->v.btn->draw_as ) { case XIBT_EMULATED: return FALSE; case XIBT_NATIVE: return TRUE; } return ( BOOLEAN ) xi_get_pref( XI_PREF_NATIVE_CTRLS ); } #ifdef XI_USE_TX_SUPPORT void xi_caret_off( XinWindow win ) { XI_ITF_DATA *itf_data; itf_data = xi_get_itf( win )->v.itf; if ( itf_data->caret_is_on ) { itf_data->caret_is_on = FALSE; XinWindowCaretOff( win ); } } #endif BOOLEAN xi_get_obj_by_pointer( XI_OBJ * parent, XI_OBJ * target ) { XI_OBJ **objlist; int n; if ( parent == target ) return ( TRUE ); switch ( parent->type ) { case XIT_GROUP: case XIT_CELL: case XIT_ROW: return ( FALSE ); default: break; } /* search in child list */ objlist = xi_get_member_list( parent, &n ); for ( ; n > 0; n--, objlist++ ) { /* call recursively for generality in future versions */ if ( xi_get_obj_by_pointer( *objlist, target )) return ( TRUE ); } return ( FALSE ); } BOOLEAN xi_is_obj( XI_OBJ* obj, XI_OBJ* itf ) { if (!xi_is_itf( itf )) return FALSE; return xi_get_obj_by_pointer( itf, obj ); }