/******************************************************************************* * 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 XVT_INCL_NATIVE #define XI_INTERNAL #include "xi.h" #include "xitext.h" #include "xistx.h" #include "xilm.h" #include "xiutils.h" #include "xvtmenu.h" #include "xi_int.h" #if XIWS == MTFWS #include #include #endif #if XI_IS_CH #undef strcmp #define strcmp(a, b) strcmp(a, b) #endif #if XVT_OS == XVT_OS_CTOS #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) #else #if XIWS == WMWS #define BORDER_WIDTH 8 #define EDIT_BORDER_WIDTH_Y 0 #define EDIT_BORDER_SPACE_Y 0 #else #define BORDER_WIDTH 2 #define EDIT_BORDER_WIDTH_Y 1 #define EDIT_BORDER_SPACE_Y 1 #endif #endif /******************************* STATIC DATA ********************************/ static XI_EQ *xi_eq; static BOOLEAN inited = FALSE; static XI_WINDOW_LIST *xi_window_list; static char *list_parent; extern WINDOW xi_modal_win; /******************************** FUNCTIONS *********************************/ BOOLEAN xi_compare_objs( XI_OBJ* obj_one, XI_OBJ* obj_two ) { if (obj_one == obj_two) return(TRUE); if ( obj_two != NULL && obj_two->type == XIT_CELL && obj_one != NULL && obj_one->type == XIT_CELL && obj_two->parent == obj_one->parent ) { XI_CELL_DATA* cell_one = &obj_one->v.cell; XI_CELL_DATA* cell_two = &obj_two->v.cell; return cell_one->row == cell_two->row && cell_one->column == cell_two->column && cell_one->is_vert_scrolled == cell_two->is_vert_scrolled; } return FALSE; } static XI_OBJ * get_non_focus_cell_obj(XI_LIST_DATA *list_data) { int i; for (i = 0; i < FOCUS_CELL_ARRAY_LEN; ++i) if (list_data->focus_cell == &list_data->focus_cell_array[i]) break; i = (i + 1) % FOCUS_CELL_ARRAY_LEN; return &list_data->focus_cell_array[i]; } XI_OBJ * xi_search_itf(XI_OBJ *xi_obj, XI_SEARCH_TYPE search_type, int parm1) { XI_OBJ *obj; XI_OBJ * *objp; int i, column, tab_cid; unsigned long attrib; XI_OBJ *cell_obj; XI_LIST_DATA *list_data; LM lm; switch (search_type) { case XI_SEARCH_FOR_FOCUSABLE: switch (xi_obj->type) { case XIT_LIST: lm = xi_obj->v.list->lm; attrib = lm_get_attrib(lm, LM_LIST, 0, 0, FALSE); if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) return NULL; return(xi_obj); case XIT_CELL: return(xi_obj); case XIT_COLUMN: lm = xi_obj->parent->v.list->lm; attrib = lm_get_attrib(lm, LM_LIST, 0, 0, FALSE); if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) return NULL; column = xi_obj_to_idx(xi_obj); attrib = lm_get_attrib(lm, LM_COLUMN, column, 0, FALSE); if ((attrib & (XI_ATR_ENABLED | XI_ATR_SELECTABLE | XI_ATR_VISIBLE)) != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) return NULL; else { list_data = xi_obj->parent->v.list; cell_obj = get_non_focus_cell_obj(list_data); cell_obj->v.cell.row = 0; cell_obj->v.cell.column = (unsigned char)column; return (cell_obj); } case XIT_FIELD: attrib = stx_get_attrib(xi_obj->v.field->stx); if ((attrib & XI_ATR_ENABLED) != 0 && (attrib & XI_ATR_VISIBLE) != 0) return (xi_obj); else return NULL; case XIT_BTN: #if XIWS == MACWS return NULL; #else { unsigned long attrib; attrib = xi_obj->v.btn->attrib; if ((attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)) return xi_obj; else return NULL; } #endif case XIT_GROUP: return NULL; default: break; } break; case XI_SEARCH_FOR_TAB_CID: switch (xi_obj->type) { case XIT_FIELD: tab_cid = xi_obj->v.field->tab_cid; break; case XIT_BTN: tab_cid = xi_obj->v.btn->tab_cid; break; case XIT_FORM: tab_cid = xi_obj->v.form->tab_cid; break; case XIT_CONTAINER: tab_cid = xi_obj->v.container->tab_cid; break; case XIT_LIST: tab_cid = xi_obj->v.list->tab_cid; break; default: tab_cid = -1; break; } if (tab_cid == parm1) return xi_obj; break; case XI_SEARCH_FOR_FIELD: if (xi_obj->type == XIT_FIELD) return xi_obj; break; default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20002", 20002, "Internal XI error"); } /* search child list */ objp = xi_obj->children; obj = NULL; for (i = xi_obj->nbr_children; i > 0 && obj == NULL; i--, objp++) obj = xi_search_itf(*objp, search_type, parm1); return obj; } static void near xi_remove_from_parent_list(XI_OBJ *xi_obj) { XI_OBJ *parent; XI_OBJ * *list; int n; BOOLEAN copying_down = FALSE; if ((parent = xi_obj->parent) == NULL) return; list = parent->children; n = parent->nbr_children; for (; n > 0; n--, list++) { if (copying_down) list[-1] = *list; if (*list == xi_obj) copying_down = TRUE; } /* error if we did not find the child in the list */ xvt_errmsg_sig_if(!(copying_down), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20001", 20001, "XI: internal object deletion error"); parent->nbr_children--; } /* xi_find_next_obj: find the next control in the tabbing sequence. The focus_obj parameter indicates the object that currently has the focus. The type of navigation is given by the tab_type parameter. */ XI_OBJ * xi_find_next_obj(XI_OBJ *focus_obj, XI_NEXT_TYPE tab_type, long c) { XI_OBJ_TYPE type; XI_OBJ *itf, *obj; int tab_cid; if (focus_obj == NULL || focus_obj->type == XIT_ITF) { /* find the first thing on the interface */ return(xi_search_itf(focus_obj->itf, XI_SEARCH_FOR_FOCUSABLE, 0)); } type = focus_obj->type; itf = focus_obj->itf; switch (tab_type) { case XI_NEXT_FORM_TAB: case XI_NEXT_ITF_TAB: switch (tab_type) { case XI_NEXT_FORM_TAB: if (type == XIT_FORM) return(xi_search_itf(itf, XI_SEARCH_FOR_FIELD, 0)); obj = focus_obj; break; case XI_NEXT_ITF_TAB: obj = focus_obj->parent; if (obj->type == XIT_ITF) /* No container, ignore it */ return NULL; break; } while (TRUE) { switch (obj->type) { case XIT_FIELD: tab_cid = obj->v.field->tab_cid; break; case XIT_BTN: tab_cid = obj->v.btn->tab_cid; break; case XIT_FORM: tab_cid = obj->v.form->tab_cid; break; case XIT_LIST: tab_cid = obj->v.list->tab_cid; break; case XIT_CONTAINER: tab_cid = obj->v.container->tab_cid; break; default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20003", 20003, "Internal error"); break; } obj = xi_get_obj(itf, tab_cid); if (obj == NULL || obj == focus_obj) break; #if XIWS == MACWS if (obj->type == XIT_BTN || obj->type == XIT_CONTAINER) continue; #endif if ( (xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) continue; if (obj->type == XIT_LIST) { int i, nbr_members; XI_OBJ * *members; BOOLEAN have_column; members = xi_get_member_list(obj, &nbr_members); have_column = FALSE; for (i = 0; i < nbr_members; ++i) { unsigned long attrib; attrib = xi_get_attrib(members[i]); if ((attrib & XI_ATR_ENABLED) && ! (attrib & XI_ATR_SELECTABLE)) { have_column = TRUE; break; } } if (! have_column) continue; } /* If the tab key was pressed, and the focus is not on the first enabled and visible radio button in the group, then skip to a control that is not in the group. */ { XI_OBJ * *rb_obj, *parent; int i; if (c != K_DOWN && obj->type == XIT_BTN && obj->v.btn->type == XIBT_RADIOBTN && obj->parent->type == XIT_CONTAINER) { parent = obj->parent; for (i = 0, rb_obj = parent->children; i < parent->nbr_children; ++i, ++rb_obj) if ((xi_get_attrib(*rb_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)) break; if (*rb_obj != obj) continue; } } /* If a meta-tab key was pressed, and the obj->type == XIT_FORM then move the focus to the first field in the form */ if (obj->type == XIT_FORM) { XI_OBJ * *field_obj; int i; for (i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj) if ((xi_get_attrib(*field_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)) break; if (i == obj->nbr_children) continue; obj = *field_obj; } break; } return(obj); case XI_NEXT_FORM_BACKTAB: case XI_NEXT_ITF_BACKTAB: switch (tab_type) { case XI_NEXT_FORM_BACKTAB: if (type == XIT_FORM) return(xi_search_itf(itf, XI_SEARCH_FOR_FIELD, 0)); obj = focus_obj; break; case XI_NEXT_ITF_BACKTAB: obj = focus_obj->parent; if (obj->type == XIT_ITF) /* No container, ignore it */ return NULL; break; } while (TRUE) { /* xi_search_itf, searching for TAB CID finds the tab control id just previous in the tabbing sequence, hence the break at the bottom of the loop. */ obj = xi_search_itf(itf, XI_SEARCH_FOR_TAB_CID, obj->cid); if (obj == NULL || obj == focus_obj) break; #if XIWS == MACWS if (obj->type == XIT_BTN || obj->type == XIT_CONTAINER) continue; #endif if ( (xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) continue; if (obj->type == XIT_LIST) { int i, nbr_members; XI_OBJ * *members; BOOLEAN have_column; members = xi_get_member_list(obj, &nbr_members); have_column = FALSE; for (i = 0; i < nbr_members; ++i) { unsigned long attrib; attrib = xi_get_attrib(members[i]); if ((attrib & XI_ATR_ENABLED) && ! (attrib & XI_ATR_SELECTABLE)) { have_column = TRUE; break; } } if (! have_column) continue; } /* If a meta-tab key was pressed, and the obj->type == XIT_FORM then move the focus to the first field in the form */ if (obj->type == XIT_FORM) { XI_OBJ * *field_obj; int i; for (i = 0, field_obj = obj->children; i < obj->nbr_children; ++i, ++field_obj) if ((xi_get_attrib(*field_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)) break; if (i == obj->nbr_children) continue; obj = *field_obj; } break; } if (obj && c != K_UP && obj->type == XIT_BTN && obj->v.btn->type == XIBT_RADIOBTN && obj->parent->type == XIT_CONTAINER && obj->parent->children[0] != obj) { obj = obj->parent->children[0]; while (TRUE) { if ((xi_get_attrib(obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)) break; obj = xi_search_itf(itf, XI_SEARCH_FOR_TAB_CID, obj->cid); } } return(obj); } return NULL; } /* xi_lowlevel_focus: inform a control that it is gaining or losing the focus. A control may reset some internal state when this happens. This is not refusable. */ static void near xi_lowlevel_focus(XI_OBJ *xi_obj, BOOLEAN set) { XI_OBJ *itf; WINDOW win; BOOLEAN native_controls = (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS); itf = xi_obj->itf; win = itf->v.itf->xvt_win; if (native_controls) { if (set && xi_obj->type != XIT_BTN) /* should be set, not ! set */ if (xvt_scr_get_focus_vobj() == win) /* should be ==, not != */ xvt_scr_set_focus_vobj(win); xvt_vobj_raise(win); } switch(xi_obj->type) { case XIT_CELL: lm_focus_cb( xi_obj->parent->v.list->lm, xi_obj->v.cell.row, xi_obj->v.cell.column, xi_obj->v.cell.is_vert_scrolled, set ); return; case XIT_FIELD: stx_focus_cb(xi_obj->v.field->stx, set); break; case XIT_BTN: { XI_BTN_DATA *bd; bd = xi_obj->v.btn; if (!native_controls) { BOOLEAN enabled, visible, focus; unsigned long attrib; if (itf->v.itf->back_color && ! bd->drawable) { 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); xi_draw_button(xi_obj, &bd->rct, bd->text, bd->down_icon_rid, bd->up_icon_rid, bd->disabled_icon_rid, enabled, visible, focus, bd->down, bd->dflt, bd->checked, FALSE); } else xi_invalidate_rect(win, &bd->rct); } else { if (set) xvt_scr_set_focus_vobj(bd->btnctl); } break; } default: /* ignore */ break; } } /* is_group_member: given an object, determine if it is in a group. */ static BOOLEAN near is_group_member(XI_OBJ *obj, XI_OBJ *group) { int *cidlist; int i; cidlist = group->v.group->cidlist; for (i = group->v.group->nbr_cids; i > 0; i--, cidlist++) { if (*cidlist == obj->cid) return(TRUE); } return(FALSE); } BOOLEAN xi_is_focus_moving(XI_OBJ *xi_obj) { XI_OBJ *itf = xi_obj->itf; return itf->v.itf->moving_focus; } /* ----------------------------------------------------------------------- */ /* lm_list_is_about_to_lose_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN lm_list_is_about_to_lose_focus(LM_DATA *lmp) { if (lm_list_has_focus(lmp) && lmp->txt_is_invisible && lmp->focus_rec) { int idx, focus_row, focus_column; BOOLEAN v_scrolled; for (idx = 0; idx < lmp->nbr_realized_rows; ++idx) if (lmp->focus_rec == lmp->recs[idx]) return FALSE; lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1); ++lmp->nbr_realized_rows; idx = lmp->nbr_realized_rows - 1; lmp->recs[idx] = lmp->focus_rec; lmp->saved_focus_rec = lmp->focus_rec; lmp->focus_rec = 0L; lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled); focus_row = idx; lm_set_focus_cell(lmp, focus_row, focus_column, TRUE ); lm_invalidate_rows_internal((LM)lmp, focus_row, focus_row, FALSE, focus_column, TRUE ); calculate_pix_offsets(lmp, FALSE ); calculate_visibles(lmp); return TRUE; } return FALSE; } /* ----------------------------------------------------------------------- */ /* lm_list_did_lose_focus */ /* ----------------------------------------------------------------------- */ static void lm_list_did_lose_focus(LM_DATA *lmp) { LM_CB_DATA lm_cb_data; lm_cb_data.lm = (LM)lmp; lm_cb_data.cb_type = LM_CB_REC_FREE; lm_cb_data.cid = lmp->cid; lm_cb_data.win = lmp->win; lm_cb_data.v.rec_free.record = lmp->saved_focus_rec; (*lmp->lm_cb)(&lm_cb_data); lm_allocate_rec_info(lmp, lmp->nbr_realized_rows - 1); --lmp->nbr_realized_rows; lmp->focus_rec = 0L; lmp->txt_is_invisible = FALSE; } /* ----------------------------------------------------------------------- */ /* lm_list_did_not_lose_focus */ /* ----------------------------------------------------------------------- */ static void lm_list_did_not_lose_focus(LM_DATA *lmp) { lm_allocate_rec_info(lmp, lmp->realized_rows_array_len - 1); --lmp->nbr_realized_rows; lmp->focus_rec = lmp->saved_focus_rec; } /* ----------------------------------------------------------------------- */ /* send focus event */ /* ----------------------------------------------------------------------- */ static BOOLEAN send_object_event( XI_OBJ* object, int event_type ) { XI_EVENT xiev; MEMCLEAR(xiev); xiev.type = event_type; xiev.v.xi_obj = object; call_cb(object->itf, &xiev); return !xiev.refused; } /* ----------------------------------------------------------------------- */ /* move_focus_off_groups */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_group_focus( XI_OBJ* primary_obj, XI_OBJ* secondary_obj, int event_type ) { XI_OBJ** objp; int i; BOOLEAN moving_between_rows = FALSE; if ( primary_obj == NULL ) return TRUE; if (secondary_obj != NULL && secondary_obj->type == XIT_CELL) { if (primary_obj->type == XIT_CELL) moving_between_rows = ( primary_obj->v.cell.row != secondary_obj->v.cell.row ); secondary_obj = secondary_obj->parent->children[ secondary_obj->v.cell.column ]; } if (primary_obj->type == XIT_CELL) primary_obj = primary_obj->parent->children[primary_obj->v.cell.column]; objp = primary_obj->itf->children; for (i = primary_obj->itf->nbr_children; i > 0; i--, objp++) { XI_OBJ* obj; obj = *objp; if (obj->type == XIT_GROUP && is_group_member(primary_obj, obj) && ( secondary_obj == NULL || !is_group_member(secondary_obj, obj) || moving_between_rows )) if (!send_object_event( obj, event_type )) return FALSE; } return TRUE; } /* ----------------------------------------------------------------------- */ /* move_off_column */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_off_column( XI_OBJ* old_focus, XI_OBJ* new_focus ) { if ( new_focus != NULL && new_focus->type == XIT_CELL && old_focus->v.cell.column == new_focus->v.cell.column ) return TRUE; old_focus = old_focus->parent->children[old_focus->v.cell.column]; return send_object_event( old_focus, XIE_OFF_COLUMN ); } /* ----------------------------------------------------------------------- */ /* move_off_row */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_row_focus( XI_OBJ* primary_obj, XI_OBJ* secondary_obj, int event_type ) { XI_OBJ row_obj; /* move off of row */ if ( secondary_obj != NULL && secondary_obj->type == XIT_CELL && primary_obj->v.cell.row == secondary_obj->v.cell.row && primary_obj->parent == secondary_obj->parent ) return TRUE; XI_MAKE_ROW(&row_obj, primary_obj->parent, primary_obj->v.cell.row); row_obj.v.row_data.is_vert_scrolled = primary_obj->v.cell.is_vert_scrolled; if (!send_object_event( &row_obj, event_type )) return FALSE; return TRUE; } /* ----------------------------------------------------------------------- */ /* move_on_column */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_on_column( XI_OBJ* old_focus, XI_OBJ* new_focus ) { if ( old_focus != NULL && old_focus->type == XIT_CELL && old_focus->parent == new_focus->parent && old_focus->v.cell.column == new_focus->v.cell.column) return TRUE; new_focus = new_focus->parent->children[new_focus->v.cell.column]; return send_object_event( new_focus, XIE_ON_COLUMN ); } /* ----------------------------------------------------------------------- */ /* same_parents */ /* ----------------------------------------------------------------------- */ static BOOLEAN same_parents( XI_OBJ* one, XI_OBJ* two ) { if (one != NULL && one->type != XIT_LIST && one->type != XIT_FORM) one = one->parent; if (two != NULL && two->type != XIT_LIST && two->type != XIT_FORM) two = two->parent; return one == two; } /* ----------------------------------------------------------------------- */ /* remove_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN remove_focus( XI_OBJ* old_focus, XI_OBJ* new_focus ) { /* move off old 1st-level object */ if (old_focus == NULL) return TRUE; switch (old_focus->type) { case XIT_CELL: if ( !send_object_event( old_focus, XIE_OFF_CELL ) || !move_off_column( old_focus, new_focus ) || !move_group_focus( old_focus, new_focus, XIE_OFF_GROUP ) || !move_row_focus( old_focus, new_focus, XIE_OFF_ROW ) ) return FALSE; if ( !same_parents( old_focus, new_focus ) ) return send_object_event( old_focus->parent, XIE_OFF_LIST ); break; case XIT_LIST: return ( move_group_focus( old_focus, new_focus, XIE_OFF_GROUP ) && (same_parents(old_focus, new_focus) || send_object_event( old_focus, XIE_OFF_LIST )) ); case XIT_FIELD: if ( !send_object_event( old_focus, XIE_OFF_FIELD ) || !move_group_focus( old_focus, new_focus, XIE_OFF_GROUP ) ) return FALSE; if ( old_focus->parent != new_focus->parent) return send_object_event( old_focus->parent, XIE_OFF_FORM ); break; default: return move_group_focus( old_focus, new_focus, XIE_OFF_GROUP ); } return TRUE; } /* ----------------------------------------------------------------------- */ /* place_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN place_focus (XI_OBJ* old_focus, XI_OBJ* new_focus) { if (new_focus == NULL) return TRUE; switch (new_focus->type) { case XIT_CELL: if ( !same_parents( old_focus, new_focus ) && !send_object_event( new_focus->parent, XIE_ON_LIST )) return FALSE; return ( move_row_focus( new_focus, old_focus, XIE_ON_ROW ) && move_group_focus( new_focus, old_focus, XIE_ON_GROUP ) && move_on_column( old_focus, new_focus ) && send_object_event( new_focus, XIE_ON_CELL )); case XIT_LIST: return (( same_parents(old_focus, new_focus) || send_object_event( new_focus, XIE_ON_LIST )) && move_group_focus( new_focus, old_focus, XIE_ON_GROUP )); case XIT_FIELD: if ( (old_focus == NULL || new_focus->parent != old_focus->parent ) && !send_object_event( new_focus->parent, XIE_ON_FORM )) return FALSE; return ( move_group_focus( new_focus, old_focus, XIE_ON_GROUP ) && send_object_event( new_focus, XIE_ON_FIELD )); } return move_group_focus( new_focus, old_focus, XIE_ON_GROUP ); } /* ----------------------------------------------------------------------- */ /* find_cell_obj */ /* ----------------------------------------------------------------------- */ static XI_OBJ* find_cell_obj( XI_OBJ* new_focus ) { LM_DATA* lmp; XI_OBJ tmp_obj; XI_LIST_DATA* list_data; list_data = new_focus->parent->v.list; lmp = (LM_DATA *)list_data->lm; tmp_obj = *new_focus; new_focus = get_non_focus_cell_obj(tmp_obj.parent->v.list); new_focus->v.cell.row = tmp_obj.v.cell.row; new_focus->v.cell.column = tmp_obj.v.cell.column; if (new_focus->v.cell.row >= (unsigned char)lmp->nbr_realized_rows) return new_focus->itf; return new_focus; } /* ----------------------------------------------------------------------- */ /* move_focus_to_list */ /* ----------------------------------------------------------------------- */ static BOOLEAN move_focus_to_list( XI_OBJ** focus_result ) { LM_DATA* lmp; int col; XI_OBJ* new_focus; XI_LIST_DATA* list_data; new_focus = *focus_result; list_data = new_focus->v.list; lmp = (LM_DATA *)list_data->lm; if (new_focus->nbr_children <= 0) return FALSE; if (lmp->sizing_row) return FALSE; if ( lmp->nbr_realized_rows == 0) { *focus_result = new_focus->itf; return TRUE; } if ( lmp->single_select ) /* attempt to select row */ return TRUE; new_focus = list_data->focus_cell; /* if cell is selectable, disabled, etc, then find another cell */ col = new_focus->v.cell.column; while (TRUE) { long attrib; attrib = lmp->lm_column_data[col]->attrib; if ((attrib & XI_ATR_ENABLED) && !(attrib & XI_ATR_SELECTABLE)) { new_focus->v.cell.column = (unsigned char)col; break; } col++; if (col == lmp->nbr_columns) col = 0; if ((unsigned char)col == new_focus->v.cell.column) { *focus_result = new_focus->itf; return TRUE; } } if (new_focus->v.cell.row >= (unsigned char)lmp->nbr_realized_rows) { if (new_focus->type == XIT_CELL) { /* Last row had focus, but has been deleted. Set focus to new last row, if there is one */ if (lmp->nbr_realized_rows >= 1) new_focus->v.cell.row = lmp->nbr_realized_rows - 1; else new_focus = xi_find_next_obj( new_focus->parent, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR ); } else new_focus = new_focus->itf; } *focus_result = new_focus; return TRUE; } /* ----------------------------------------------------------------------- */ /* determine_focus_button */ /* ----------------------------------------------------------------------- */ static XI_OBJ* determine_focus_button( XI_OBJ* new_focus ) { int i; unsigned long attr = 0L; xvt_errmsg_sig_if(!(new_focus->nbr_children), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20005", 20005, "Internal error"); for (i = 0; i < new_focus->nbr_children; i++) { attr = xi_get_attrib(new_focus->children[i]); if ((attr & XI_ATR_ENABLED) && (attr & XI_ATR_VISIBLE)) return new_focus->children[i]; } return xi_find_next_obj(new_focus, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR); } /* ----------------------------------------------------------------------- */ /* determine_new_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN determine_new_focus( XI_OBJ** new_focus ) { if (*new_focus == NULL) return TRUE; do { switch ((*new_focus)->type) { case XIT_CELL: *new_focus = find_cell_obj( *new_focus ); break; case XIT_LIST: return move_focus_to_list( new_focus ); case XIT_FORM: { XI_OBJ* focus_field = (*new_focus)->v.form->focus_field; if (focus_field) *new_focus = focus_field; break; } case XIT_CONTAINER: *new_focus = determine_focus_button( *new_focus ); break; } } while (*new_focus != NULL && ((*new_focus)->type == XIT_CONTAINER || (*new_focus)->type == XIT_FORM || (*new_focus)->type == XIT_LIST )); if (*new_focus == NULL) return FALSE; return TRUE; } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ static void check_new_focus_enabled( XI_OBJ* xi_obj ) { if (xi_obj == NULL) return; switch (xi_obj->type) { case XIT_CELL: { BOOLEAN xi_obj_enabled; xi_obj_enabled = ((xi_get_attrib(xi_obj->parent) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)); xvt_errmsg_sig_if(!(xi_obj_enabled), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20006", 20006, "Attempting to move to disabled or invisible object"); break; } case XIT_BTN: case XIT_FIELD: case XIT_LIST: { BOOLEAN xi_obj_enabled; xi_obj_enabled = ((xi_get_attrib(xi_obj) & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) == (XI_ATR_ENABLED | XI_ATR_VISIBLE)); xvt_errmsg_sig_if(!(xi_obj_enabled), NULL_WIN, SEV_FATAL, ERR_ASSERT_4, "20007", 20007, "Attempting to move to disabled or invisible object"); break; } } } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ static BOOLEAN determine_alternate_focus( XI_OBJ* old_focus, XI_OBJ** new_focus, BOOLEAN next_if_disabled, int check_for_reenabled ) { XI_OBJ* xi_obj; xi_obj = *new_focus; /* if field for new focus has been disabled, proceed with next field */ if (xi_obj->type != XIT_CELL && xi_obj->type != XIT_ITF) { unsigned long attrib; attrib = xi_get_attrib(xi_obj); if (! (attrib & XI_ATR_ENABLED)) { if (next_if_disabled) xi_obj = xi_find_next_obj(xi_obj, XI_NEXT_FORM_TAB, XI_PREF_FORM_TAB_CHAR); else return FALSE; } } /* if next field used to be disabled, and is not enabled, move to it */ if (check_for_reenabled) { if (xi_obj->type == XIT_FIELD) { XI_OBJ *tmp_obj; tmp_obj = xi_find_next_obj( old_focus, check_for_reenabled == 1 ? XI_NEXT_FORM_TAB : XI_NEXT_FORM_BACKTAB, check_for_reenabled == 1 ? xi_get_pref(XI_PREF_FORM_TAB_CHAR) : xi_get_pref(XI_PREF_FORM_BACKTAB_CHAR)); if (tmp_obj) xi_obj = tmp_obj; } } *new_focus = xi_obj; return TRUE; } /* ----------------------------------------------------------------------- */ /* perform_move_focus */ /* ----------------------------------------------------------------------- */ static BOOLEAN perform_move_focus( XI_OBJ* old_focus, XI_OBJ* new_focus, BOOLEAN make_callbacks, BOOLEAN next_if_disabled, int check_for_reenabled ) { BOOLEAN row_changed; if (!determine_new_focus( &new_focus )) return FALSE; check_new_focus_enabled( new_focus ); /* remove focus */ if (make_callbacks && !remove_focus( old_focus, new_focus )) return FALSE; if (!determine_alternate_focus( old_focus, &new_focus, next_if_disabled, check_for_reenabled ) ) return FALSE; if (make_callbacks && !place_focus( old_focus, new_focus )) return FALSE; /* if list has focus, it's a single-select list */ if ( new_focus != NULL && new_focus->type == XIT_LIST ) { unsigned long attrib; XI_OBJ row_obj; XI_LIST_DATA* list_data = new_focus->v.list; LM_DATA* lmp = (LM_DATA*)list_data->lm; int row = list_data->focus_cell->v.cell.row; /* See if the focus row is selected. */ if (row >= lmp->nbr_realized_rows) row = lmp->nbr_realized_rows - 1; XI_MAKE_ROW( &row_obj, new_focus, row ); attrib = xi_get_attrib(&row_obj); /* If it isn't, see if any row is selected. */ if ((attrib & XI_ATR_SELECTED) == 0) { for (row = 0; row < lmp->nbr_realized_rows; row++) { XI_MAKE_ROW( &row_obj, new_focus, row ); attrib = xi_get_attrib(&row_obj); if (attrib & XI_ATR_SELECTED) break; } } if (row < lmp->nbr_realized_rows) /* Move the focus to the selected row. */ list_data->focus_cell->v.cell.row = row; else { /* Select the first row in the list and make it the focus row. */ list_data->focus_cell->v.cell.row = 0; XI_MAKE_ROW( &row_obj, new_focus, 0 ); if (make_callbacks) { XI_EVENT event; MEMCLEAR(event); event.type = XIE_SELECT; event.v.select.xi_obj = &row_obj; event.v.select.selected = TRUE; event.v.select.dbl_click = FALSE; event.v.select.records = &lmp->recs[0]; call_cb(new_focus->itf, &event); if (event.refused) return FALSE; } /* xi_set_attrib(&row_obj, attrib | XI_ATR_SELECTED ); */ } } /* if we get to here then it has happened */ { XI_ITF_DATA* itf_data; itf_data = new_focus->itf->v.itf; itf_data->chg_flag = FALSE; itf_data->focus_obj = new_focus; if (itf_data->virtual_itf) xi_make_obj_visible(new_focus); } if (new_focus->type == XIT_CELL) new_focus->parent->v.list->focus_cell = new_focus; if (new_focus->type == XIT_FIELD) new_focus->parent->v.form->focus_field = new_focus; if (old_focus != NULL) xi_lowlevel_focus(old_focus, FALSE); if (new_focus != NULL) xi_lowlevel_focus(new_focus, TRUE); row_changed = TRUE; if (old_focus && new_focus && old_focus->type == XIT_CELL && new_focus->type == XIT_CELL && old_focus->parent == new_focus->parent && old_focus->v.cell.row == new_focus->v.cell.row) row_changed = FALSE; if (old_focus != NULL) { if ((old_focus->type == XIT_CELL) && row_changed && (old_focus->v.cell.is_vert_scrolled != TRUE)) { LM lm; lm = old_focus->parent->v.list->lm; lm_redraw_row((LM_DATA *)lm, old_focus->v.cell.row, FALSE); } } if (new_focus != NULL) { if ((new_focus->type == XIT_CELL) && row_changed) { LM lm; lm = new_focus->parent->v.list->lm; lm_redraw_row((LM_DATA *)lm, new_focus->v.cell.row, FALSE); if ( ((LM_DATA *)lm)->txt != NULL ) txt_redraw(((LM_DATA *)lm)->txt, FALSE); } } return TRUE; } /* ----------------------------------------------------------------------- */ /* move_focus_internal */ /* ----------------------------------------------------------------------- */ /* This function attempts to move the focus to the object indicated, returning TRUE if successful, FALSE if refused. This function will set or remove the focus from any low-level editing modules as necessary. If make_callbacks is TRUE, then XI callbacks will be issued to determine whether the focus change should be allowed before proceeding. */ BOOLEAN xi_move_focus_internal(XI_OBJ *xi_obj, BOOLEAN make_callbacks, BOOLEAN next_if_disabled, int check_for_reenabled) { XI_OBJ* focus_obj; XI_ITF_DATA* itf_data; LM_DATA* lmp = NULL; BOOLEAN focus_was_on_invisible = FALSE; itf_data = xi_obj->itf->v.itf; focus_obj = itf_data->focus_obj; if (xi_compare_objs( focus_obj, xi_obj )) return(TRUE); itf_data->moving_focus = TRUE; if (focus_obj && focus_obj->type == XIT_CELL) { XI_OBJ *list_obj; list_obj = focus_obj->parent; lmp = (LM_DATA *)(list_obj->v.list->lm); focus_was_on_invisible = lm_list_is_about_to_lose_focus(lmp); } if (!perform_move_focus( focus_obj, xi_obj, make_callbacks, next_if_disabled, check_for_reenabled )) { itf_data->moving_focus = FALSE; if (focus_was_on_invisible) lm_list_did_not_lose_focus(lmp); return FALSE; } if (focus_was_on_invisible) lm_list_did_lose_focus(lmp); if (make_callbacks) { XI_EVENT event; MEMCLEAR(event); event.type = XIE_POST_NAVIGATION; call_cb(xi_obj->itf, &event); } itf_data->moving_focus = FALSE; return(TRUE); } static void near xi_set_interface_window(XI_OBJ *xi_obj) { WINDOW win; #if XIWS != PMWS WINDOW itf_win; itf_win = xi_obj->itf->v.itf->xvt_win; #endif win = xvt_scr_get_focus_vobj(); while (win != xi_obj->itf->v.itf->xvt_win) { if (win == NULL_WIN) return; win = xvt_vobj_get_parent(win); } /* TODO we have a problem here. If we call xvt_R3_set_front_window here, then OS/2 quits generating E_CONTROL events. If we don't call xvt_R3_set_front_window here, then the vertical scroll bar retains the keyboard focus after scrolling. */ #if XIWS != PMWS xvt_scr_set_focus_vobj(itf_win); xvt_vobj_raise(itf_win); #endif } BOOLEAN xi_move_focus(XI_OBJ *xi_obj) { XI_OBJ *list_obj; LM_DATA* lmp = NULL; if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL || (xi_get_attrib(xi_obj) & XI_ATR_VISIBLE)) { if (xi_obj->type == XIT_CELL) { list_obj = xi_obj->parent; lmp = (LM_DATA *)(list_obj->v.list->lm); if (CELL_IS_SELECTABLE((LM)lmp, xi_obj->v.cell.row, xi_obj->v.cell.column)) return FALSE; } xi_set_interface_window(xi_obj); return xi_move_focus_internal(xi_obj, TRUE, FALSE, 0); } return FALSE; } void xi_set_focus(XI_OBJ *xi_obj) { XI_OBJ *list_obj; LM_DATA* lmp = NULL; if ( xi_obj->type == XIT_ITF || xi_obj->type == XIT_CELL || (xi_get_attrib(xi_obj) & XI_ATR_VISIBLE)) { if (xi_obj->type == XIT_CELL) { list_obj = xi_obj->parent; lmp = (LM_DATA *)(list_obj->v.list->lm); if (CELL_IS_SELECTABLE((LM)lmp, xi_obj->v.cell.row, xi_obj->v.cell.column)) return; } xi_set_interface_window(xi_obj); xi_move_focus_internal(xi_obj, FALSE, FALSE, 0); } } static void near xi_add_to_parent_list(XI_OBJ *obj, int position) { XI_OBJ *parent; if ((parent = obj->parent) == NULL) return; realloc_ptrs((void * * *)&parent->children, parent->nbr_children, parent); if (position == -1) parent->children[parent->nbr_children] = obj; else { int i; for (i = parent->nbr_children; i > position; --i) parent->children[i] = parent->children[i - 1]; parent->children[position] = obj; } parent->nbr_children++; } static void xi_stx_cb(STX_CB_DATA *stx_cb_data) { XI_EVENT xiev; BOOLEAN send_cb; XI_OBJ *xi_obj; xi_obj = xiev.v.xi_obj = (XI_OBJ *)stx_get_app_data(stx_cb_data->stx); xiev.refused = FALSE; switch(stx_cb_data->cb_type) { case STX_CB_CHAR: /* generate an XIE_CHAR_FIELD */ xiev.type = XIE_CHAR_FIELD; xiev.v.chr.xi_obj = xi_obj; xiev.v.chr.ch = stx_cb_data->v.chr.ch; xiev.v.chr.shift = stx_cb_data->v.chr.shift; xiev.v.chr.control = stx_cb_data->v.chr.control; xiev.v.chr.is_paste = stx_cb_data->v.chr.is_paste; send_cb = TRUE; break; case STX_CB_CHANGE: /* generate an XIE_CHG_FIELD */ xiev.type = XIE_CHG_FIELD; send_cb = TRUE; break; case STX_CB_FOCUS: stx_cb_data->v.refused = !xi_move_focus_internal(xi_obj, TRUE, TRUE, 0); send_cb = FALSE; break; case STX_CB_DBL: xiev.type = XIE_DBL_FIELD; send_cb = TRUE; break; default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20008", 20008, "XI: unknown STX callback"); } if (send_cb) call_cb(xi_obj->itf, &xiev); if (stx_cb_data->cb_type == STX_CB_CHAR) { stx_cb_data->v.chr.ch = xiev.v.chr.ch; stx_cb_data->v.chr.refused = xiev.refused; } } static void xi_lm_cb(LM_CB_DATA *lm_cb_data) { XI_EVENT xiev; BOOLEAN send_cb = FALSE; XI_OBJ *lm_obj; XI_OBJ *next_obj; XI_LIST_DATA *ldata; LM_DATA *lmp; MEMCLEAR(xiev); lm_obj = (XI_OBJ *)lm_get_list_obj(lm_cb_data->lm); lmp = (LM_DATA *)lm_obj->v.list->lm; ldata = lm_obj->v.list; xiev.v.xi_obj = ldata->focus_cell; next_obj = get_non_focus_cell_obj(ldata); switch(lm_cb_data->cb_type) { case LM_CB_CHAR: /* generate an XIE_CHAR_CELL */ xiev.type = XIE_CHAR_CELL; xiev.v.chr.xi_obj = ldata->focus_cell; xiev.v.chr.ch = lm_cb_data->v.chr.ch; xiev.v.chr.shift = lm_cb_data->v.chr.shift; xiev.v.chr.control = lm_cb_data->v.chr.control; xiev.v.chr.is_paste = lm_cb_data->v.chr.is_paste; send_cb = TRUE; break; case LM_CB_CHANGE: xiev.type = XIE_CHG_CELL; send_cb = TRUE; break; case LM_CB_FOCUS: case LM_CB_CELL_BTN: { BOOLEAN ref; XI_OBJ *focus_obj; focus_obj = xi_get_focus(lm_obj->itf); next_obj->v.cell.row = (unsigned char)lm_cb_data->row; next_obj->v.cell.column = (unsigned char)lm_cb_data->column; next_obj->v.cell.is_vert_scrolled = FALSE; ref = FALSE; if (focus_obj && focus_obj->type == XIT_CELL && next_obj->type == XIT_CELL) { if (focus_obj->parent != next_obj->parent || focus_obj->v.cell.row != next_obj->v.cell.row || focus_obj->v.cell.column != next_obj->v.cell.column) { if (!xi_move_focus_internal(next_obj, TRUE, FALSE, 0)) if (lm_cb_data->cb_type == LM_CB_FOCUS) ref = lm_cb_data->v.refused = TRUE; } } else if (!xi_move_focus_internal(next_obj, TRUE, FALSE, 0)) if (lm_cb_data->cb_type == LM_CB_FOCUS) ref = lm_cb_data->v.refused = TRUE; next_obj = get_non_focus_cell_obj(ldata); next_obj->v.cell.row = (unsigned char)(lm_cb_data->row); next_obj->v.cell.column = (unsigned char)(lm_cb_data->column); send_cb = FALSE; if ((! ref) && (lm_cb_data->cb_type == LM_CB_CELL_BTN)) { xiev.type = XIE_BUTTON; xiev.v.xi_obj = next_obj; send_cb = TRUE; } break; } case LM_CB_DBL: xiev.type = XIE_DBL_CELL; send_cb = TRUE; break; case LM_CB_TEXT: xiev.type = XIE_CELL_REQUEST; xiev.v.cell_request.list = lm_obj; xiev.v.cell_request.s = lm_cb_data->v.text.text; xiev.v.cell_request.len = lm_cb_data->v.text.len; xiev.v.cell_request.col_nbr = lm_cb_data->column; xiev.v.cell_request.rec = lm_cb_data->rec; xiev.v.cell_request.icon_rid = lm_cb_data->v.text.icon_rid; xiev.v.cell_request.attrib = lm_cb_data->v.text.attrib; xiev.v.cell_request.color = lm_cb_data->v.text.color; xiev.v.cell_request.back_color = lm_cb_data->v.text.back_color; xiev.v.cell_request.records = &lmp->recs[0]; send_cb = TRUE; break; case LM_CB_REC_ALLOCATE: xiev.type = XIE_REC_ALLOCATE; xiev.v.rec_allocate.list = lm_obj; xiev.v.rec_allocate.record = lm_cb_data->v.rec_allocate.record; send_cb = TRUE; break; case LM_CB_REC_FREE: xiev.type = XIE_REC_FREE; xiev.v.rec_free.list = lm_obj; xiev.v.rec_free.record = lm_cb_data->v.rec_free.record; send_cb = TRUE; break; case LM_CB_GET_FIRST: case LM_CB_GET_NEXT: case LM_CB_GET_PREV: case LM_CB_GET_LAST: switch (lm_cb_data->cb_type) { case LM_CB_GET_FIRST: xiev.type = XIE_GET_FIRST; break; case LM_CB_GET_NEXT: xiev.type = XIE_GET_NEXT; break; case LM_CB_GET_PREV: xiev.type = XIE_GET_PREV; break; case LM_CB_GET_LAST: xiev.type = XIE_GET_LAST; break; } xiev.v.rec_request.list = lm_obj; xiev.v.rec_request.spec_rec = lm_cb_data->v.rec_request.spec_rec; xiev.v.rec_request.data_rec = lm_cb_data->v.rec_request.data_rec; xiev.v.rec_request.percent = lm_cb_data->v.rec_request.percent; xiev.v.rec_request.attrib = lm_cb_data->v.rec_request.attrib; xiev.v.rec_request.color = lm_cb_data->v.rec_request.color; send_cb = TRUE; break; case LM_CB_GET_PERCENT: xiev.type = XIE_GET_PERCENT; xiev.v.get_percent.list = lm_obj; xiev.v.get_percent.record = lm_cb_data->v.get_percent.record; send_cb = TRUE; break; case LM_CB_SELECT: { if (lm_cb_data->row == 255 && lm_cb_data->column == 255) { xiev.type = XIE_SELECT; xiev.v.select.xi_obj = lm_obj; xiev.v.select.selected = TRUE; xiev.v.select.dbl_click = FALSE; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.records = &lmp->recs[0]; xiev.v.select.column = 0; send_cb = TRUE; } else if (lm_cb_data->row == 255) { xiev.type = XIE_SELECT; xiev.v.select.xi_obj = lm_obj->children[lm_cb_data->column]; xiev.v.select.selected = lm_cb_data->v.select.selected; xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.column = lm_cb_data->column; xiev.v.select.records = &lmp->recs[0]; send_cb = TRUE; } else { XI_OBJ row_obj; XI_MAKE_ROW(&row_obj, lm_obj, lm_cb_data->row); xiev.type = XIE_SELECT; xiev.v.select.xi_obj = &row_obj; xiev.v.select.selected = lm_cb_data->v.select.selected; xiev.v.select.dbl_click = lm_cb_data->v.select.dbl_click; xiev.v.select.shift = lm_cb_data->v.select.shift; xiev.v.select.control = lm_cb_data->v.select.control; xiev.v.select.column = lm_cb_data->column; xiev.v.select.records = &lmp->recs[0]; send_cb = TRUE; } break; } case LM_CB_ROW_SIZE: { XI_OBJ row_obj; XI_MAKE_ROW(&row_obj, lm_obj, lm_cb_data->row); xiev.type = XIE_ROW_SIZE; xiev.v.row_size.xi_obj = &row_obj; xiev.v.row_size.new_row_height = lm_cb_data->v.row_size.new_row_height; send_cb = TRUE; break; } case LM_CB_COL_DELETE: xiev.type = XIE_COL_DELETE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; send_cb = TRUE; break; case LM_CB_COL_MOVE: xiev.type = XIE_COL_MOVE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; xiev.v.column.new_col_nbr = lm_cb_data->v.column.new_col_nbr; xiev.v.column.in_fixed = lm_cb_data->v.column.in_fixed; send_cb = TRUE; break; case LM_CB_COL_SIZE: xiev.type = XIE_COL_SIZE; xiev.v.column.list = lm_obj; xiev.v.column.col_nbr = lm_cb_data->column; xiev.v.column.new_col_width = lm_cb_data->v.column.new_col_width; xiev.v.column.new_col_pixel_width = lm_cb_data->v.column.new_col_pixel_width; send_cb = TRUE; break; default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20009", 20009, "XI: unknown LM callback"); } if (send_cb) call_cb(lm_obj->itf, &xiev); if (lm_cb_data->cb_type == LM_CB_CHAR) { lm_cb_data->v.chr.refused = xiev.refused; lm_cb_data->v.chr.ch = xiev.v.chr.ch; } if (lm_cb_data->cb_type == LM_CB_SELECT) lm_cb_data->v.select.refused = xiev.refused; if (lm_cb_data->cb_type == LM_CB_ROW_SIZE) lm_cb_data->v.row_size.refused = xiev.refused; if (lm_cb_data->cb_type == LM_CB_TEXT) { lm_cb_data->v.text.icon_rid = xiev.v.cell_request.icon_rid; lm_cb_data->v.text.attrib = xiev.v.cell_request.attrib; lm_cb_data->v.text.color = xiev.v.cell_request.color; lm_cb_data->v.text.back_color = xiev.v.cell_request.back_color; lm_cb_data->v.text.font = xiev.v.cell_request.font; lm_cb_data->v.text.font_id = xiev.v.cell_request.font_id; lm_cb_data->v.text.button = xiev.v.cell_request.button; lm_cb_data->v.text.button_on_left = xiev.v.cell_request.button_on_left; lm_cb_data->v.text.button_on_focus = xiev.v.cell_request.button_on_focus; lm_cb_data->v.text.button_icon_rid = xiev.v.cell_request.button_icon_rid; } if (lm_cb_data->cb_type == LM_CB_GET_PERCENT) lm_cb_data->v.get_percent.percent = xiev.v.get_percent.percent; if (lm_cb_data->cb_type == LM_CB_REC_ALLOCATE) lm_cb_data->v.rec_allocate.record = xiev.v.rec_allocate.record; switch (lm_cb_data->cb_type) { case LM_CB_GET_FIRST: case LM_CB_GET_NEXT: case LM_CB_GET_PREV: case LM_CB_GET_LAST: lm_cb_data->v.rec_request.data_rec = xiev.v.rec_request.data_rec; lm_cb_data->v.rec_request.attrib = xiev.v.rec_request.attrib; lm_cb_data->v.rec_request.color = xiev.v.rec_request.color; lm_cb_data->v.rec_request.row_height = xiev.v.rec_request.row_height; lm_cb_data->v.rec_request.refused = xiev.refused; lm_cb_data->v.rec_request.has_focus = xiev.v.rec_request.has_focus; break; case LM_CB_COL_DELETE: case LM_CB_COL_MOVE: case LM_CB_COL_SIZE: lm_cb_data->v.column.refused = xiev.refused; break; } } /* This queue is more of a stack than a queue but event ordering is not important. This function is used to queue up events for later processing to avoid recursive callbacks at bad times. For example, XIE_INIT is queued up during interface creation. */ static void near xi_enqueue(XI_EVENT *xiev, XI_OBJ *itf) { XI_EQ* xi_el; xi_el = (XI_EQ *)xi_tree_malloc(sizeof(XI_EQ), NULL); xi_el->xiev = *xiev; xi_el->itf = itf; xi_el->next = NULL; if (xi_eq == NULL) xi_eq = xi_el; else { XI_EQ* last = xi_eq; while (last->next != NULL) last = last->next; last->next = xi_el; } } /* ------------------------------------------------------------------------- */ /* remove all events associated with an interface from the que */ /* ------------------------------------------------------------------------- */ static void xi_que_remove( XI_OBJ* itf ) { XI_EQ* current; XI_EQ* last; last = NULL; current = xi_eq; while (current != NULL) { if (current->itf != itf) { last = current; current = current->next; } else { XI_EQ* next = current->next; if (last == NULL) xi_eq = next; else last->next = next; xi_tree_free( current ); current = next; } } } /* This function will dequeue all events queued up via xi_enqueue. This function is called at the end of xi_event, so that any events that were queued would be flushed out at that time. */ void xi_dequeue(void) { XI_EQ *xi_el; XI_OBJ * *objp; XI_OBJ *editable; int i; static BOOLEAN inside; /* avoid recursive calls */ if (inside) return; inside = TRUE; while (xi_eq != NULL) { xi_el = xi_eq; call_cb(xi_el->itf, &xi_el->xiev); if (xi_el == xi_eq) { xi_eq = xi_eq->next; if (xi_el->xiev.type == XIE_INIT) { /* fill in all lists */ for (objp = xi_el->itf->children, i = xi_el->itf->nbr_children; i != 0; i--, objp++) { if ((*objp)->type == XIT_LIST) { if (! (*objp)->v.list->done_initial_xi_scroll) { if (xi_get_attrib(*objp) & XI_ATR_VISIBLE) { (*objp)->v.list->done_initial_xi_scroll = TRUE; xi_scroll_internal(*objp, XI_SCROLL_FIRST, (*objp)->v.list->start_percent, FALSE ); } } } } editable = xi_search_itf(xi_el->itf, XI_SEARCH_FOR_FOCUSABLE, 0); if (editable) xi_move_focus_internal(editable, TRUE, FALSE, 0); } xi_tree_free((char *)xi_el); } } inside = FALSE; } /* xi_add_window_to_list: Record a window as being an XI window, so that XI can tell its windows apart from other windows. */ static void near xi_add_window_to_list(WINDOW win, XI_OBJ *itf) { XI_WINDOW_LIST *list; /* list_parent is the tree memory parent of all structures in the linked list of windows. It is used to avoid clogging up the FIRSTNODE's child list too much. */ if (list_parent == NULL) list_parent = (char *)xi_tree_malloc(1, NULL); list = (XI_WINDOW_LIST *)xi_tree_malloc(sizeof(XI_WINDOW_LIST), list_parent); list->next = xi_window_list; list->win = win; list->itf = itf; xi_window_list = list; } void xi_remove_window_from_list(WINDOW win) { XI_WINDOW_LIST *list; XI_WINDOW_LIST *next; if (win == xi_window_list->win) { list = xi_window_list; xi_window_list = xi_window_list->next; xi_que_remove( list->itf ); xi_tree_free(list); if (xi_window_list == NULL) { xi_tree_free(list_parent); list_parent = NULL; } return; } else { for (list = xi_window_list; list != NULL && (next = list->next) != NULL; list = next) { if (next->win == win) { list->next = next->next; xi_que_remove( next->itf ); xi_tree_free(next); return; } } } xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20004", 20004, "Internal XI error"); } /* find an interface from its id */ XI_OBJ *xi_get_itf_from_id( int id ) { XI_WINDOW_LIST *list; list = xi_window_list; while (list != NULL && list->itf->cid != id) list = list->next; if (list == NULL) return NULL; return list->itf; } BOOLEAN xi_is_window(WINDOW win) { register XI_WINDOW_LIST *list; for (list = xi_window_list; list != NULL; list = list->next) if (list->win == win) return TRUE; return FALSE; } BOOLEAN xi_is_itf(XI_OBJ *itf) { register XI_WINDOW_LIST *list; for (list = xi_window_list; list != NULL; list = list->next) if (list->itf == itf) return TRUE; return FALSE; } BOOLEAN xi_is_changed( XI_OBJ* obj ) { return obj->itf->v.itf->chg_flag; } XI_OBJ * xi_get_itf(WINDOW win) { XI_WINDOW_LIST *next; for (next = xi_window_list; next != NULL; next = next->next) if (next->win == win) { return next->itf; } return NULL; } /* ------------------------------------------------------------------------ */ /* create_children */ /* ------------------------------------------------------------------------ */ static XI_OBJ * xi_create_internal( XI_OBJ * parent, XI_OBJ_DEF* xi_obj_def, BOOLEAN creating_list ); static void create_children( XI_OBJ_DEF* xi_obj_def, XI_OBJ* obj, BOOLEAN creating_list ) { XI_OBJ_DEF * * child; int i; /* create children of the object if there are any */ child = xi_obj_def->children; for (i = 0; i < xi_obj_def->nbr_children; child++, i++) /* xi_create automatically adds object to the parent list */ xi_create_internal(obj, *child, creating_list ); } /* ------------------------------------------------------------------------ */ /* create_interface */ /* ------------------------------------------------------------------------ */ static void interface_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* itf ) { static BOOLEAN first_itf = TRUE; XI_ITF_DATA * itf_data; XI_ITF_DEF * itf_def; RCT def_rct; RCT * rctp; RCT rct; WINDOW itf_win; BOOLEAN do_move_window = FALSE; XI_EVENT xiev; itf_def = xi_obj_def->v.itf; rctp = itf_def->rctp; xi_get_def_rect(xi_obj_def, &def_rct); def_rct.left = 12; def_rct.right += 12; if (rctp == NULL || rctp->top == rctp->bottom) { rct = def_rct; if (rctp) xvt_rect_offset(&rct, rctp->left, rctp->top); } else rct = *rctp; itf_data = (XI_ITF_DATA *)xi_tree_malloc(sizeof(XI_ITF_DATA), (char *)itf); itf_data->xi_eh = itf_def->xi_eh; itf_data->half_baked = TRUE; itf_data->edit_menu = itf_def->edit_menu; itf_data->back_color = itf_def->back_color; itf_data->automatic_back_color = itf_def->automatic_back_color; if (itf_def->automatic_back_color) { #if (XIWS == XOLWS) itf_data->back_color = COLOR_GRAY; #else if (xi_get_pref(XI_PREF_3D_LOOK)) itf_data->back_color = COLOR_LTGRAY; else itf_data->back_color = COLOR_WHITE; #endif } itf_data->virtual_itf = itf_def->virtual_itf; itf_data->modal = itf_def->modal; itf_data->size_font_to_win = itf_def->size_font_to_win; itf_data->tab_on_enter = itf_def->tab_on_enter; itf_data->prev_modal = NULL_WIN; itf->v.itf = itf_data; itf_data->use_xil_win = itf_def->use_xil_win; if (itf_def->font_id) { itf_data->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ), itf_data); *itf_data->font = xi_create_copy_font_id(itf->itf, itf_def->font_id, 0); } itf_data->fu_height = xi_get_fu_height_font( itf_data->font ? itf_data->font : &xi_sysfont); itf_data->fu_width = xi_get_fu_width_font( itf_data->font ? itf_data->font : &xi_sysfont); itf_data->max_xi_pnt.h = def_rct.right - def_rct.left; itf_data->max_xi_pnt.v = def_rct.bottom - def_rct.top; xi_pu_to_fu(itf->itf, &itf_data->max_xi_pnt, 1); xi_even_fu_pnt(&itf_data->max_xi_pnt); itf_data->menu_win = itf_def->menu_win; if (itf_def->win) { itf_data->xvt_win = itf_def->win; itf_win = itf_def->win; if (itf_def->size_win) do_move_window = TRUE; } else { WIN_TYPE win_type; WINDOW parent; win_type = W_DOC; parent = NULL_WIN; if (itf_data->modal) { parent = SCREEN_WIN; #if XIWS == WINWS xvt_vobj_set_attr(0, ATTR_WIN_POPUP_DETACHED, TRUE); #endif } if (rct.top < xi_get_pref(XI_PREF_ITF_MIN_TOP)) { int delta; delta = (int)xi_get_pref(XI_PREF_ITF_MIN_TOP) - rct.top; rct.top += delta; rct.bottom += delta; } if (rct.left < xi_get_pref(XI_PREF_ITF_MIN_LEFT)) { int delta; delta = (int)xi_get_pref(XI_PREF_ITF_MIN_LEFT) - rct.left; rct.left += delta; rct.right += delta; } itf_data->xvt_win = xi_new_child_window(&rct, itf_def->title, win_type, itf_def->ctl_size, itf_def->ctl_vscroll, itf_def->ctl_hscroll, itf_def->ctl_close, itf_def->ctl_iconized, itf_def->ctl_iconizable, parent, PTR_LONG(itf), 0, 0L, TRUE, TRUE, itf_def->menu_bar_rid); if (itf_data->modal) { if (xi_modal_win != NULL_WIN) { /* Nested modal */ itf_data->prev_modal = xi_modal_win; #if (XIWS == WINWS) || (XIWS == PMWS) xvt_vobj_set_enabled(xi_modal_win, FALSE); #endif #if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS) xvt_vobj_set_enabled(xi_modal_win, FALSE); #if XIWS == MACWS xvt_scr_set_focus_vobj( itf_data->xvt_win ); xvt_vobj_raise( itf_data->xvt_win ); #endif #endif xi_modal_win = itf_data->xvt_win; } else { #if (XIWS == WINWS) || (XIWS == PMWS) xvt_vobj_set_enabled(TASK_WIN, FALSE); #endif xi_modal_win = itf_data->xvt_win; #if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS) { SLIST win_list = xvt_scr_list_wins(); SLIST_ELT elt; for (elt = xvt_slist_get_first(win_list); elt != NULL; elt = xvt_slist_get_next(win_list, elt)) { if ((WINDOW)*xvt_slist_get_data(elt) != xi_modal_win) { xvt_vobj_set_enabled((WINDOW)*xvt_slist_get_data(elt), FALSE); } } xvt_slist_destroy(win_list); } #endif } } itf_win = itf_data->xvt_win; itf_data->win_xi_pnt.v = rct.bottom - rct.top; itf_data->win_xi_pnt.h = rct.right - rct.left; xi_pu_to_fu(itf->itf, &itf_data->win_xi_pnt, 1); xi_even_fu_pnt(&itf_data->win_xi_pnt); } xvt_vobj_get_client_rect(itf_win, &itf_data->original_win_rct); if (itf_data->font) itf_data->original_font_size = (int)xvt_font_get_size(*itf_data->font); xi_add_window_to_list(itf_data->xvt_win, itf); if (xi_get_pref(XI_PREF_USE_APP_DATA)) xvt_vobj_set_data(itf_data->xvt_win, PTR_LONG(itf)); if (itf_data->virtual_itf) { xi_adjust_sb_vir_itf(itf_win, itf); xvt_sbar_set_range(itf_data->xvt_win, HSCROLL, 0, 100); xvt_sbar_set_range(itf_data->xvt_win, VSCROLL, 0, 100); } first_itf = FALSE; xi_add_to_parent_list(itf, -1); #if XI_IS_CH CTOS_IS_CH; xi_coalesce_invalidates(itf, TRUE); CTOS_END; #endif create_children( xi_obj_def, itf, FALSE ); /* queue up initialization event */ xiev.type = XIE_INIT; xiev.v.xi_obj = itf; xi_enqueue(&xiev, itf); #if XI_IS_CH CTOS_IS_CH; xi_coalesce_invalidates(itf, FALSE); CTOS_END; #endif if (do_move_window) xvt_vobj_move(itf_win, &rct); } /* ------------------------------------------------------------------------ */ /* assign rectangles */ /* ------------------------------------------------------------------------ */ static void assign_rectangles( XI_OBJ* itf, XI_RCT* dest_form_rect, XI_RCT* dest_pixel_rect, XI_RCT* source_form_rect, XI_RCT* source_pixel_rect ) { if (source_pixel_rect->left || source_pixel_rect->right || source_pixel_rect->top || source_pixel_rect->bottom ) { *dest_pixel_rect = *dest_form_rect = *source_pixel_rect; xi_pu_to_fu( itf, (PNT *)dest_form_rect, 2); } else { *dest_pixel_rect = *dest_form_rect = *source_form_rect; xi_fu_to_pu(itf, (PNT *)dest_pixel_rect, 2); } } /* ------------------------------------------------------------------------ */ /* container_create */ /* ------------------------------------------------------------------------ */ static void container_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* container ) { XI_CONTAINER_DEF* cdef; XI_OBJ_DEF* child; XI_CONTAINER_DATA* cdata; int i, len, max_len; XI_BTN_TYPE button_type; xvt_errmsg_sig_if(!(xi_obj_def->nbr_children > 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20011", 20011, "Can't create empty container"); max_len = 0; for (i = 0; i < xi_obj_def->nbr_children; ++i) { child = xi_obj_def->children[i]; xvt_errmsg_sig_if(!(child->type == XIT_BTN), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20012", 20012, "Containers can only contain buttons"); if (i ==0) button_type = child->v.btn->type; else xvt_errmsg_sig_if(!(child->v.btn->type == button_type), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20013", 20013, "Can't mix button types in a container"); if ((len = (int)strlen(child->v.btn->text)) > max_len) max_len = len; } cdef = xi_obj_def->v.container; cdata = (XI_CONTAINER_DATA *) xi_tree_malloc(sizeof(XI_CONTAINER_DATA), (char *)container); assign_rectangles( container->itf, &cdata->xi_rct, &cdata->rct, &cdef->xi_rct, &cdef->pixel_rect ); cdata->orientation = cdef->orientation; cdata->tab_cid = cdef->tab_cid; cdata->btn_height = cdef->btn_height; cdata->btn_width = cdef->btn_width; cdata->nbr_buttons = xi_obj_def->nbr_children; cdata->packed = cdef->packed; container->v.container = cdata; xi_container_rect_calc(container, max_len, button_type); xi_add_to_parent_list( container, -1); create_children( xi_obj_def, container, FALSE ); } /* ------------------------------------------------------------------------ */ /* rectangle_create */ /* ------------------------------------------------------------------------ */ static void rectangle_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* rectangle ) { XI_RECT_DATA *rect_data; XI_RECT_DEF *rect_def = xi_obj_def->v.rect; rect_data = (XI_RECT_DATA *)xi_tree_malloc(sizeof(XI_RECT_DATA), rectangle); rect_data->fore_color = rect_def->fore_color; rect_data->back_color = rect_def->back_color; rect_data->hilight_color = rect_def->hilight_color; rect_data->shadow_color = rect_def->shadow_color; rect_data->well = rect_def->well; rect_data->ridge = rect_def->ridge; rect_data->attrib = rect_def->attrib; #if XI_IS_CH CTOS_IS_CH; { RCT rct; rect_data->xi_rct = rect_def->xi_rct; rct = rect_def->xi_rct; rct.top = (rct.top / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; rct.left = (rct.left / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; rct.bottom = ((rct.bottom + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; rct.right = ((rct.right + XI_FU_MULTIPLE / 2) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; rect_data->rct = rct; } CTOS_END; #endif #if XI_IS_NOT_CH CTOS_IS_PM; assign_rectangles( rectangle->itf, &rect_data->xi_rct, &rect_data->rct, &rect_def->xi_rct, &rect_def->pixel_rect ); CTOS_END; #endif rectangle->v.rect = rect_data; #if XI_IS_CH xi_invalidate_rect( rectangle->itf->v.itf->xvt_win, &rct); #endif xi_add_to_parent_list(rectangle, -1); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20050", 20050, "xi_create: Rectangles cannot have children"); } /* ------------------------------------------------------------------------ */ /* line_create */ /* ------------------------------------------------------------------------ */ static void line_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* line ) { XI_LINE_DATA *line_data; XI_LINE_DEF *line_def = xi_obj_def->v.line; PNT pnt1, pnt2; RCT rct; line_data = (XI_LINE_DATA *)xi_tree_malloc( sizeof(XI_LINE_DATA), line); line_data->fore_color = line_def->fore_color; line_data->well = line_def->well; line_data->attrib = line_def->attrib; if ( line_def->pixel_pnt1.h || line_def->pixel_pnt1.v || line_def->pixel_pnt2.h || line_def->pixel_pnt2.v ) { pnt1 = line_def->pixel_pnt1; pnt2 = line_def->pixel_pnt2; line_data->xi_pnt1 = pnt1; line_data->xi_pnt2 = pnt2; xi_pu_to_fu(line->itf, &line_data->xi_pnt1, 1); xi_pu_to_fu(line->itf, &line_data->xi_pnt2, 1); } else { pnt1 = line_def->pnt1; pnt2 = line_def->pnt2; line_data->xi_pnt1 = pnt1; line_data->xi_pnt2 = pnt2; #if XI_IS_CH CTOS_IS_CH; pnt1.h = (pnt1.h / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; pnt1.v = (pnt1.v / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; pnt2.h = (pnt2.h / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; pnt2.v = (pnt2.v / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; CTOS_END; #endif #if XI_IS_NOT_CH CTOS_IS_PM; xi_fu_to_pu(line->itf, &pnt1, 1); xi_fu_to_pu(line->itf, &pnt2, 1); CTOS_END; #endif } line_data->pnt1 = pnt1; line_data->pnt2 = pnt2; line->v.line = line_data; rct.top = min(pnt1.v, pnt2.v); rct.left = min(pnt1.h, pnt2.h); rct.bottom = max(pnt1.v, pnt2.v); rct.right = max(pnt1.h, pnt2.h); xi_invalidate_rect( line->itf->v.itf->xvt_win, &rct); xi_add_to_parent_list(line, -1); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20051", 20051, "xi_create: Lines cannot have children"); } /* ------------------------------------------------------------------------ */ /* button_create */ /* ------------------------------------------------------------------------ */ static void button_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* button ) { XI_BTN_DATA *btn_data; XI_BTN_DEF *btn_def = xi_obj_def->v.btn; RCT rct; WINDOW itf_win; itf_win = button->itf->v.itf->xvt_win; btn_data = (XI_BTN_DATA *) xi_tree_malloc(sizeof(XI_BTN_DATA), button); btn_data->attrib = btn_def->attrib; btn_data->tab_cid = btn_def->tab_cid; btn_data->dflt = btn_def->dflt; btn_data->down_icon_rid = btn_def->down_icon_rid; btn_data->up_icon_rid = btn_def->up_icon_rid; btn_data->disabled_icon_rid = btn_def->disabled_icon_rid; btn_data->icon_x = btn_def->icon_x; btn_data->icon_y = btn_def->icon_y; btn_data->text = (char *) xi_tree_malloc(strlen(btn_def->text) + 1, btn_data); btn_data->checked = btn_def->checked; btn_data->type = btn_def->type; btn_data->fore_color = btn_def->fore_color; btn_data->drawable = btn_def->drawable; strcpy(btn_data->text, btn_def->text); assign_rectangles( button->itf, &btn_data->xi_rct, &btn_data->rct, &btn_def->xi_rct, &btn_def->pixel_rect ); button->v.btn = btn_data; xi_button_rect_calc(button, button->parent->nbr_children); rct = btn_data->rct; if (! (BOOLEAN)xi_get_pref(XI_PREF_NATIVE_CTRLS)) xi_invalidate_rect(itf_win, &rct); else { WIN_TYPE type; switch (btn_def->type) { case XIBT_BUTTON: case XIBT_BUTTON_CHECKBOX: case XIBT_BUTTON_RADIOBTN: type = WC_PUSHBUTTON; break; case XIBT_RADIOBTN: case XIBT_TABBTN: type = WC_RADIOBUTTON; break; case XIBT_CHECKBOX: type = WC_CHECKBOX; break; } btn_data->btnctl = xi_new_control(&rct, btn_def->text, type, itf_win, (BOOLEAN)((btn_def->attrib & XI_ATR_VISIBLE) != 0), xi_obj_def->cid, NULL); if ((btn_def->attrib & XI_ATR_ENABLED) == 0) xvt_vobj_set_enabled(btn_data->btnctl, FALSE); if (btn_def->checked && type == WC_CHECKBOX) xvt_ctl_set_checked(btn_data->btnctl, TRUE); } xi_add_to_parent_list(button, -1); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20052", 20052, "xi_create: Buttons cannot have children"); } /* ------------------------------------------------------------------------ */ /* form_create */ /* ------------------------------------------------------------------------ */ static void form_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* form ) { XI_FORM_DATA *form_data; XI_FORM_DEF *form_def; form_def = xi_obj_def->v.form; form_data = (XI_FORM_DATA *) xi_tree_malloc(sizeof(XI_FORM_DATA), (char *)form); form_data->attrib = XI_ATR_VISIBLE | XI_ATR_ENABLED; form_data->tab_cid = form_def->tab_cid; form->v.form = form_data; xi_add_to_parent_list(form, -1); create_children( xi_obj_def, form, FALSE ); } /* ------------------------------------------------------------------------ */ /* field_create */ /* ------------------------------------------------------------------------ */ static void field_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* field ) { STX_DEF stxdef; XI_FIELD_DATA * field_data; XI_FIELD_DEF * xi_fd; int btn_dim_x; int btn_dim_x2; int fu_width; int fu_height; int edit_height; int btn_space; WINDOW itf_win; int leading, ascent, descent, font_height; itf_win = field->itf->v.itf->xvt_win; fu_width = xi_get_fu_width(field->itf); fu_height = xi_get_fu_height(field->itf); btn_dim_x = (fu_height * XI_FU_MULTIPLE) / 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; btn_dim_x = (int)(((long)btn_dim_x * fu_width) / XI_FU_MULTIPLE); btn_dim_x2 = (int) (((long)btn_dim_x2 * fu_width) / XI_FU_MULTIPLE); MEMCLEAR(stxdef); stxdef.cid = xi_obj_def->cid; xi_fd = xi_obj_def->v.field; stxdef.pnt = xi_fd->pixel_origin; if (stxdef.pnt.v == 0 && stxdef.pnt.h == 0) { stxdef.pnt = xi_fd->pnt; xi_fu_to_pu(field->itf, &stxdef.pnt, 1); } stxdef.pixel_width = xi_fd->pixel_width; if (stxdef.pixel_width == 0) stxdef.pixel_width = xi_fd->field_width * fu_width / XI_FU_MULTIPLE; stxdef.xi_rct = xi_fd->xi_rct; field_data = (XI_FIELD_DATA *)xi_tree_malloc(sizeof(XI_FIELD_DATA), (char *)field); if (xi_fd->font_id) { stxdef.font = xi_create_copy_font_id(field->itf, xi_fd->font_id, 0); field_data->font_set = TRUE; } else if (field->itf->v.itf->font) { stxdef.font = *field->itf->v.itf->font; field_data->font_set = TRUE; } else { stxdef.font = xi_sysfont; field_data->font_set = FALSE; } field_data->rct.top = stxdef.pnt.v; field_data->rct.left = stxdef.pnt.h; field_data->rct.right = stxdef.pnt.h + stxdef.pixel_width; field_data->rct.bottom = stxdef.pnt.v + fu_height; xi_set_xvt_font(itf_win, &stxdef.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 (! (xi_fd->xi_rct.top || xi_fd->xi_rct.bottom || xi_fd->xi_rct.left || xi_fd->xi_rct.right)) { if (xi_fd->button) { field_data->btn_rct.top = stxdef.pnt.v; if (xi_fd->button_on_left) { field_data->btn_rct.left = stxdef.pnt.h; field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; if (xi_fd->pixel_button_distance) stxdef.pnt.h = field_data->btn_rct.right + xi_fd->pixel_button_distance; else stxdef.pnt.h += btn_dim_x2; } else { #if XI_IS_CH BOOLEAN b; CTOS_IS_CH; b = (BOOLEAN)(xi_fd->attrib & XI_ATR_BORDER); field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width + (b ? 24 : 8); field_data->btn_rct.right = field_data->btn_rct.left + 8; 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; if (xi_fd->pixel_button_distance) { field_data->btn_rct.left = stxdef.pnt.h + stxdef.pixel_width + xi_fd->pixel_button_distance; field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; } else { int right; right = stxdef.pnt.h + stxdef.pixel_width + btn_dim_x2; /* convert to form units */ right = (int)(((long)right * XI_FU_MULTIPLE) / fu_width ); /* round up to nearest FU multiple */ right = ((right + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; /* convert to pixels */ right = (int)(((long)right * fu_width) / XI_FU_MULTIPLE); field_data->btn_rct.right = right; field_data->btn_rct.left = right - btn_dim_x; } CTOS_END; #endif } } } else { field_data->rct = xi_fd->xi_rct; xi_fu_to_pu(field->itf, (PNT *)&field_data->rct, 2); if (xi_fd->button) { field_data->btn_rct = xi_fd->xi_rct; xi_fu_to_pu(field->itf, (PNT *)&field_data->btn_rct, 2); if (xi_fd->button_on_left) { PNT p; p.h = btn_dim_x2; xi_pu_to_fu(field->itf, &p, 1); field_data->btn_rct.right = field_data->btn_rct.left + btn_dim_x; stxdef.xi_rct.left += p.h; stxdef.xi_rct.right += p.h; } else { int right; right = field_data->btn_rct.right + btn_space + btn_dim_x2; /* convert to form units */ right = (int)(((long)right * XI_FU_MULTIPLE) / fu_width ); /* round up to nearest FU multiple */ right = ((right + XI_FU_MULTIPLE) / XI_FU_MULTIPLE) * XI_FU_MULTIPLE; /* convert to pixels */ right = (int)(((long)right * fu_width) / XI_FU_MULTIPLE); field_data->btn_rct.right = right; field_data->btn_rct.left = right - btn_dim_x; } } } field_data->btn_rct.bottom = field_data->btn_rct.top + edit_height; stxdef.pix_char_width = fu_width; stxdef.attrib = xi_fd->attrib; stxdef.text_size = xi_fd->text_size; stxdef.back_color = xi_fd->back_color; stxdef.enabled_color = xi_fd->enabled_color; stxdef.disabled_color = xi_fd->disabled_color; stxdef.disabled_back_color = xi_fd->disabled_back_color; stxdef.active_color = xi_fd->active_color; stxdef.active_back_color = xi_fd->active_back_color; stxdef.hilight_color = xi_fd->hilight_color; stxdef.shadow_color = xi_fd->shadow_color; stxdef.stx_cb = xi_stx_cb; stxdef.app_data = PTR_LONG(field); stxdef.parent = (char *)field_data; stxdef.well = xi_fd->well; stxdef.platform = xi_fd->platform; stxdef.auto_tab = xi_fd->auto_tab; field_data->stx = stx_create(itf_win, &stxdef); field_data->tab_cid = xi_fd->tab_cid; field_data->button = xi_fd->button; field_data->button_on_left = xi_fd->button_on_left; field_data->icon_rid = xi_fd->icon_rid; field_data->well = xi_fd->well; field_data->platform = xi_fd->platform; field_data->xi_rct = xi_fd->xi_rct; field_data->xi_pnt = xi_fd->pnt; field_data->field_width = xi_fd->field_width; field->v.field = field_data; xi_add_to_parent_list(field, -1); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20053", 20053, "xi_create: Fields cannot have children"); } /* ------------------------------------------------------------------------ */ /* text_create */ /* ------------------------------------------------------------------------ */ static void text_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* text ) { XI_TEXT_DATA *text_data; XI_TEXT_DEF *text_def = xi_obj_def->v.text; text_data = (XI_TEXT_DATA *) xi_tree_malloc(sizeof(XI_TEXT_DATA), text); text_data->attrib = text_def->attrib; assign_rectangles( text->itf, &text_data->xi_rct, &text_data->rct, &text_def->xi_rct, &text_def->pixel_rect ); if (text_def->font_id) { text_data->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ), text_data); *text_data->font = xi_create_copy_font_id(text->itf, text_def->font_id, 0); } text_data->text = (char *)xi_tree_malloc(strlen(text_def->text) + 1, text); strcpy(text_data->text, text_def->text); text_data->fore_color = text_def->fore_color; text_data->back_color = text_def->back_color; text->v.text = text_data; xi_invalidate_rect( text->itf->v.itf->xvt_win, &text_data->rct); xi_add_to_parent_list(text, -1); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20055", 20055, "xi_create: Static text controls cannot have children"); } /* ------------------------------------------------------------------------ */ /* group_create */ /* ------------------------------------------------------------------------ */ static void group_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* group, BOOLEAN creating_list ) { XI_GROUP_DEF *group_def = xi_obj_def->v.group; XI_GROUP_DATA *group_data; group_data = (XI_GROUP_DATA *)xi_tree_malloc( sizeof(XI_GROUP_DATA), group); group_data->nbr_cids = group_def->nbr_cids; group_data->cidlist = (int *)xi_tree_malloc( sizeof(int) * group_def->nbr_cids, group_data); memcpy((char *)group_data->cidlist, (char *)group_def->cids, sizeof(int) * group_def->nbr_cids); group->v.group = group_data; xi_add_to_parent_list(group, -1); create_children( xi_obj_def, group, creating_list ); } /* ------------------------------------------------------------------------ */ /* column_create */ /* ------------------------------------------------------------------------ */ static void column_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ* obj, BOOLEAN creating_list ) { LM_COLUMN_DEF lm_column_def; XI_COLUMN_DATA * column_data; XI_COLUMN_DEF * col_def; XI_OBJ * * column; int i; int pixel_width; LM_DATA * lmp; XI_LIST_DATA * list_data; int char_pixel_width; list_data = obj->parent->v.list; lmp = (LM_DATA *)list_data->lm; MEMCLEAR(lm_column_def); column_data = (XI_COLUMN_DATA *)xi_tree_malloc(sizeof(XI_COLUMN_DATA), (char *)obj); col_def = xi_obj_def->v.column; lm_column_def.attrib = col_def->attrib; char_pixel_width = xi_get_fu_width( obj->itf ); if (col_def->pixel_width == 0) if (xi_get_xil_pref((XI_OBJ*) obj )) col_def->pixel_width = col_def->width * char_pixel_width; else col_def->pixel_width = col_def->width * char_pixel_width / XI_FU_MULTIPLE; pixel_width = col_def->pixel_width; if (list_data->width) { pixel_width = lmp->pixel_width; for (i = 0; i < min(lmp->fixed_columns, lmp->nbr_columns); ++i) pixel_width -= lmp->lm_column_data[i]->pix_width; pixel_width = min(pixel_width, col_def->pixel_width); } if (col_def->position) lm_column_def.position = min(col_def->position, lmp->nbr_columns); else { for ( lm_column_def.position = i = 0, column = obj->parent->children; i < obj->parent->nbr_children; i++, column++) { xvt_errmsg_sig_if(!((*column)->type == XIT_COLUMN), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20015", 20015, "Internal XI error"); if ((*column)->v.column->sort_number < col_def->sort_number) lm_column_def.position++; } } lm_column_def.pix_width = pixel_width; lm_column_def.text_size = col_def->text_size; if (lm_column_def.text_size < 2) lm_column_def.text_size = 2; lm_column_def.heading_text = col_def->heading_text; lm_column_def.center_heading = col_def->center_heading; #if XVTWS != WMWS lm_column_def.heading_well = col_def->heading_well; lm_column_def.heading_platform = col_def->heading_platform; lm_column_def.column_well = col_def->column_well; lm_column_def.column_platform = col_def->column_platform; #else lm_column_def.heading_well = FALSE; lm_column_def.heading_platform = FALSE; lm_column_def.column_well = FALSE; lm_column_def.column_platform = FALSE; #endif if (col_def->font || col_def->font_id) { lm_column_def.font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ), NULL); if (col_def->font_id) *lm_column_def.font = xi_create_copy_font_id(obj->itf, col_def->font_id, 0); } lm_column_def.icon_rid = col_def->icon_rid; lm_column_def.icon_x = col_def->icon_x; lm_column_def.icon_y = col_def->icon_y; lm_column_def.size_rows = col_def->size_rows; lm_column_def.suppress_update_heading = col_def->suppress_update_heading; lm_column_def.suppress_update_cells = col_def->suppress_update_cells; lm_column_def.vertical_align_center = col_def->vertical_align_center; lm_column_def.vertical_align_bottom = col_def->vertical_align_bottom; lm_column_def.wrap_text = col_def->wrap_text; if (col_def->wrap_text) if (lmp->max_lines_in_cell == 1) lmp->max_lines_in_cell = 5; lm_column_def.auto_tab = col_def->auto_tab; obj->v.column = column_data; column_data->sort_number = col_def->sort_number; xi_add_to_parent_list(obj, lm_column_def.position); lm_create_column( obj->parent->v.list->lm, &lm_column_def, (BOOLEAN)!creating_list, TRUE); xvt_errmsg_sig_if(!( xi_obj_def->nbr_children == 0), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20056", 20056, "xi_create: Columns cannot have children"); if (list_data->width == 0 && list_data->sb_win) xi_move_list_scroll_bar( obj->parent); } /* ------------------------------------------------------------------------ */ /* list_data_create */ /* ------------------------------------------------------------------------ */ static void list_data_create( XI_LIST_DEF* list_def, XI_OBJ* list ) { XI_LIST_DATA * list_data; list_data = (XI_LIST_DATA *)xi_tree_malloc( sizeof(XI_LIST_DATA), (char *)list); list->v.list = list_data; list_data->xi_pnt = list_def->xi_pnt; list_data->height = list_def->height; list_data->one_row_list = list_def->one_row_list; list_data->start_percent = list_def->start_percent; list_data->horz_sync_list = list_def->horz_sync_list; list_data->vert_sync_list = list_def->vert_sync_list; list_data->row_focus_border = list_def->row_focus_border; list_data->row_focus_border_color = list_def->row_focus_border_color; list_data->max_lines_in_cell = list_def->max_lines_in_cell; list_data->single_select = list_def->single_select; list_data->font = (FONT_OBJ *)xi_tree_malloc( sizeof(FONT_OBJ), list_data); if (list_def->font || list_def->font_id) { if (list_def->font_id) *list_data->font = xi_create_copy_font_id( list->itf, list_def->font_id, 0); } else if (list->itf->v.itf->font) { *list_data->font = *list->itf->v.itf->font; } else *list_data->font = xi_sysfont; } /* ------------------------------------------------------------------------ */ /* list_module_def_create */ /* ------------------------------------------------------------------------ */ static void list_module_def_create( LM_DEF* lm_def, XI_LIST_DEF* list_def, XI_OBJ* list ) { /* create LM */ XI_LIST_DATA* list_data = list->v.list; MEMCLEAR(*lm_def); lm_def->cid = list->cid; lm_def->pnt = list_def->xi_pnt; if (xi_get_xil_pref((XI_OBJ*) list->parent)) lm_def->pixel_height = list_def->height; else { if (list_def->pixel_origin.h || list_def->pixel_origin.v ) lm_def->pnt = list_def->pixel_origin; else { lm_def->pnt = list_def->xi_pnt; xi_fu_to_pu(list->itf, &lm_def->pnt, 1); } if (list_def->pixel_height) lm_def->pixel_height = list_def->pixel_height; else lm_def->pixel_height = list_def->height * xi_get_fu_height( list->itf ) / XI_FU_MULTIPLE; } lm_def->pix_char_width = xi_get_fu_width( list->itf ); lm_def->attrib = list_def->attrib; lm_def->back_color = list_def->back_color; lm_def->enabled_color = list_def->enabled_color; lm_def->disabled_color = list_def->disabled_color; lm_def->disabled_back_color = list_def->disabled_back_color; lm_def->active_color = list_def->active_color; lm_def->active_back_color = list_def->active_back_color; lm_def->white_space_color = list_def->white_space_color; if (! lm_def->white_space_color) lm_def->white_space_color = COLOR_LTGRAY; lm_def->rule_color = list_def->rule_color; if (! lm_def->rule_color ) lm_def->rule_color = COLOR_BLACK; lm_def->lm_cb = xi_lm_cb; if (list_data->font) lm_def->font = list_data->font; else if ( list->itf->v.itf->font) lm_def->font = list->itf->v.itf->font; else lm_def->font = &xi_sysfont; lm_def->no_heading = list_def->no_heading; lm_def->one_row_list = list_def->one_row_list; lm_def->sizable_columns = list_def->sizable_columns; lm_def->movable_columns = list_def->movable_columns; lm_def->fixed_columns = list_def->fixed_columns; #if XI_IS_CH CTOS_IS_CH; lm_def->min_cell_height = 8; lm_def->min_heading_height = list_def->min_heading_height; CTOS_END; #endif #if XI_IS_NOT_CH CTOS_IS_PM; lm_def->min_cell_height = list_def->min_cell_height; lm_def->min_heading_height = list_def->min_heading_height; CTOS_END; #endif lm_def->no_horz_lines = list_def->no_horz_lines; lm_def->no_vert_lines = list_def->no_vert_lines; lm_def->first_vis_column = list_def->first_vis_column; lm_def->drop_and_delete = list_def->drop_and_delete; lm_def->select_cells = list_def->select_cells; lm_def->get_all_records = list_def->get_all_records; lm_def->keep_all_records = list_def->keep_all_records; lm_def->resize_with_window = list_def->resize_with_window; lm_def->horz_sync_list = list_def->horz_sync_list; lm_def->vert_sync_list = list_def->vert_sync_list; lm_def->row_focus_border = list_def->row_focus_border; lm_def->row_focus_border_color = list_def->row_focus_border_color; lm_def->single_select = list_def->single_select; lm_def->retain_back_color_on_select = list_def->retain_back_color_on_select; if (xi_get_xil_pref((XI_OBJ*) list->parent)) lm_def->pixel_width = list_def->width; else { if (list_def->pixel_width) lm_def->pixel_width = list_def->pixel_width; else { PNT p; p.h = list_def->width; p.v = 0; xi_fu_to_pu(list->itf, &p, 1); lm_def->pixel_width = p.h; } lm_def->max_lines_in_cell = list_def->max_lines_in_cell; } } /* ------------------------------------------------------------------------ */ /* lm_get_width */ /* ------------------------------------------------------------------------ */ static int lm_get_width( XI_OBJ_DEF* obj_def, int fu_width, int columns ) { XI_LIST_DEF* list_def = obj_def->v.list; int i; int number_fixed_columns; int fixed_column_width; int max_movable_column; int movable_column_width; int total_columns; int width; XI_OBJ_DEF** column; /* calculate all pixel widths */ column = obj_def->children; total_columns = obj_def->nbr_children; /* If it is an empty list, just return */ if (total_columns <= 0) return 0; for ( i = 0; i < total_columns; ++column, ++i ) { XI_COLUMN_DEF* col = (*column)->v.column; if (!col->pixel_width) { if (xi_get_xil_pref((XI_OBJ*) obj_def->parent)) col->pixel_width = col->width * fu_width; else col->pixel_width = col->width * fu_width / XI_FU_MULTIPLE; } } /* find sum of fixed column widths */ number_fixed_columns = min( list_def->fixed_columns, total_columns); column = obj_def->children; fixed_column_width = 0; for ( i = 0; i < number_fixed_columns; ++column, ++i ) fixed_column_width += (*column)->v.column->pixel_width; /* add the internal rule widths to the fixed columns */ if (number_fixed_columns > 1) fixed_column_width += (number_fixed_columns - 1) * lm_get_col_spacing(); /* find largest moveable column width, and sum of movable column widths */ max_movable_column = 0; movable_column_width = 0; if (columns <= number_fixed_columns) { columns = number_fixed_columns; /* if we have any movable columns, columns must be at least */ /* # fixed_columns + 1 */ if ( total_columns > number_fixed_columns ) columns++; } for (; i < columns; ++column, ++i) { XI_COLUMN_DEF* col = (*column)->v.column; movable_column_width += col->pixel_width; max_movable_column = max( max_movable_column, col->pixel_width); } for (; i < total_columns; ++column, ++i ) max_movable_column = max( max_movable_column, (*column)->v.column->pixel_width); /* add the internal column rules for movable columns */ if (columns > number_fixed_columns + 1) movable_column_width += (columns - number_fixed_columns - 1) * lm_get_col_spacing(); /* use either the sum of the movable columns, or the largest movable column */ movable_column_width = max( movable_column_width, max_movable_column ); /* calculate width */ width = 2 * BORDER_WIDTH + fixed_column_width + movable_column_width; /* add the rule between fixed & movable columns */ if (columns > number_fixed_columns && number_fixed_columns > 0) width += lm_get_col_spacing(); return width; } /* ------------------------------------------------------------------------ */ /* xi_list_def_get_client_width */ /* ------------------------------------------------------------------------ */ int xi_list_def_get_client_width( XI_OBJ_DEF* obj_def, int columns ) { FONT_OBJ* font; font = xi_def_get_font( obj_def ); return lm_get_width( obj_def, xi_get_fu_width_font( font ), columns ); } /* ------------------------------------------------------------------------ */ /* xi_list_def_get_outer_width */ /* ------------------------------------------------------------------------ */ int xi_list_def_get_outer_width( XI_OBJ_DEF* obj_def, int columns ) { int result; result = xi_list_def_get_client_width( obj_def, columns ); if (obj_def->v.list->scroll_bar) result += (int)xi_get_pref(XI_PREF_SB_OFFSET) + (int)xi_get_pref(XI_PREF_SB_WIDTH); #ifdef XI_IS_CH return result; #else return result + 2 * BORDER_WIDTH; #endif } #if XIWS == PMWS /* This function is required to fix a scrolling problem on PM. */ PFNWP oldProc = NULL; MRESULT EXPENTRY win_sub_proc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) { switch( msg ) { case WM_HSCROLL: case WM_VSCROLL: { if( SHORT2FROMMP( mp2 ) == SB_ENDSCROLL ) { WinSetFocus( HWND_DESKTOP, hwnd ); return( (MRESULT)0 ); } } break; } return( oldProc( hwnd, msg, mp1, mp2 ) ); } #endif /* ------------------------------------------------------------------------ */ /* list_create */ /* ------------------------------------------------------------------------ */ static void list_create( XI_OBJ_DEF* xi_obj_def, XI_OBJ * list ) { XI_LIST_DEF* list_def = xi_obj_def->v.list; XI_LIST_DATA* list_data; LM_DEF lm_def; int i, min_height; RCT rct, min_rct; WINDOW itf_win; BOOLEAN save_or; BOOLEAN use_wrap = TRUE; itf_win = list->itf->v.itf->xvt_win; list_data_create( list_def, list ); list_data = list->v.list; list_module_def_create( &lm_def, list_def, list ); if (lm_def.pixel_width) { int min_width; min_width = lm_get_width( xi_obj_def, lm_def.pix_char_width, 1 ); /* insure minimum size */ if ( min_width > lm_def.pixel_width ) lm_def.pixel_width = min_width; } if ( list_def->resize_with_window && list->parent && list->parent->itf->v.itf->xvt_win) { RCT cr; xvt_vobj_get_client_rect( list->parent->itf->v.itf->xvt_win, &cr); save_or = xi_obj_def->v.list->one_row_list; xi_obj_def->v.list->one_row_list = TRUE; xi_get_def_rect(xi_obj_def, &min_rct); xi_obj_def->v.list->one_row_list = save_or; min_height = min_rct.bottom - min_rct.top; lm_def.pixel_height = cr.bottom - lm_def.pnt.v; if (lm_def.pixel_width) lm_def.pixel_height -= (int)xi_get_pref(XI_PREF_SB_HEIGHT); lm_def.pixel_height = max(lm_def.pixel_height, min_height); if (lm_def.pixel_width) { int idx, min_width, max_hs; XI_OBJ_DEF *col_def; RCT col_rct; min_width = 0; if (xi_obj_def->nbr_children > 0 ) { for (idx = 0; idx < xi_obj_def->v.list->fixed_columns; ++idx) { col_def = xi_obj_def->children[idx]; xi_get_def_rect(col_def, &col_rct); min_width += (col_rct.right - col_rct.left); } max_hs = 0; for ( idx = xi_obj_def->v.list->fixed_columns; idx < xi_obj_def->nbr_children; ++idx) { col_def = xi_obj_def->children[idx]; xi_get_def_rect(col_def, &col_rct); if (!col_def->v.column->wrap_text) use_wrap = FALSE; max_hs = max(max_hs, (col_rct.right - col_rct.left)); } min_width += max_hs; } lm_def.pixel_width = cr.right - lm_def.pnt.h - 2 * BORDER_WIDTH; if (list_def->scroll_bar) lm_def.pixel_width -= (int)xi_get_pref(XI_PREF_SB_WIDTH); lm_def.pixel_width = max( lm_def.pixel_width, min_width ); } } lm_def.list_obj = list; lm_def.itf_obj = list->itf; lm_def.parent = (char *)list_data; list_data->width = lm_def.pixel_width; if (!use_wrap) xi_set_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL, 1); /* TODO calculate and set realized_rows_array_len TODO also set nbr_rows, if user specified a specific nbr of rows. */ list_data->lm = lm_create( itf_win, &lm_def, list_data); list_data->scroll_bar_button = list_def->scroll_bar_button; /* * Initialize focus obj data. Use list object for defaults. */ list_data->focus_cell_array[0] = *list; list_data->focus_cell_array[0].parent = list; list_data->focus_cell_array[0].type = XIT_CELL; list_data->focus_cell_array[0].v.cell.row = list_data->focus_cell_array[0].v.cell.column = 0; list_data->focus_cell_array[0].v.cell.is_vert_scrolled = FALSE; for (i = 1; i < FOCUS_CELL_ARRAY_LEN; ++i) list_data->focus_cell_array[i] = list_data->focus_cell_array[0]; list_data->focus_cell = &list_data->focus_cell_array[0]; list_data->tab_cid = list_def->tab_cid; list_data->scroll_bar = list_def->scroll_bar; xi_add_to_parent_list(list, -1); create_children( xi_obj_def, list, TRUE ); if (list_def->scroll_bar) { if (list_data->sb_win) xi_move_list_scroll_bar(list); else { RCT rct; long attrib; attrib = lm_get_attrib(list_data->lm, LM_LIST, 0, 0, FALSE); xi_get_sb_rect(list, &rct); list_data->sb_win = xi_new_control(&rct, "", WC_VSCROLL, itf_win, (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0), list->cid, NULL); xvt_sbar_set_range(list_data->sb_win, HVSCROLL, 0, 100); if (! (attrib & XI_ATR_ENABLED)) xvt_vobj_set_enabled(list_data->sb_win, FALSE); xi_get_sb_rect(list, &rct); if (list_data->scroll_bar_button) xi_invalidate_rect(list->itf->v.itf->xvt_win, &list_data->sbb_rct); } } if (lm_def.pixel_width != 0) { unsigned long attrib; attrib = lm_get_attrib(list_data->lm, LM_LIST, 0, 0, FALSE); xi_get_hsb_rect( list, &rct); list_data->hsb_win = xi_new_control( &rct, "", WC_HSCROLL, itf_win, (BOOLEAN)((attrib & XI_ATR_VISIBLE) != 0), list->cid + HSCROLL_CID_CONST, NULL); if (! (attrib & XI_ATR_ENABLED)) xvt_vobj_set_enabled(list_data->hsb_win, FALSE); lm_set_hscroll_range(list_data->lm); } xi_get_rect( list, &rct); xi_inflate_rect(&rct, 8); xi_invalidate_rect(itf_win, &rct); lm_set_hscroll_range(list->v.list->lm); if (xi_obj_def->v.list->first_vis_column) { xvt_dwin_update(itf_win); xi_hscroll_internal( list, xi_obj_def->v.list->first_vis_column - xi_obj_def->v.list->fixed_columns, 0); } #if XIWS == PMWS { HWND hwnd = (HWND)xvt_vobj_get_attr( itf_win, ATTR_NATIVE_WINDOW ); if( hwnd && (oldProc == NULL)) oldProc = WinSubclassWindow( hwnd, win_sub_proc ); } #endif } /* ------------------------------------------------------------------------ */ /* xi_create_internal */ /* ------------------------------------------------------------------------ */ static XI_OBJ * xi_create_internal( XI_OBJ * parent, XI_OBJ_DEF* xi_obj_def, BOOLEAN creating_list ) { XI_OBJ * obj; if (! inited) xi_init(); /* object data initialization common to all types */ obj = (XI_OBJ *)xi_tree_malloc(sizeof(XI_OBJ), (char *)parent); obj->parent = parent; obj->cid = xi_obj_def->cid; obj->type = xi_obj_def->type; obj->app_data = xi_obj_def->app_data; obj->app_data2 = xi_obj_def->app_data2; if (xi_obj_def->type != XIT_ITF) { RCT rct; XI_ITF_DATA *itf_data; obj->itf = parent->itf; xi_get_def_rect(xi_obj_def, &rct); xi_pu_to_fu(NULL, (XI_PNT *)&rct, 2); itf_data = obj->itf->v.itf; itf_data->max_xi_pnt.h = max(itf_data->max_xi_pnt.h, rct.right); itf_data->max_xi_pnt.v = max(itf_data->max_xi_pnt.v, rct.bottom); } else obj->itf = obj; switch (xi_obj_def->type) { case XIT_ITF: interface_create( xi_obj_def, obj ); break; case XIT_CONTAINER: container_create( xi_obj_def, obj ); break; case XIT_RECT: rectangle_create( xi_obj_def, obj ); break; case XIT_LINE: line_create( xi_obj_def, obj ); break; case XIT_BTN: button_create( xi_obj_def, obj ); break; case XIT_FORM: form_create( xi_obj_def, obj ); break; case XIT_FIELD: field_create( xi_obj_def, obj ); break; case XIT_LIST: list_create( xi_obj_def, obj ); break; case XIT_COLUMN: column_create( xi_obj_def, obj, creating_list ); break; case XIT_TEXT: text_create( xi_obj_def, obj ); break; case XIT_GROUP: group_create( xi_obj_def, obj, creating_list ); break; case XIT_CELL: case XIT_ROW: default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20016", 20016, "xi_create: Invalid XI_OBJ_TYPE"); } return obj; } /* ------------------------------------------------------------------------ */ /* xi_create */ /* ------------------------------------------------------------------------ */ /* xi_create performs the following steps: 1. Copy the *_DEFs into *_DATAs 2. Call creation functions for LM, STX, buttons 3. Initialize event routing */ XI_OBJ * xi_create(XI_OBJ *parent, XI_OBJ_DEF *xi_obj_def) { return xi_create_internal( parent, xi_obj_def, FALSE ); } void xi_close_window_internal(XI_OBJ *itf) { XI_ITF_DATA *itf_data = itf->v.itf; if (itf_data->modal) { if (itf_data->xvt_win != xi_modal_win) { /* Modal closing, but not on top */ XI_OBJ *temp_itf; WINDOW curWin = xi_modal_win; do { temp_itf = xi_get_itf(curWin); curWin = temp_itf->v.itf->prev_modal; } while (curWin != itf_data->xvt_win); temp_itf->v.itf->prev_modal = itf_data->prev_modal; } else { xi_modal_win = itf_data->prev_modal; if (xi_modal_win == NULL_WIN) { #if (XIWS == WINWS) || (XIWS == PMWS) xvt_vobj_set_enabled(TASK_WIN, TRUE); #endif #if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS) { SLIST win_list = xvt_scr_list_wins(); SLIST_ELT elt; for (elt = xvt_slist_get_first(win_list); elt != NULL; elt = xvt_slist_get_next(win_list, elt)) xvt_vobj_set_enabled((WINDOW)*xvt_slist_get_data(elt), TRUE); xvt_slist_destroy(win_list); } #endif } else { #if (XIWS == WINWS) || (XIWS == PMWS) xvt_vobj_set_enabled(xi_modal_win, TRUE); #if XIWS == PMWS xvt_scr_set_focus_vobj(xi_modal_win); xvt_vobj_raise(xi_modal_win); #endif #endif #if (XIWS == WMWS) || (XIWS == GRWS) || (XIWS == MACWS) xvt_vobj_set_enabled(xi_modal_win, TRUE); xvt_scr_set_focus_vobj(xi_modal_win); xvt_vobj_raise(xi_modal_win); #endif } } } xvt_vobj_destroy(itf_data->xvt_win); } static void near xi_delete_internal(XI_OBJ *xi_obj, BOOLEAN recursive) { RCT rct; XI_OBJ_TYPE type = xi_obj->type; if (xi_obj->itf->v.itf->focus_obj == xi_obj) xi_obj->itf->v.itf->focus_obj = NULL; switch(type) { case XIT_FIELD: xi_get_rect(xi_obj, &rct); xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct); stx_delete(xi_obj->v.field->stx); break; case XIT_FORM: case XIT_CONTAINER: { XI_OBJ * *objlist; int n; /* loop over sub-objects */ if (!recursive) { objlist = xi_get_member_list(xi_obj, &n); for (; n > 0; n--, objlist++) xi_delete_internal(*objlist, TRUE); break; } } case XIT_GROUP: break; case XIT_ITF: { XI_ITF_DATA *itf_data; itf_data = xi_obj->v.itf; if (itf_data->in_callback) itf_data->closing = TRUE; else xi_close_window_internal(xi_obj); return; } case XIT_LIST: { XI_LIST_DATA *list_data; list_data = xi_obj->v.list; xi_get_rect(xi_obj, &rct); if (list_data->scroll_bar) xvt_vobj_destroy(list_data->sb_win); if (list_data->hsb_win) xvt_vobj_destroy(list_data->hsb_win); xi_inflate_rect(&rct, 8); xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct); if (!recursive) lm_delete(list_data->lm); break; } case XIT_COLUMN: { XI_LIST_DATA *list_data; int col_nbr; BOOLEAN move_hsb; list_data = xi_obj->parent->v.list; col_nbr = xi_obj_to_idx(xi_obj); move_hsb = (col_nbr < ((LM_DATA *)(list_data->lm))->fixed_columns); if (!recursive) lm_delete_column(list_data->lm, col_nbr, TRUE); if (list_data->scroll_bar && (! list_data->width)) xi_move_list_scroll_bar(xi_obj->parent); if (! recursive) { if (list_data->hsb_win && move_hsb) { list_data->have_hsb_rct = FALSE; xi_move_list_hscroll_bar(xi_obj->parent); } } break; } case XIT_TEXT: case XIT_RECT: case XIT_LINE: xi_get_rect(xi_obj, &rct); xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct); break; case XIT_BTN: if (xi_obj->v.btn->btnctl) xvt_vobj_destroy(xi_obj->v.btn->btnctl); else { xi_get_rect(xi_obj, &rct); xi_invalidate_rect(xi_obj->itf->v.itf->xvt_win, &rct); } break; default: xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL, ERR_ASSERT_4,"20017", 20017, "Invalid XI object passed to xi_delete"); break; } if (!recursive) { xi_remove_from_parent_list(xi_obj); if (type == XIT_COLUMN) /* an ugly hack */ { XI_LIST_DATA *list_data; list_data = xi_obj->parent->v.list; lm_make_rrr_room_pix( (LM_DATA*) list_data->lm, 0, FALSE ); } xi_tree_free((char *)xi_obj); } } void xi_delete(XI_OBJ *xi_obj) { xi_delete_internal(xi_obj, FALSE); } void xi_move_column_internal(XI_OBJ *column, int position, BOOLEAN in_hscrolling) { XI_OBJ *list; XI_LIST_DATA *list_data; LM_DATA *lm_data; LM_COLUMN_DATA *col_data; LM_COLUMN_DEF lm_column_def; int col_nbr, i; FONT_OBJ *font; BOOLEAN move_hsb = FALSE; int focus_row, focus_column; BOOLEAN v_scrolled; BOOLEAN redraw_row = FALSE; list = column->parent; list_data = list->v.list; lm_data = (LM_DATA *)list_data->lm; i = xi_obj_to_idx(column); lm_get_focus_cell(lm_data, &focus_row, &focus_column, &v_scrolled); if (focus_column == i && lm_data->row_focus_border) redraw_row = TRUE; if (list_data->hsb_win) if (i < lm_data->fixed_columns || position < lm_data->fixed_columns) move_hsb = TRUE; if (position == lm_data->fixed_columns && ! in_hscrolling) move_hsb = TRUE; col_nbr = xi_obj_to_idx(column); col_data = lm_data->lm_column_data[col_nbr]; MEMCLEAR(lm_column_def); lm_column_def.attrib = col_data->attrib; lm_column_def.position = position; lm_column_def.pix_width = col_data->pix_width; lm_column_def.text_size = col_data->text_size; lm_column_def.heading_text = (char *)xi_tree_malloc( strlen(col_data->heading_text) + 1, list_data); strcpy(lm_column_def.heading_text, col_data->heading_text); lm_column_def.center_heading = col_data->center_heading; #if XVTWS != WMWS lm_column_def.heading_well = col_data->heading_well; lm_column_def.heading_platform = col_data->heading_platform; lm_column_def.column_well = col_data->column_well; lm_column_def.column_platform = col_data->column_platform; #else lm_column_def.heading_well = FALSE; lm_column_def.heading_platform = FALSE; lm_column_def.column_well = FALSE; lm_column_def.column_platform = FALSE; #endif lm_column_def.icon_rid = col_data->icon_rid; lm_column_def.icon_x = col_data->icon_x; lm_column_def.icon_y = col_data->icon_y; lm_column_def.vertical_align_center = col_data->vertical_align_center; lm_column_def.vertical_align_bottom = col_data->vertical_align_bottom; lm_column_def.wrap_text = col_data->wrap_text; lm_column_def.auto_tab = col_data->auto_tab; if (col_data->font) { font = (FONT_OBJ*)xi_tree_malloc(sizeof(FONT_OBJ), NULL); lm_column_def.font = font; *lm_column_def.font = *col_data->font; } lm_delete_column((LM)lm_data, col_nbr, FALSE); xi_remove_from_parent_list(column); xi_add_to_parent_list(column, lm_column_def.position); lm_create_column((LM)lm_data, &lm_column_def, TRUE, in_hscrolling); if (move_hsb) { list->v.list->have_hsb_rct = FALSE; xi_move_list_hscroll_bar(column->parent); } lm_set_hscroll_range((LM)lm_data); if (redraw_row) lm_redraw_row(lm_data, focus_row, FALSE); } void xi_move_column(XI_OBJ *column, int position) { XI_OBJ *list; XI_LIST_DATA *list_data; LM_DATA *lm_data; int current_pos; list = column->parent; list_data = list->v.list; lm_data = (LM_DATA *)list_data->lm; current_pos = xi_obj_to_idx(column); xi_move_column_internal(column, position, (BOOLEAN)(current_pos >= lm_data->fixed_columns)); } BOOLEAN xi_is_auto_tab( XI_OBJ *xi_obj ) { if ( xi_obj->type == XIT_FIELD ) return ((STX_DATA*)xi_obj->v.field->stx)->auto_tab; if ( xi_obj->type == XIT_COLUMN ) return LMP(xi_obj->parent->v.list->lm)-> lm_column_data[xi_obj_to_idx(xi_obj)]->auto_tab; return FALSE; } void xi_init(void) { if (! inited) { inited = TRUE; xi_init_sysvals(); } }