/******************************************************************************* * Copyright 1991-1995 by ORCA Software, Inc. * * * * All rights reserved. May not be reproduced or distributed, in printed or * * electronic form, without permission of ORCA Software, Inc. May not be * * distributed as object code, separately or linked with other object modules, * * without permission. * *******************************************************************************/ #define XI_INTERNAL #include "xiextend.h" #include "xi.h" #include "xiutils.h" #include "xitext.h" #include "xistx.h" #include "xilm.h" #if XIWS == WINWS #include "dos.h" #endif #if XVT_OS == XVT_OS_CTOS #define STX_VERT_FUDGE ((npctos_env == CHSERVICE) ? 0 : 6) #define BORDER_WIDTH ((npctos_env == CHSERVICE) ? 8 : 2) #define EDIT_BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1) #define EDIT_BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1) #define BORDER_WIDTH_X ((npctos_env == CHSERVICE) ? 8 : 1) #define BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1) #define BORDER_SPACE_X ((npctos_env == CHSERVICE) ? 0 : 1) #define BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1) #else #if XIWS == WMWS #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 #endif #define MAX_RADIO_BUTTONS 30 CBRUSH ltgray_cbrush = { PAT_SOLID, COLOR_LTGRAY }; CBRUSH gray_cbrush = { PAT_SOLID, COLOR_GRAY }; CBRUSH hollow_cbrush = { PAT_HOLLOW, COLOR_WHITE }; FONT_OBJ xi_sysfont; #if (XIWS != GRWS) || (XVT_CC != XVT_CC_MS70) CPEN hollow_cpen = { 0, PAT_HOLLOW, P_SOLID, COLOR_WHITE }; CPEN black_cpen = { 1, PAT_SOLID, P_SOLID, COLOR_BLACK }; CPEN rubber_cpen = { 1, PAT_RUBBER, P_DASH, COLOR_BLACK }; CBRUSH white_cbrush = { PAT_SOLID, COLOR_WHITE }; #endif /* added following lines for 386 port of dgr */ #if XIWS == GRWS CPEN hollow_cpen = { 0, PAT_HOLLOW, P_SOLID, COLOR_WHITE }; CPEN black_cpen = { 1, PAT_SOLID, P_SOLID, COLOR_BLACK }; CPEN rubber_cpen = { 1, PAT_RUBBER, P_DASH, COLOR_BLACK }; CBRUSH white_cbrush = { PAT_SOLID, COLOR_WHITE }; #endif static WINDOW 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 */ K_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 */ #if XVT_OS == XVT_OS_CTOS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ 12, /* 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 */ 24, /* XI_PREF_ITF_MIN_TOP */ 8, /* XI_PREF_ITF_MIN_LEFT */ FALSE, /* XI_PREF_XIL */ FALSE, /* XI_PREF_ASSERT_ON_NULL_CID */ #else #if XIWS == WMWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ COLOR_GRAY, /* XI_PREF_COLOR_DARK */ TRUE, /* 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #elif XIWS == PMWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #elif XIWS == GRWS 2, /* XI_PREF_COLUMN_OFFSET */ 0, /* XI_PREF_SB_OFFSET */ 12, /* XI_PREF_SB_WIDTH */ 12, /* 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ COLOR_GRAY, /* XI_PREF_COLOR_DARK */ FALSE, /* 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ COLOR_GRAY, /* XI_PREF_COLOR_DISABLED */ #elif XIWS == MACWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #elif XIWS == XOLWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_GRAY, /* XI_PREF_COLOR_CTRL */ COLOR_DKGRAY, /* XI_PREF_COLOR_DARK */ FALSE, /* 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #elif XIWS == MTFWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #elif XIWS == WINWS 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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ COLOR_GRAY, /* XI_PREF_COLOR_DARK */ FALSE, /* XI_PREF_OPTIMIZE_CELL_REQUESTS */ 1, /* XI_PREF_CARET_WIDTH */ 500, /* XI_PREF_TRIPLE_CLICK_TIME */ K_DOWN | XI_MOD_CONTROL, /* 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #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 */ COLOR_WHITE, /* XI_PREF_COLOR_LIGHT */ COLOR_LTGRAY, /* XI_PREF_COLOR_CTRL */ 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 */ K_F3, /* XI_PREF_ITF_TAB_CHAR */ K_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 */ 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 */ #endif #endif }; static long aga_preferences[AGA_NBR_PREFERENCES] = { COLOR_LTGRAY, COLOR_GRAY, COLOR_DKGRAY}; RCT big_clip = { 0, 0, 10000, 10000 }; static void xi_caret_suspend(WINDOW win); static void xi_caret_restore(WINDOW win); #if XIWS == WMWS void xi_fix_color(COLOR *color) { if (*color == COLOR_BLACK) *color = COLOR_WHITE; else if (*color == COLOR_WHITE) *color = COLOR_BLACK; } #endif char * tgstrncpy(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; } } RCT * xi_inflate_rect(RCT *rct, int amount) { rct->bottom += amount; rct->right += amount; rct->left -= amount; rct->top -= amount; return(rct); } static void xi_offset_rect(RCT *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); } } XVT_FNTID xi_create_copy_font_id(XI_OBJ *itf, XVT_FNTID font_id, XVT_FNTID old_font_id) { int i, j; XVT_FNTID copy_font_id; XI_ITF_DATA *itf_data; BOOLEAN found = FALSE; itf_data = itf->v.itf; if (old_font_id) { for (i = 0; i < itf_data->nbr_font_ids; ++i) { if (itf_data->font_ids[i] == old_font_id) { found = TRUE; break; } } if (found) { if (font_compare(old_font_id, itf_data->font_ids[i])) return old_font_id; xvt_font_destroy(font_id); if (i < itf_data->nbr_font_ids) { for (j = i; j < itf_data->nbr_font_ids - 1; ++j) itf_data->font_ids[j] = itf_data->font_ids[j + 1]; itf_data->nbr_font_ids--; xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids, sizeof(XVT_FNTID), itf_data); } } } copy_font_id = xvt_font_create(); xvt_font_copy(copy_font_id, font_id, (unsigned long)XVT_FA_ALL); itf_data->nbr_font_ids++; xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids, sizeof(XVT_FNTID), itf_data); itf_data->font_ids[itf_data->nbr_font_ids - 1] = copy_font_id; return copy_font_id; } void xi_free_font_id(XI_OBJ *itf, XVT_FNTID font_id) { XI_ITF_DATA *itf_data; int i, j; itf_data = itf->v.itf; for (i = 0; i < itf_data->nbr_font_ids; ++i) if (itf_data->font_ids[i] == font_id) break; xvt_font_destroy(font_id); if (i < itf_data->nbr_font_ids) { for (j = i; j < itf_data->nbr_font_ids - 1; ++j) itf_data->font_ids[j] = itf_data->font_ids[j + 1]; itf_data->nbr_font_ids--; xi_realloc_array((void **)&itf_data->font_ids, itf_data->nbr_font_ids, sizeof(XVT_FNTID), itf_data); } } 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; WINDOW 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; xvt_sbar_set_pos(win, VSCROLL, 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; xvt_sbar_set_pos(win, HSCROLL, ps); } void xi_get_hsb_rect(XI_OBJ *xi_obj, RCT *rctp) { XI_LIST_DATA *list_data; LM_DATA *lmp; RCT rct1, rct3; XI_OBJ * *members; int nbr_members; #if (XIWS == WINWS) || (XIWS == GRWS) RCT 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 == WINWS) || (XIWS == GRWS) if (list_data->hsb_win) xvt_vobj_get_client_rect(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 XI_IS_NOT_CH CTOS_IS_PM; rct3.top = rct1.bottom - 1; rct3.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH; CTOS_END; #endif #if XI_IS_CH CTOS_IS_CH; rct3.top = rct1.bottom; rct3.right = lmp->rct.left + lmp->pixel_width; CTOS_END; #endif rct3.bottom = rct3.top + (int)xi_get_pref(XI_PREF_SB_HEIGHT); #if (XIWS == WINWS) || (XIWS == GRWS) if (list_data->hsb_win) rct3.bottom = rct3.top + r.bottom; #endif *rctp = rct3; list_data->hsb_rct = rct3; list_data->have_hsb_rct = TRUE; } void xi_get_sb_rect(XI_OBJ *xi_obj, RCT *rctp) { RCT rct; int offset, width; XI_LIST_DATA *list_data; LM_DATA *lmp; #if (XIWS == WINWS) || (XIWS == GRWS) RCT 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 == WINWS) || (XIWS == GRWS) if (list_data->sb_win) xvt_vobj_get_client_rect(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 XI_IS_NOT_CH CTOS_IS_PM; if (list_data->width) rct.left = rct.left + lmp->pixel_width + offset + 2 * BORDER_WIDTH - 1; else rct.left = rct.right + offset - 1; CTOS_END; #endif #if XI_IS_CH CTOS_IS_CH; if (list_data->width) rct.left = rct.left + lmp->pixel_width + offset; else rct.left = rct.right + offset; CTOS_END; #endif rct.right = rct.left + width; #if (XIWS == WINWS) || (XIWS == GRWS) 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 == WINWS) || (XIWS == GRWS) if (list_data->sb_win) list_data->sbb_rct.right = list_data->sbb_rct.left + r.right; #endif #if XI_IS_CH CTOS_IS_CH; rct.top = lm_data->pix_row1_top; CTOS_END; #endif #if XI_IS_NOT_CH CTOS_IS_PM; rct.top = list_data->sbb_rct.bottom; CTOS_END; #endif } *rctp = rct; list_data->sb_rct = rct; list_data->have_sb_rct = TRUE; } void xi_move_list_scroll_bar(XI_OBJ *xi_obj) { RCT rct; WINDOW win = xi_obj->itf->v.itf->xvt_win; WINDOW 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->xvt_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) xvt_vobj_move(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) { RCT rct; WINDOW 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) xvt_vobj_move(hsb_win, &rct); } BOOLEAN xi_half_baked(WINDOW win) { XI_OBJ *itf; itf = xi_get_itf(win); if (itf) return itf->v.itf->half_baked; return FALSE; } 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() { #if XIWS == MTFWS clean_primesel(); #endif xvt_font_destroy(xi_sysfont); } long xi_get_pref(XI_PREF_TYPE pref_type) { long pref; pref = xi_preferences[pref_type]; #if XVT_OS == XVT_OS_CTOS CTOS_IS_CH; switch (pref_type) { case XI_PREF_COLUMN_OFFSET: pref = 0; break; case XI_PREF_SB_OFFSET: pref = 0; break; case XI_PREF_SB_WIDTH: pref = 8; break; case XI_PREF_SB_HEIGHT: pref = 8; break; case XI_PREF_BUTTON_HEIGHT: pref = 24; break; case XI_PREF_BUTTON_PAD: pref = 32; break; case XI_PREF_HORZ_SPACING: pref = 16; break; case XI_PREF_VERT_SPACING: pref = 0; break; case XI_PREF_VERT_PIXEL_SPACING: case XI_PREF_HORZ_PIXEL_SPACING: pref = 0; break; case XI_PREF_ITF_MIN_TOP: pref = 16; break; } CTOS_END; #endif 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_id(XVT_FNTID font_id) { font_set = TRUE; xi_sysfont = xvt_font_create(); xvt_font_copy(xi_sysfont, font_id, (unsigned long)XVT_FA_ALL); } void xi_init_sysvals(void) { static RCT rct = { -1000, -1000, -900, -900 }; WINDOW win; int ascent, descent, leading, height; if (! font_set) { xi_sysfont = xvt_font_create(); xvt_font_set_family(xi_sysfont, XVT_FFN_HELVETICA); xvt_font_set_size(xi_sysfont, 9); } /* Determine height and average width of chosen font. We do this by creating an invisible window and selecting the font into it and getting its metrics. */ win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0); xvt_font_map(xi_sysfont, win); xvt_dwin_set_font(win, xi_sysfont); xvt_font_get_metrics(xi_sysfont, &leading, &ascent, &descent); 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, xi_xvt_get_text_width(win, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", -1) / 52); xi_set_sysval(XI_SV_SYSFONT_HEIGHT, height); xvt_vobj_destroy(win); } /* xi_get_enclosing_rect - get the enclosing rectangle of two other rectangles. ENTRY - src1, src2 are the rects of interest. EXIT - dst is set to the enclosing rect and returned. If is OK for dst to equal one of the sources. */ RCT * xi_get_enclosing_rect(RCT *dst, RCT *src1, RCT *src2) { RCT rct; rct.top = min(src1->top, src2->top); rct.left = min(src1->left, src2->left); rct.bottom = max(src1->bottom, src2->bottom); rct.right = max(src1->right, src2->right); *dst = rct; return(dst); } void xi_fu_to_pu(XI_OBJ *itf, PNT *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, PNT *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(WINDOW win, 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] = XI_PASSWORD_CHAR; buf[1] = '\0'; pw_size = xi_xvt_get_text_width(win, buf, 1); return (pw_size * len); } else return(xi_xvt_get_text_width(win, s, len)); } void xi_draw_clipped_text(WINDOW win, char *s, RCT *bound_rctp, RCT *clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen, int rule_and_space, int str_len) { int ascent, descent, leading, wid; char buf[256]; int len; int baseline; RCT tmp_rct; if (! (attrib & XI_ATR_VISIBLE)) return; xi_get_font_metrics(win, &leading, &ascent, &descent); tmp_rct = *clip_rctp; /* Adjust bottom so border is not overwritten */ tmp_rct.bottom = tmp_rct.bottom - BORDER_WIDTH; xi_set_clip(win, &tmp_rct); NOREF( set_the_cpen ); /* TODO ????? if (set_the_cpen) xi_set_cpen(win, &black_cpen); */ len = strlen(s); len = min(len, sizeof(buf) - 1); if (attrib & XI_ATR_PASSWORD) memset(buf, XI_PASSWORD_CHAR, len); else gstrncpy(buf, s, len); buf[len] = '\0'; #if XI_IS_CH CTOS_IS_CH; NOREF(rule_and_space); baseline = bound_rctp->top + 8; CTOS_END; #endif #if XI_IS_NOT_CH CTOS_IS_PM; 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; CTOS_END; #endif if (attrib & XI_ATR_RJUST) { wid = xi_xvt_get_text_width(win, buf, -1); xi_draw_text(win, bound_rctp->right - wid, baseline, buf, str_len); } else { if (attrib & XI_ATR_HCENTER) { int x; wid = xi_xvt_get_text_width(win, 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, x, baseline, buf, str_len); } else xi_draw_text(win, bound_rctp->left, baseline, buf, str_len); } xi_set_clip(win, (RCT *)NULL); } void xi_draw_text_attrib(WINDOW win, int x, int y, char *s, int len, unsigned long attrib) { char buf[256]; if (! (attrib & XI_ATR_VISIBLE)) return; if (len == -1) len = strlen(s); len = min(len, sizeof(buf) - 1); if (attrib & XI_ATR_PASSWORD) memset(buf, XI_PASSWORD_CHAR, len); else gstrncpy(buf, s, len); buf[len] = '\0'; #if 0 #if XIWS == PMWS /* Nasty hack for OS2, because OS2 doesn't draw LTGRAY rectangles correctly, but does if you draw opaque spaces with LTGRAY back color */ #define BUFSZ 200 { char s[BUFSZ], *sp; int i; for (i = 0, sp = s; i < BUFSZ; ++i, ++sp) *sp = ' '; s[BUFSZ - 1] = '\0'; xi_draw_text(win, x, y, s, -1); } #endif #endif xi_draw_text(win, x, y, buf, -1); } void xi_draw_3d_rect(WINDOW win, RCT *rctp, BOOLEAN well, int height, COLOR color_light, COLOR color_ctrl, COLOR color_dark) { RCT rct; PNT pnt, pnt2; CPEN cpen; CBRUSH 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; xi_set_draw_mode(win, M_COPY); /* draw upper left lines */ cpen.color = well ? color_dark : color_light; xi_set_cpen(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.color = well ? color_light : color_dark; xi_set_cpen(win, &cpen); pnt.h = rct.left; pnt.v = rct.bottom - 1; xi_move_to(win, pnt); pnt2.h = rct.right; pnt2.v = pnt.v; xi_draw_line(win, pnt2); if (height == 2) { pnt.h++; pnt.v--; xi_move_to(win, pnt); pnt2.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--; pnt.v++; xi_move_to(win, pnt); pnt2.h = pnt.h; pnt2.v = rct.bottom; xi_draw_line(win, pnt2); } xi_set_cpen(win, &hollow_cpen); cbrush = white_cbrush; cbrush.color = color_ctrl; xi_set_cbrush(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--; } #if XIWS == XOLWS || XIWS == MTFWS /* X GRAY SCALE HACK */ xi_set_xvt_back_color(win, COLOR_WHITE); { DRAW_CTOOLS ct; xi_get_draw_ctools(win, &ct); ct.opaque_text = FALSE; xi_set_draw_ctools(win, &ct); xi_draw_text(win, rctp->left, rctp->top, " ", -1); } #endif xi_draw_rect(win, &rct); } void xi_draw_3d_line(WINDOW win, PNT pnt1, PNT pnt2, BOOLEAN well) { COLOR color_light, color_dark; PNT pnt1x, pnt2x; CPEN cpen; color_light = xi_get_pref(XI_PREF_COLOR_LIGHT); color_dark = xi_get_pref(XI_PREF_COLOR_DARK); cpen = black_cpen; xi_set_draw_mode(win, M_COPY); cpen.color = well ? color_dark : color_light; xi_set_cpen(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.color = well ? color_light : color_dark; xi_set_cpen(win, &cpen); xi_move_to(win, pnt1x); xi_draw_line(win, pnt2x); } void xi_draw_thick_rect(WINDOW win, RCT *rctp, int width) { RCT 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(WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black, BOOLEAN fill, COLOR color) { PNT pnt1, pnt2; int half_width, width; RCT rct; COLOR color_light, color_ctrl, color_dark; CPEN 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.color = well ? color_dark : color_light; if (black) cpen.color = COLOR_BLACK; if (color) cpen.color = color; xi_set_cpen(win, &cpen); xi_set_draw_mode(win, M_COPY); /* 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.color = well ? color_light : color_dark; if (black) cpen.color = COLOR_BLACK; if (color) cpen.color = color; xi_set_cpen(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; PNT pnt1, pnt2; v1 = rct.top + half_width - 1; v2 = rct.top + half_width; cpen.color = color_ctrl; xi_set_cpen(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(WINDOW win, RCT *rctp, BOOLEAN well, BOOLEAN black, int height, COLOR color) { RCT 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; } } char * gmemmove(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; } #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 != WMWS void dbg_rct(char *tag, RCT *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_get_font_metrics(WINDOW win, int *leadingp, int *ascentp, int *descentp) { xvt_dwin_get_font_metrics(win, leadingp, ascentp, descentp); #if XVTWS == WINWS if (*leadingp == 0) { *leadingp = 2; *ascentp -= 2; } #endif } void xi_set_xvt_font(WINDOW win, FONT_OBJ *fontp, BOOLEAN scale) { NOREF(scale); /* xvt_font_map(*fontp, win); this causes GPF in XVT, even though it is valid */ xvt_dwin_set_font(win, *fontp); } void xi_set_cur_window(WINDOW 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_set_draw_ctools(WINDOW win, DRAW_CTOOLS *ct) { xvt_dwin_set_draw_ctools(win, ct); #if XIWS == WMWS { DRAW_CTOOLS lct; lct = *ct; xi_fix_color(&lct.pen.color); xi_fix_color(&lct.brush.color); xi_fix_color(&lct.back_color); xi_fix_color(&lct.fore_color); xvt_dwin_set_draw_ctools(win, &lct); } #else xvt_dwin_set_draw_ctools(win, ct); #endif } void xi_set_draw_mode(WINDOW win, DRAW_MODE mode) { xvt_dwin_set_draw_mode(win, mode); } void xi_set_cbrush(WINDOW win, CBRUSH *cbrush) { #if XIWS == WMWS { CBRUSH lcbrush; lcbrush = *cbrush; xi_fix_color(&lcbrush.color); xvt_dwin_set_cbrush(win, &lcbrush); } #else xvt_dwin_set_cbrush(win, cbrush); #endif } void xi_set_cpen(WINDOW win, CPEN *cpen) { #if XIWS == WMWS { CPEN lcpen; lcpen = *cpen; xi_fix_color(&lcpen.color); xvt_dwin_set_cpen(win, &lcpen); } #else xvt_dwin_set_cpen(win, cpen); #endif } void xi_set_xvt_back_color(WINDOW win, COLOR color) { #if XIWS == WMWS xi_fix_color(&color); #endif xvt_dwin_set_back_color(win, color); } void xi_set_xvt_fore_color(WINDOW win, COLOR color) { xvt_dwin_set_fore_color(win, color); } DRAW_CTOOLS * xi_get_draw_ctools(WINDOW win, DRAW_CTOOLS *ct) { return xvt_dwin_get_draw_ctools(win, ct); } void xi_dbg(char *buf) { xvt_debug_printf(buf); } WINDOW xi_new_child_window(RCT *rctp, char *title, WIN_TYPE t, BOOLEAN ctl_size, BOOLEAN ctl_vscroll, BOOLEAN ctl_hscroll, BOOLEAN ctl_close, BOOLEAN ctl_iconized, BOOLEAN ctl_iconizable, WINDOW parent, long app_data, short reserve1, long reserve2, BOOLEAN visible, BOOLEAN enabled, int menu_bar_rid) { long flags; WINDOW win; NOREF(reserve1); NOREF(reserve2); if (! parent) #if (XIWS != XOLWS) parent = TASK_WIN; #else parent = SCREEN_WIN; #endif flags = (ctl_size ? WSF_SIZE : 0) | (ctl_close ? WSF_CLOSE : 0) | (ctl_iconized ? WSF_ICONIZED : 0) | (ctl_iconizable ? WSF_ICONIZABLE : 0) | (ctl_hscroll ? WSF_HSCROLL : 0) | (ctl_vscroll ? WSF_VSCROLL : 0) | (visible ? 0 : WSF_INVISIBLE) | (enabled ? 0 : WSF_DISABLED) | (menu_bar_rid ? 0 : WSF_NO_MENUBAR); win = xvt_win_create(t, rctp, title, menu_bar_rid, parent, flags, EM_ALL, (EVENT_HANDLER)xi_event, app_data); xvt_errmsg_sig_if(!(win), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20090", 20090, "xvt_win_create returned NULL"); xvt_vobj_set_attr(NULL_WIN, ATTR_SUPPRESS_UPDATE_CHECK, (long)TRUE); return win; } void xi_terminate(void) { xvt_app_destroy(); } int xi_xvt_get_text_width(WINDOW win, char *string, int len) { return xvt_dwin_get_text_width(win, string, len); } void xi_even_fu(int *f) { *f = (*f * XI_FU_MULTIPLE + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE; } void xi_even_fu_pnt(PNT *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_sysfont); } int xi_get_fu_height(XI_OBJ *itf) { if (itf) return itf->v.itf->fu_height; else return xi_get_fu_height_font(&xi_sysfont); } int xi_get_fu_width_font(FONT_OBJ *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(FONT_OBJ *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(FONT_OBJ *font, PNT *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--; } } #define FONT_ATTR_SIZE 256 /* family or native_desc size */ /* The following font comparison routine is not general purpose, it does not properly handle the case where one of the compared fonts has the native descriptor and the other one does not. This does not matter in case of xi, where we compare if an (unmapped) font matches an already mapped one, and thus native descriptor is only important when both fonts have it set. */ BOOLEAN font_compare ( XVT_FNTID f1, XVT_FNTID f2 ) { char buf1[FONT_ATTR_SIZE]; char buf2[FONT_ATTR_SIZE]; if (f1 == f2) return TRUE; /* If both font have valid native descs, compare those */ if ( xvt_font_get_native_desc(f1, buf1, FONT_ATTR_SIZE) && xvt_font_get_native_desc(f2, buf2, FONT_ATTR_SIZE)) { if ( *buf1 && *buf2 ) return ( strncmp(buf1, buf2, FONT_ATTR_SIZE ) == 0 ); } /* If one of the fonts lacks nd, compare portable attrs */ if ( xvt_font_get_style(f1) != xvt_font_get_style(f2) ) return FALSE; if ( xvt_font_get_size (f1) != xvt_font_get_size (f2) ) return FALSE; if ( !xvt_font_get_family( f1, buf1, FONT_ATTR_SIZE )) return FALSE; if ( !xvt_font_get_family( f2, buf2, FONT_ATTR_SIZE )) return FALSE; return ( strncmp(buf1, buf2, FONT_ATTR_SIZE ) == 0 ); } void xi_get_font_metrics_font(FONT_OBJ *font, int *leading, int *ascent, int *descent, int *char_width) { typedef struct { XVT_FNTID font_id; int leading; int ascent; int descent; int char_width; } FONT_INFO; static FONT_INFO *font_info, *fi; static int font_info_cnt = 0; int i; WINDOW win; BOOLEAN close_win = FALSE; for (i = 0, fi = font_info; i < font_info_cnt; ++i, ++fi) { if (font_compare(fi->font_id, *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]; fi->font_id = xvt_font_create(); xvt_font_copy(fi->font_id, *font, (unsigned long)XVT_FA_ALL); /* Remove this code because we can't assume that a window with focus is drawable - it could be a dialog. Create a dummy window in all cases. win = xvt_scr_get_focus_vobj(); if (! win || win == TASK_WIN) */ { RCT rct; rct.top = -200; rct.left = -200; rct.bottom = -100; rct.right = -100; win = xi_new_child_window(&rct, "", W_DOC, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL_WIN, 0L, 0, 0L, FALSE, FALSE, 0); close_win = TRUE; } xi_set_xvt_font(win, font, FALSE); { int tl, ta, td; xi_get_font_metrics(win, &tl, &ta, &td); fi->leading = tl; fi->ascent = ta; fi->descent = td; } fi->char_width = xi_xvt_get_text_width(win, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", - 1) / 52; if (close_win) xvt_vobj_destroy(win); *leading = fi->leading; *ascent = fi->ascent; *descent = fi->descent; *char_width = fi->char_width; } /********************************************************************/ /* FUNCTIONS THAT NEED TRANSPOSING */ static void ppnt_to_vpnt(WINDOW win, PNT *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(WINDOW win, PNT *pnt) { XI_ITF_DATA *itf_data; itf_data = (xi_get_itf(win))->v.itf; pnt->h -= itf_data->delta_x; pnt->v -= itf_data->delta_y; } #define VPNT_TO_PPNT(pp) \ (pp)->h -= cur_delta_x; \ (pp)->v -= cur_delta_y; static void vrct_to_prct(WINDOW win, RCT *rct) { XI_ITF_DATA *itf_data; itf_data = (xi_get_itf(win))->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; } #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; static void move_tx_edit( XI_OBJ* xi_obj ) { TXEDIT text_edit; XI_ITF_DATA* itf_data; RCT rect; RCT new_rect; WINDOW window; text_edit = xi_get_txedit( xi_obj ); if (text_edit == BAD_TXEDIT) return; window = xvt_tx_get_win( text_edit ); itf_data = xi_obj->itf->v.itf; xvt_tx_get_rect( text_edit , &rect); stx_get_inside_rect( xi_obj->v.field->stx, &new_rect ); xi_offset_rect(&new_rect, itf_data->delta_x, itf_data->delta_y); xvt_tx_move(text_edit, &new_rect ); xi_inflate_rect(&new_rect, 1); xvt_dwin_invalidate_rect(window, &new_rect); xi_inflate_rect(&rect, 1); xvt_dwin_invalidate_rect(window, &rect); } static void move_xvt_controls(XI_OBJ *xi_obj ) { XI_OBJ * *objlist; int n; RCT rct; switch (xi_obj->type) { case XIT_ITF: if (! xi_obj->v.itf->half_baked) xvt_dwin_update(xi_obj->v.itf->xvt_win); break; case XIT_FIELD: move_tx_edit( xi_obj ); break; 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); xvt_vobj_move(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); xvt_vobj_move(list_data->hsb_win, &rct); } break; } case XIT_BTN: { RCT 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); xvt_vobj_move(btn_data->btnctl, &rct); } break; } } objlist = xi_get_member_list(xi_obj, &n); for (; n > 0; n--, objlist++) move_xvt_controls(*objlist ); if (xi_obj->type == XIT_ITF) xi_set_clip(xi_obj->v.itf->xvt_win, NULL); } void xi_adjust_sb_vir_itf(WINDOW win, XI_OBJ *itf) { RCT rct; XI_ITF_DATA *itf_data; itf_data = itf->v.itf; xvt_vobj_get_client_rect(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) { PNT 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) xvt_dwin_invalidate_rect(win, NULL); move_xvt_controls( itf ); xi_caret_restore(win); } set_sb_positions(itf); } BOOLEAN xi_eh(WINDOW win, EVENT *ep) { switch (ep->type) { case E_UPDATE: update_pending = FALSE; xi_set_cur_window(win); break; case E_CHAR: if (update_pending && (ep->v.chr.ch == K_UP || ep->v.chr.ch == K_DOWN)) return FALSE; break; case E_SIZE: { XI_OBJ *itf; XI_ITF_DATA *itf_data; RCT rct; itf = xi_get_itf(win); if (! itf) break; itf_data = itf->v.itf; if (itf_data->size_font_to_win) { RCT old_win_rct; int bottom, right; XVT_FNTID *itf_font_id; xvt_vobj_get_client_rect(win, &rct); old_win_rct = itf->v.itf->original_win_rct; bottom = old_win_rct.bottom; right = old_win_rct.right; itf_font_id = itf_data->font; if (itf_font_id) { 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; xvt_font_set_size(*itf_font_id, point_size2 - 1); xi_set_obj_font_id(itf, *itf_font_id); } break; } if (itf_data->virtual_itf) xi_adjust_sb_vir_itf(win, itf); break; } case E_MOUSE_DOWN: case E_MOUSE_UP: case E_MOUSE_DBL: case E_MOUSE_MOVE: ppnt_to_vpnt(win, &ep->v.mouse.where); break; case E_HSCROLL: { 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.what) { case SC_LINE_UP: delta_x = -4 * XI_FU_MULTIPLE; break; case SC_LINE_DOWN: delta_x = 4 * XI_FU_MULTIPLE; break; case SC_PAGE_UP: delta_x = -10 * XI_FU_MULTIPLE; break; case SC_PAGE_DOWN: delta_x = 10 * XI_FU_MULTIPLE; break; case SC_THUMB: { int oldp, newp; oldp = itf_data->phys_xi_pnt.h; newp = (int)((long)ep->v.scroll.pos * ((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 SC_THUMBTRACK: 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) { RCT client_rct; PNT pnt; xvt_dwin_update(win); xvt_vobj_get_client_rect(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; #if XIWS == WMWS /* Hack for *VERY* nasty bug in XVT/CH - need to call xvt_dwin_set_clip twice, to make XVT/CH have no clipping region for xvt_dwin_scroll_rect. */ { RCT rct; rct = client_rct; xi_inflate_rect(&rct, 120); xi_set_clip(win, &rct); xi_set_clip(win, NULL); } #endif xvt_dwin_scroll_rect(win, &client_rct, -pnt.h, 0); set_sb_positions(itf); move_xvt_controls(itf ); do_vir_pan_event(itf, pnt.h, 0, FALSE); xi_caret_restore(win); } break; } case E_VSCROLL: { 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.what) { case SC_LINE_UP: delta_y = -XI_FU_MULTIPLE; break; case SC_LINE_DOWN: delta_y = XI_FU_MULTIPLE; break; case SC_PAGE_UP: delta_y = -10 * XI_FU_MULTIPLE; break; case SC_PAGE_DOWN: delta_y = 10 * XI_FU_MULTIPLE; break; case SC_THUMB: { int oldp, newp; oldp = itf_data->phys_xi_pnt.v; newp = (int)((long)ep->v.scroll.pos * ((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 SC_THUMBTRACK: 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) { RCT client_rct; PNT pnt; xvt_dwin_update(win); xvt_vobj_get_client_rect(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; #if XIWS == WMWS { RCT rct; rct = client_rct; rct.bottom += 24; xi_set_clip(win, &rct); xi_set_clip(win, NULL); } #endif xvt_dwin_scroll_rect(win, &client_rct, 0, -pnt.v); set_sb_positions(itf); move_xvt_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) { RCT cr; WINDOW win; XI_ITF_DATA *itf_data; PNT pf, p; int old; pf.h = delta_x; pf.v = delta_y; itf_data = itf->v.itf; win = xi_get_window(itf); xvt_vobj_get_client_rect(win, &cr); xvt_dwin_update(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; #if XIWS == WMWS { RCT rct; rct = cr; rct.bottom += 24; xi_set_clip(win, &cr); xi_set_clip(win, NULL); } #endif xvt_dwin_scroll_rect(win, &cr, -p.h, -p.v); set_sb_positions(itf); move_xvt_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) { RCT or, cr, cr2; XI_OBJ *itf; XI_ITF_DATA *itf_data; WINDOW win; int dt, db, dl, dr, dh, dv; PNT 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); xvt_vobj_get_client_rect(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) { xvt_dwin_update(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; #if XIWS == WMWS { RCT rct; xvt_vobj_get_client_rect(win, &rct); rct.bottom += 24; xi_set_clip(win, &rct); xi_set_clip(win, NULL); } #endif xvt_dwin_scroll_rect(win, &cr, -p.h, -p.v); set_sb_positions(itf); move_xvt_controls(itf); do_vir_pan_event(itf, p.h, p.v, FALSE); xi_caret_restore(win); } } WINDOW xi_new_control(RCT *lrctp, char *title, WIN_TYPE t, WINDOW parent, BOOLEAN visible, int id, char *templat) { long ctl_flags; RCT r; r = *lrctp; vrct_to_prct(parent, &r); NOREF(templat); ctl_flags = (visible ? 0 : CTL_FLAG_INVISIBLE); return xvt_ctl_create(t, &r, title, parent, ctl_flags, 0L, id); } void xi_scroll_rect(WINDOW win, RCT *rctp, int dh, int dv) { RCT r; xi_set_cur_window(win); r = *rctp; VRCT_TO_PRCT(&r); update_pending = TRUE; #if 0 { HWND hwnd; RECT rect; rect.left = r.left; rect.top = r.top; rect.right = r.right; rect.bottom = r.bottom; hwnd = xvt_vobj_get_attr(win, ATTR_NATIVE_WINDOW); ScrollWindow(hwnd, dh, dv, &rect, &rect); } #endif #if XIWS == WMWS NOREF(dh); NOREF(dv); xvt_dwin_invalidate_rect(win, &r); #else xvt_dwin_set_clip(win, &r); xvt_dwin_scroll_rect(win, &r, dh, dv); #endif } void xi_draw_text(WINDOW win, int x, int y, char *string, int len) { xi_set_cur_window(win); x -= cur_delta_x; y -= cur_delta_y; #if XIWS == WMWS y -= 8; { DRAW_CTOOLS ct; xvt_dwin_get_draw_ctools(win, &ct); if (ct.mode == M_XOR) xvt_dwin_set_draw_mode(win, M_COPY); } #endif xvt_dwin_draw_text(win, x, y, string, len); } void xi_set_clip(WINDOW win, RCT *rctp) { RCT 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; xvt_dwin_set_clip(win, &r); } else xvt_dwin_set_clip(win, NULL); } void xi_caret_on(WINDOW win, int x, int y, int height) { XI_ITF_DATA *itf_data; PNT p; itf_data = xi_get_itf(win)->v.itf; if (itf_data->caret_is_on) { xvt_win_set_caret_visible(win, FALSE ); } xvt_win_set_caret_size(win, (int)xi_get_pref(XI_PREF_CARET_WIDTH), height); itf_data->caret_x = x; itf_data->caret_y = y; itf_data->caret_height = height; itf_data->caret_is_on = TRUE; p.h = x; p.v = y; vpnt_to_ppnt(win, &p); x = p.h; y = p.v; xvt_win_set_caret_pos(win, p); xvt_win_set_caret_visible(win, TRUE); } void xi_caret_off(WINDOW 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; #if XVTWS == WINWS { PNT _p; _p.h = -100; _p.v = -100; xvt_win_set_caret_pos(win, _p); xvt_win_set_caret_visible(win, TRUE); }; #endif xvt_win_set_caret_visible(win, FALSE ); } } static void xi_caret_suspend(WINDOW win) { XI_ITF_DATA *itf_data; itf_data = xi_get_itf(win)->v.itf; if (itf_data->caret_is_on) { xvt_win_set_caret_visible(win, FALSE ); } } static void xi_caret_restore(WINDOW win) { XI_ITF_DATA *itf_data; PNT p; itf_data = xi_get_itf(win)->v.itf; if (itf_data->caret_is_on) { int leading, ascent, descent, x, y; p.h = itf_data->caret_x; p.v = itf_data->caret_y; /* This patches a bug in the caret position in XVT/WIN */ #if XIWS == WINWS xvt_dwin_get_font_metrics( win, &leading, &ascent, &descent ); p.v -= itf_data->caret_height - (leading + ascent + descent ); #endif vpnt_to_ppnt(win, &p); x = p.h; y = p.v; #if XIWS == GRWS ++x; #endif { PNT _p; _p.h = x; _p.v = y; xvt_win_set_caret_pos(win, _p); xvt_win_set_caret_visible(win, TRUE); }; xvt_win_set_caret_size(win, (int)xi_get_pref(XI_PREF_CARET_WIDTH), itf_data->caret_height); } } #if XI_IS_CH void xi_coalesce_invalidates(XI_OBJ *itf, BOOLEAN coalesce) { XI_ITF_DATA *itf_data; CTOS_IS_CH; itf_data = itf->v.itf; if (coalesce) { if (! itf_data->coalescing) { itf_data->inv_rct.top = SHRT_MAX; itf_data->inv_rct.left = SHRT_MAX; itf_data->inv_rct.bottom = 0; itf_data->inv_rct.right = 0; itf_data->invalidated = FALSE; } ++itf_data->coalescing; } else { --itf_data->coalescing; if (! itf_data->coalescing && itf_data->invalidated) xvt_dwin_invalidate_rect(itf_data->xvt_win, &itf_data->inv_rct); } CTOS_END; } #endif void xi_invalidate_rect(WINDOW win, RCT *rct) { RCT r, cr, dr; #if XI_IS_CH XI_OBJ *itf; XI_ITF_DATA *itf_data; #endif if (rct != NULL && (rct->top >= rct->bottom || rct->left >= rct->right)) return; #if XI_IS_CH CTOS_IS_CH; itf = xi_get_itf(win); if (itf) { itf_data = itf->v.itf; if (itf_data->coalescing) { itf_data->invalidated = TRUE; xi_get_enclosing_rect(&itf_data->inv_rct, &itf_data->inv_rct, rct); return; } } CTOS_END; #endif if (! rct) { xvt_dwin_invalidate_rect(win, NULL); return; } r = *rct; vrct_to_prct(win, &r); xvt_vobj_get_client_rect(win, &cr); if (xi_rect_intersect(&dr, &r, &cr)) { update_pending = TRUE; xvt_dwin_invalidate_rect(win, &r); } } BOOLEAN xi_needs_update(WINDOW win, RCT *rct) { RCT r; r = *rct; vrct_to_prct(win, &r); return xvt_dwin_is_update_needed(win, &r); } void xi_draw_icon(WINDOW win, int x, int y, int rid, COLOR fore_color, COLOR back_color) { #if XIWS == PMWS DRAW_CTOOLS save_ctools; #endif #if XVTWS == WMWS NOREF(x); NOREF(y); NOREF(rid); #endif NOREF(fore_color); NOREF(back_color); xi_set_cur_window(win); #if XI_IS_CH return; #else x -= cur_delta_x; y -= cur_delta_y; #if (XIWS == MTFWS) || (XIWS == MACWS) if (fore_color) xvt_dwin_set_fore_color(win, fore_color); if (back_color) xvt_dwin_set_back_color(win, back_color); #endif #if XIWS == PMWS { DRAW_CTOOLS new_ctools; new_ctools.pen.width = 1; new_ctools.pen.color = COLOR_BLACK; new_ctools.pen.pat = PAT_SOLID; new_ctools.pen.style = P_SOLID; new_ctools.brush.pat = PAT_SOLID; new_ctools.brush.color = COLOR_BLACK; new_ctools.mode = M_COPY; new_ctools.opaque_text = TRUE; new_ctools.fore_color = fore_color; new_ctools.back_color = back_color; xvt_dwin_get_draw_ctools(win, &save_ctools); xvt_dwin_set_draw_ctools(win, &new_ctools); { RCT r; r.top = y; r.left = x; r.bottom = y + 1; r.right = x + 1; xvt_dwin_draw_rect(win, &r); } } #endif if (rid) xvt_dwin_draw_icon(win, x, y, rid); #if XIWS == PMWS xvt_dwin_set_draw_ctools(win, &save_ctools); #endif #endif } #if XIWS == WMWS static void adjust_point(short *p) { *p = ((*p + 4) / 8) * 8; } #endif void xi_draw_rect(WINDOW win, RCT *rctp) { if (rctp->top >= rctp->bottom || rctp->left >= rctp->right) return; { #if XVT_OS == XVT_OS_CTOS { RCT r; xi_set_cur_window(win); CTOS_IS_CH; r = *rctp; VRCT_TO_PRCT(&r); draw_rect(&r); CTOS_END; } { RCT rct; DRAW_CTOOLS ct; RCT r; xi_set_cur_window(win); CTOS_IS_PM; r = *rctp; VRCT_TO_PRCT(&r); xi_get_draw_ctools(win, &ct); rct = r; if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID) xvt_dwin_draw_rect(win, &rct); else { rct.top++; rct.right--; xvt_dwin_draw_rect(win, &rct); } CTOS_END; } #else /* XVT_OS_CTOS */ #if XIWS == WMWS DRAW_CTOOLS ct; RCT r; 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(&r); xi_get_draw_ctools(win, &ct); if (ct.mode == M_XOR && ! xvt_rect_is_empty(&r)) ct.brush.color = COLOR_BLACK; if (ct.brush.pat == PAT_HOLLOW) ct.brush.color = ct.back_color; xvt_dwin_set_draw_ctools(win, &ct); xvt_dwin_draw_rect(win, &r); #else /* WMWS */ /************************************* XM *****************************/ #if (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == XOLWS) RCT rct; DRAW_CTOOLS ct; #endif /* (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == XOLWS) */ RCT r; r = *rctp; xi_set_cur_window(win); VRCT_TO_PRCT(&r); #if (XIWS == MTFWS) || (XIWS == XOLWS) xi_get_draw_ctools(win, &ct); rct = r; if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID) xvt_dwin_draw_rect(win, &rct); else { xvt_dwin_draw_rect(win, &rct); } #endif /* MTFWS || XOLWS */ /************************************* PM *****************************/ #if XIWS == PMWS xi_get_draw_ctools(win, &ct); rct = r; if (ct.mode == M_XOR || ct.brush.pat == PAT_SOLID) xvt_dwin_draw_rect(win, &rct); else { xvt_dwin_draw_rect(win, &rct); } #endif /* PMWS */ #if (XIWS != MTFWS) && (XIWS != PMWS) && (XIWS != XOLWS) xvt_dwin_draw_rect(win, &r); #endif /* MTFWS || PMWS || XOLWS */ #endif /* WMWS */ #endif /* XVT_OS_CTOS */ } } static PNT move_to_pnt; void xi_move_to(WINDOW win, PNT pnt) { NOREF(win); VPNT_TO_PPNT(&pnt); move_to_pnt = pnt; } void xi_draw_line(WINDOW win, PNT pnt) { PNT mpnt, mtp; xi_set_cur_window(win); VPNT_TO_PPNT(&pnt); mpnt = pnt; mtp = move_to_pnt; if (mtp.v != mpnt.v && mtp.h != mpnt.h) { if (mtp.h > mpnt.h) { PNT tpnt; tpnt = mtp; mtp = mpnt; mpnt = tpnt; } #if XI_IS_PM CTOS_IS_PM; if (mtp.v > mpnt.v) { mtp.v--; mpnt.h--; } else { mpnt.v--; mpnt.h--; } CTOS_END; #endif #if XIWS == MACWS if (mtp.v > mpnt.v) { mpnt.h--; mpnt.v++; } else { mtp.v++; mpnt.h--; } mtp.v--; mpnt.v--; #endif #if XIWS == WINWS if (mtp.v > mpnt.v) { mpnt.v--; mtp.v--; } #endif #if XIWS == GRWS if (mtp.v > mpnt.v) { mtp.v--; mpnt.h--; } else { mpnt.v--; mpnt.h--; } #endif #if (XIWS == MTFWS) || (XIWS == XOLWS) if (mtp.v > mpnt.v) { mpnt.h--; mtp.v--; } else { mpnt.h--; mpnt.v--; } #endif xvt_dwin_draw_set_pos(win, mtp); xvt_dwin_draw_line(win, mpnt); } else { #if (XVT_OS == XVT_OS_CTOS) CTOS_IS_PM; move_to_pnt.v++; mpnt.v++; if (move_to_pnt.v == mpnt.v) --mpnt.h; if (move_to_pnt.h == mpnt.h) --mpnt.v; CTOS_END; #else #if (XIWS == MACWS) || (XIWS == MTFWS) || (XIWS == PMWS) || (XIWS == GRWS) || (XIWS == XOLWS) if (move_to_pnt.v == mpnt.v) --mpnt.h; if (move_to_pnt.h == mpnt.h) --mpnt.v; #endif #endif xvt_dwin_draw_set_pos(win, move_to_pnt); xvt_dwin_draw_line(win, mpnt); } } BOOLEAN xi_rect_intersect(RCT *rctp, RCT *rctp1, RCT *rctp2) { RCT 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 !xvt_rect_is_empty(&r2); } void xi_trap_mouse(WINDOW win) { xvt_win_trap_pointer(win); } void xi_release_mouse(void) { xvt_win_release_pointer(); } /* 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; WINDOW win; win = xi_get_window(itf); xvt_menu_set_item_enabled(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_icon(XI_OBJ *xi_obj, int icon_rid, int down_icon_rid) { NOREF(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->xvt_win, &bd->rct); break; } default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20088", 20088, "xi_set_icon: Invalid object"); break; } } XI_RCT * xi_get_xi_rct(XI_OBJ *xi_obj, XI_RCT *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: { RCT r; xvt_vobj_get_client_rect(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, (PNT *)&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, (PNT *)&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; WINDOW 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); xi_set_xvt_font(itf_win, &stxp->font, FALSE); xi_get_font_metrics(itf_win, &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, (PNT *)&stxp->rct, 2); stxp->rct.bottom = stxp->rct.top + edit_height; } else { xi_fu_to_pu(xi_obj->itf, (PNT *)&stxp->rct, 2); stxp->rct.bottom -= BORDER_SPACE_Y; /* TODO move text edit object */ } } else { PNT p; RCT rct; short rct_r, rct_b; p = field_data->xi_pnt; xi_fu_to_pu(xi_obj->itf, &p, 1); rct_r = p.h + (field_data->field_width / XI_FU_MULTIPLE) * fu_width + 2 * BORDER_WIDTH_X + 2 * BORDER_SPACE_X; rct_b = p.v + edit_height; xvt_rect_set(&rct, p.h, p.v, rct_r, rct_b); stxp->rct = rct; } btn_dim_x = (XI_FU_MULTIPLE * fu_height) / fu_width; /* btn_dim_x is actual width of button */ #if XI_IS_NOT_CH CTOS_IS_PM; /* make buttons 70% wide as high */ btn_dim_x = (int)((long)btn_dim_x * 83L / 100L); CTOS_END; #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; xi_set_xvt_font(itf_win, &stxp->font, FALSE); xi_get_font_metrics(itf_win, &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 XI_IS_CH BOOLEAN b; STX_DATA *stxp; CTOS_IS_CH; 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; CTOS_END; #endif #if XI_IS_NOT_CH /* TODO problem with this code */ /* TODO Need a boolean - place button next to field */ /* TODO Need to handle correctly if use a button on a field with xi_rct specified */ CTOS_IS_PM; 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; CTOS_END; #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, (PNT *)&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, (PNT *)&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, (PNT *)&btn_data->rct, 2); } break; } case XIT_CONTAINER: { XI_CONTAINER_DATA *container_data; PNT 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, (PNT *)&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_id(XI_OBJ *xi_obj, XVT_FNTID font_id) { XVT_FNTID font2; font2 = xi_create_copy_font_id(xi_obj->itf, font_id, 0); switch (xi_obj->type) { 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, &font2); break; } case XIT_CELL: if (!xi_obj->v.cell.is_vert_scrolled) { XI_OBJ *list; RCT rct; list = xi_obj->parent; lm_set_font( list->v.list->lm, LM_CELL, xi_obj->v.cell.row, xi_obj->v.cell.column, &font2 ); xi_get_rect(xi_obj, &rct); xi_invalidate_rect(xi_get_window(xi_obj->itf), &rct); } break; } } 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) { WINDOW win; static BOOLEAN inside = FALSE; XI_BTN_DATA *btn; if (check != 0 && check != 1) check = 1; if (! xi_get_pref(XI_PREF_NATIVE_CTRLS)) if (xi_is_checked(xi_obj) == check) return; win = xi_obj->itf->v.itf->xvt_win; btn = xi_obj->v.btn; xi_obj->v.btn->checked = check; if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS)) { 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) xi_invalidate_rect(win, &btn->rct); else xi_draw_button(xi_obj, &btn->rct, btn->text, btn->down_icon_rid, btn->up_icon_rid, btn->disabled_icon_rid, enabled, visible, focus, btn->down, btn->dflt, btn->checked, TRUE); break; } } } else { switch (btn->type) { case XIBT_CHECKBOX: xvt_ctl_set_checked(btn->btnctl, check); break; case XIBT_RADIOBTN: case XIBT_TABBTN: { WINDOW 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; xvt_errmsg_sig_if(!(parent->nbr_children <= MAX_RADIO_BUTTONS), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20089", 20089, "Too many radio buttons in a container"); for (i = 0; i < parent->nbr_children; ++i) wins[i] = parent->children[i]->v.btn->btnctl; xvt_ctl_check_radio_button(btn->btnctl, wins, parent->nbr_children); return; } if (type == XIBT_RADIOBTN || type == XIBT_TABBTN) { xvt_ctl_set_checked(btn->btnctl, check); return; } break; } } } 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) { XI_OBJ *itf; itf = xi_obj->itf; 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, COLOR color) { RCT 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; } break; } case XIT_CELL: if (!xi_obj->v.cell.is_vert_scrolled) { LM_CELL_DATA *lmcdp; 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; lmcdp = &lmp->cell_data[row][col]; switch (part) { case XIC_ENABLED: changed = (lmcdp->color != color); lmcdp->color = color; break; case XIC_BACK: changed = (lmcdp->back_color != color); lmcdp->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_BTN: { XI_BTN_DATA *xi_bd; xi_bd = (XI_BTN_DATA*)xi_obj->v.btn; switch (part) { case XIC_FORE: case XIC_ENABLED: changed = (xi_bd->fore_color != color); xi_bd->fore_color = color; } 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; XI_RCT container_rect; container_rect = container->rct; btn_width = max_text_len; #if XIWS == MACWS btn_width *= (XI_FU_MULTIPLE + 2); #else #if XIWS == WINWS 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 #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 ( btn_type == XIBT_TABBTN ) btn_width += (int)xi_get_pref(XI_PREF_BUTTON_PAD) / 2; /* convert to pixels */ btn_width = (int)((btn_width * horz_form_unit)/XI_FU_MULTIPLE); if (container->packed) 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); /* 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: 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; XI_RCT 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; } 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; xvt_errmsg_sig_if(!( btn_height >= vert_form_unit), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20014", 20014, "Not enough room in container for buttons"); container_rect.top += top_ofst; container->rct = container_rect; container->nbr_across = 1; container->nbr_down = container->nbr_buttons; 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; PNT pnt; XI_RCT container_rect; container_rect = container->rct; xvt_errmsg_sig_if(!((container->btn_width > 0)||(container->btn_height > 0)), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20039", 20039, "width or height required with grid"); 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; xvt_errmsg_sig_if(!( container->pix_height <= container_rect.bottom - container_rect.top), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20032", 20032, "button height exceeds container height"); xvt_errmsg_sig_if(!(container->pix_width <= container_rect.right - container_rect.left), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20033", 20033, "button width exceeds container width"); pnt.v = XI_FU_MULTIPLE; xi_fu_to_pu(itf, &pnt, 1); xvt_errmsg_sig_if(!((container->pix_height >= pnt.v)), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20034", 20034, "height must be at least 8 form units"); 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); } xvt_errmsg_sig_if(!(slack >= 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20035", 20035, "Buttons won't fit in container"); } 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) { XI_RCT rect; rect = container->xi_rct; xi_fu_to_pu(cnt_obj->itf, (PNT *)&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) { RCT 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, (PNT *)&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; xvt_errmsg_sig_if(!(cnt_obj->type == XIT_CONTAINER), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20036", 20036, "xi_container_reorient() passed wrong object type"); 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 */ /*--------------------------------------------------------------------------*/ FONT_OBJ* xi_def_get_font( XI_OBJ_DEF* obj_def ) { FONT_OBJ* font = NULL; if (!obj_def) return &xi_sysfont; switch (obj_def->type) { case XIT_FIELD: if (obj_def->v.field->font_id) font = &obj_def->v.field->font_id; break; case XIT_TEXT: if (obj_def->v.text->font_id) font = &obj_def->v.text->font_id; break; case XIT_LIST: if (obj_def->v.list->font_id) font = &obj_def->v.list->font_id; break; case XIT_ITF: if (obj_def->v.itf->font_id) font = &obj_def->v.itf->font_id; 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 ) { /* Determine if the passed object is the interface */ if (xi_is_itf(obj)) { /* If the local variable is set use XIL coordinates */ if (obj->v.itf->use_xil_win) return TRUE; /* If the PREF is set use XIL coordinates */ if ((BOOLEAN)xi_get_pref(XI_PREF_XIL)) return TRUE; /* The interface was not passed in so use the PREF */ }else if ((BOOLEAN)xi_get_pref(XI_PREF_XIL)) return TRUE; return FALSE; }