campo-sirio/xi/xi2.c
alex 18c8e52948 This commit was generated by cvs2svn to compensate for changes in r5757,
which included commits to RCS files with non-trunk default branches.

git-svn-id: svn://10.65.10.50/trunk@5758 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-12-17 10:43:31 +00:00

3503 lines
107 KiB
C
Executable File

/*******************************************************************************
* 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 <X11/Intrinsic.h>
#include <Xm/Xm.h>
#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();
}
}