1146 lines
28 KiB
C
Executable File
1146 lines
28 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 XI_INTERNAL
|
|
|
|
#include "xi.h"
|
|
#include "xitext.h"
|
|
#include "xistx.h"
|
|
#include "xiutils.h"
|
|
|
|
#define tx_create
|
|
#define xvt_tx_process_event xvt_tx_process_event
|
|
|
|
/* error codes 30100 - 30104 */
|
|
|
|
#if XVT_OS == XVT_OS_CTOS
|
|
#define BORDER_WIDTH_X ((npctos_env == CHSERVICE) ? 8 : 1)
|
|
#define BORDER_WIDTH_Y ((npctos_env == CHSERVICE) ? 0 : 1)
|
|
#define BORDER_SPACE_X ((npctos_env == CHSERVICE) ? 0 : 1)
|
|
#define BORDER_SPACE_Y ((npctos_env == CHSERVICE) ? 0 : 1)
|
|
#define CHR_LEFTBRACKET "["
|
|
#define CHR_RIGHTBRACKET "]"
|
|
#else
|
|
#if XIWS != WMWS
|
|
#define BORDER_WIDTH_X 1
|
|
#define BORDER_WIDTH_Y 1
|
|
#define BORDER_SPACE_X 1
|
|
#define BORDER_SPACE_Y 1
|
|
#else
|
|
#define BORDER_WIDTH_X 8
|
|
#define BORDER_WIDTH_Y 0
|
|
#define BORDER_SPACE_X 0
|
|
#define BORDER_SPACE_Y 0
|
|
#define CHR_LEFTBRACKET "["
|
|
#define CHR_RIGHTBRACKET "]"
|
|
#endif
|
|
#endif
|
|
|
|
#define STXP(stx) ((STX_DATA *)(stx))
|
|
#define STX_IS_ENABLED(stx) ((STXP(stx)->attrib & STX_ATR_ENABLED) != 0)
|
|
#define STX_IS_VISIBLE(stx) ((STXP(stx)->attrib & STX_ATR_VISIBLE) != 0)
|
|
#define STX_HAS_BORDER(stx) ((STXP(stx)->attrib & STX_ATR_BORDER) != 0)
|
|
|
|
#define STX_REDRAW_ATR (STX_ATR_VISIBLE | STX_ATR_ENABLED | STX_ATR_RJUST | STX_ATR_PASSWORD)
|
|
|
|
static void near stx_stop_edit(STX stx);
|
|
static void draw_text_edit_border(STX_DATA *stxptr);
|
|
|
|
static void near
|
|
get_text_rect(STX stx, RCT *rct)
|
|
{
|
|
*rct = STXP(stx)->rct;
|
|
rct->top += BORDER_WIDTH_Y + BORDER_SPACE_Y;
|
|
rct->bottom -= BORDER_WIDTH_Y + BORDER_SPACE_Y;
|
|
rct->left += BORDER_WIDTH_X + BORDER_SPACE_X;
|
|
rct->right -= BORDER_WIDTH_X + BORDER_SPACE_X;
|
|
}
|
|
|
|
TXEDIT
|
|
stx_get_txedit(STX stx)
|
|
{
|
|
return STXP(stx)->txedit;
|
|
}
|
|
|
|
STX
|
|
stx_create(WINDOW win, STX_DEF *stx_def)
|
|
{
|
|
STX_DATA *stxd;
|
|
RCT rct;
|
|
int ascent, descent, leading, font_height;
|
|
short rct_r, rct_b, edit_height;
|
|
XI_OBJ *itf;
|
|
|
|
itf = xi_get_itf(win);
|
|
NOREF(itf);
|
|
xi_set_xvt_font(win, &stx_def->font, FALSE);
|
|
xi_get_font_metrics(win, &leading, &ascent, &descent);
|
|
font_height = ascent + leading + descent;
|
|
stxd = (STX_DATA *)xi_tree_malloc(sizeof(STX_DATA), stx_def->parent);
|
|
stxd->cid = stx_def->cid;
|
|
stxd->win = win;
|
|
stxd->attrib = stx_def->attrib;
|
|
rct_r = stx_def->pnt.h + stx_def->pixel_width + 2 *
|
|
BORDER_WIDTH_X + 2 * BORDER_SPACE_X;
|
|
edit_height = font_height + 2 * BORDER_WIDTH_Y + 2 * BORDER_SPACE_Y;
|
|
rct_b = stx_def->pnt.v + edit_height;
|
|
xvt_rect_set( &rct, stx_def->pnt.h, stx_def->pnt.v, rct_r, rct_b);
|
|
stxd->rct = rct;
|
|
stxd->font = stx_def->font;
|
|
stxd->back_color = stx_def->back_color;
|
|
stxd->enabled_color = stx_def->enabled_color;
|
|
stxd->disabled_color = stx_def->disabled_color;
|
|
stxd->active_color = stx_def->active_color;
|
|
stxd->active_back_color = stx_def->active_back_color;
|
|
stxd->disabled_back_color = stx_def->disabled_back_color;
|
|
stxd->hilight_color = stx_def->hilight_color;
|
|
stxd->shadow_color = stx_def->shadow_color;
|
|
stxd->stx_cb = stx_def->stx_cb;
|
|
stxd->text_size = stx_def->text_size;
|
|
stxd->app_data = stx_def->app_data;
|
|
stxd->text = (char *)xi_tree_malloc(stx_def->text_size, (char *)stxd);
|
|
stxd->text[0] = '\0';
|
|
stxd->has_focus = FALSE;
|
|
stxd->well = stx_def->well;
|
|
stxd->platform = stx_def->platform;
|
|
stxd->auto_tab = stx_def->auto_tab;
|
|
stxd->txedit = BAD_TXEDIT;
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (stx_def->xi_rct.top || stx_def->xi_rct.left ||
|
|
stx_def->xi_rct.bottom || stx_def->xi_rct.right)
|
|
{
|
|
unsigned attrib;
|
|
RCT rct;
|
|
|
|
if ((stx_def->xi_rct.bottom - stx_def->xi_rct.top) <=
|
|
XI_FU_MULTIPLE)
|
|
{
|
|
rct = stx_def->xi_rct;
|
|
xi_fu_to_pu(xi_get_itf(win), (PNT *)&rct, 2);
|
|
rct.bottom = rct.top + edit_height;
|
|
stxd->rct = rct;
|
|
}
|
|
else
|
|
{
|
|
FONT_OBJ font;
|
|
|
|
attrib = TX_WRAP;
|
|
if (stxd->attrib & XI_ATR_READONLY)
|
|
attrib |= TX_READONLY;
|
|
if (stxd->attrib & XI_ATR_BORDER)
|
|
attrib |= TX_BORDER;
|
|
if (stxd->attrib & XI_ATR_AUTOSCROLL)
|
|
attrib |= TX_AUTOHSCROLL | TX_AUTOVSCROLL;
|
|
if (! itf->v.itf->edit_menu)
|
|
attrib |= TX_NOMENU;
|
|
stxd->use_text_edit = TRUE;
|
|
rct = stx_def->xi_rct;
|
|
xi_fu_to_pu(xi_get_itf(win), (PNT *)&rct, 2);
|
|
rct.bottom -= BORDER_SPACE_Y;
|
|
stxd->rct = rct;
|
|
if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK))
|
|
&&((stxd->well == TRUE) || (stxd->platform == TRUE)))
|
|
{
|
|
xi_inflate_rect(&rct, -2);
|
|
attrib &= ~TX_BORDER;
|
|
}
|
|
if ((stxd->attrib & XI_ATR_FOCUSBORDER) || ((stxd->attrib & XI_ATR_BORDER)))
|
|
xi_inflate_rect(&rct, -1);
|
|
font = stx_def->font;
|
|
stxd->txedit = xvt_tx_create(win, &rct, attrib,
|
|
font, rct.right - rct.left - 4, INT_MAX);
|
|
xvt_tx_set_colors(stxd->txedit, stxd->enabled_color,
|
|
stxd->enabled_color, stxd->back_color);
|
|
xvt_tx_add_par(stxd->txedit, 0, "");
|
|
|
|
/* the following line is a hack for ms-windows */
|
|
{ PNT _p; _p.h = -100; _p.v = -100;
|
|
xvt_win_set_caret_pos(win, _p); /*xvt_R3MIG caret_on*/
|
|
xvt_win_set_caret_visible(win, TRUE); };
|
|
xvt_win_set_caret_visible(win, FALSE );
|
|
}
|
|
}
|
|
#endif
|
|
xi_invalidate_rect(win, &stxd->rct);
|
|
return((STX)PTR_LONG(stxd));
|
|
}
|
|
|
|
void
|
|
stx_delete(STX stx)
|
|
{
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
xvt_tx_destroy(STXP(stx)->txedit);
|
|
else
|
|
#endif
|
|
{
|
|
if (STXP(stx)->has_focus)
|
|
stx_stop_edit(stx);
|
|
xi_invalidate_rect(STXP(stx)->win, &STXP(stx)->rct);
|
|
}
|
|
xi_tree_free((char *)stx);
|
|
}
|
|
|
|
static void near
|
|
redraw_stx(STX stx, BOOLEAN update, BOOLEAN inside_only)
|
|
{
|
|
RCT rct;
|
|
DRAW_CTOOLS ct;
|
|
FONT_OBJ *ct_font;
|
|
STX_DATA *stxp = STXP(stx);
|
|
#if XI_IS_NOT_CH
|
|
RCT rct2, rr;
|
|
#endif
|
|
|
|
#if XI_IS_CH
|
|
NOREF(inside_only);
|
|
#endif
|
|
|
|
if (STXP(stx)->use_text_edit)
|
|
return;
|
|
rct = stxp->rct;
|
|
if (update && !xi_needs_update(stxp->win, &rct))
|
|
return;
|
|
if (STX_IS_VISIBLE(stx))
|
|
{
|
|
xvt_app_get_default_ctools(&ct);
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
ct.pen = hollow_cpen;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (STX_HAS_BORDER(stx) && !inside_only)
|
|
ct.pen = black_cpen;
|
|
else
|
|
ct.pen = hollow_cpen;
|
|
CTOS_END;
|
|
#endif
|
|
ct_font = &stxp->font;
|
|
if (STX_IS_ENABLED(stx))
|
|
{
|
|
ct.fore_color = ct.pen.color =
|
|
(stxp->has_focus ? stxp->active_color : stxp->enabled_color);
|
|
ct.brush.color =
|
|
(stxp->has_focus ? stxp->active_back_color : stxp->back_color);
|
|
}
|
|
else
|
|
{
|
|
/* draw disabled cells with grey background */
|
|
ct.fore_color = ct.pen.color = stxp->disabled_color;
|
|
ct.brush.color = stxp->disabled_back_color;
|
|
}
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
rct2 = rct;
|
|
if ((stxp->attrib & XI_ATR_FOCUSBORDER) || (! (stxp->attrib & XI_ATR_BORDER)))
|
|
{
|
|
if (! stxp->has_focus)
|
|
{
|
|
static XI_OBJ *itf;
|
|
COLOR back_color;
|
|
|
|
ct.pen = black_cpen;
|
|
itf = xi_get_itf(stxp->win);
|
|
back_color = itf->v.itf->back_color;
|
|
if (back_color)
|
|
ct.pen.color = back_color;
|
|
else
|
|
ct.pen.color = xi_get_pref(XI_PREF_COLOR_CTRL);
|
|
}
|
|
}
|
|
|
|
/* TODO only draw inside only if not well or plat */
|
|
if (! stxp->well && ! stxp->platform)
|
|
if ((! (stxp->attrib & XI_ATR_FOCUSBORDER)) && (! (stxp->attrib & XI_ATR_BORDER)))
|
|
{
|
|
ct.pen = hollow_cpen;
|
|
inside_only = TRUE;
|
|
}
|
|
ct.opaque_text = FALSE;
|
|
xi_set_draw_ctools(stxp->win, &ct);
|
|
|
|
/* TODO moved following two lines down */
|
|
if (stxp->well || stxp->platform)
|
|
xi_set_cbrush(stxp->win, &hollow_cbrush);
|
|
|
|
xi_set_xvt_font(stxp->win, ct_font, FALSE);
|
|
if (inside_only)
|
|
xi_inflate_rect(&rct2, -1);
|
|
rr = rct2;
|
|
xi_set_clip(stxp->win, NULL);
|
|
xi_draw_rect(stxp->win, &rr);
|
|
if (stxp->well || stxp->platform)
|
|
{
|
|
RCT r;
|
|
|
|
r = rct2;
|
|
if (!inside_only)
|
|
xi_inflate_rect(&r, -1);
|
|
xi_draw_3d_rect(stxp->win, &r, stxp->well, 1, stxp->hilight_color,
|
|
stxp->attrib & XI_ATR_ENABLED ? stxp->back_color : stxp->disabled_back_color, stxp->shadow_color);
|
|
}
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
ct.back_color = xi_get_itf(stxp->win)->v.itf->back_color;
|
|
xi_set_draw_ctools(stxp->win, &ct);
|
|
xi_set_xvt_font(stxp->win, ct_font, FALSE);
|
|
if (STX_HAS_BORDER(stx))
|
|
{
|
|
xi_draw_text(stxp->win, rct.left, rct.bottom, CHR_LEFTBRACKET, -1);
|
|
xi_draw_text(stxp->win, rct.right - 8, rct.bottom, CHR_RIGHTBRACKET, -1);
|
|
}
|
|
if (STX_IS_ENABLED(stx))
|
|
xi_set_xvt_back_color(stxp->win, stxp->back_color);
|
|
else
|
|
xi_set_xvt_back_color(stxp->win, stxp->disabled_back_color);
|
|
{
|
|
RCT r;
|
|
|
|
r = rct;
|
|
if (STX_HAS_BORDER(stx))
|
|
{
|
|
r.right -= 8;
|
|
r.left += 8;
|
|
}
|
|
xi_draw_rect(stxp->win, &r);
|
|
}
|
|
CTOS_END;
|
|
#endif
|
|
if (stxp->has_focus)
|
|
txt_redraw(stxp->txt, FALSE);
|
|
else
|
|
{
|
|
/* draw cell text */
|
|
const int old_bottom = rct.bottom;
|
|
get_text_rect(stx, &rct);
|
|
rct.bottom = old_bottom;
|
|
|
|
xi_draw_clipped_text(stxp->win, stxp->text, &rct, &rct, stxp->attrib,
|
|
TRUE, 0, -1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
stx_start_edit: create a text core edit field in the position of the
|
|
field of interest, and copy in the necessary attributes and text from
|
|
the field.
|
|
*/
|
|
static void near
|
|
stx_start_edit(STX stx)
|
|
{
|
|
TXT_DATA *txt;
|
|
|
|
STXP(stx)->has_focus = TRUE;
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
xvt_tx_set_active(STXP(stx)->txedit);
|
|
xi_invalidate_rect(STXP(stx)->win, &STXP(stx)->rct);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
txt = STXP(stx)->txt = (TXT_DATA *)xi_tree_malloc(sizeof(TXT_DATA),
|
|
(char *)stx);
|
|
txt->rct = STXP(stx)->rct;
|
|
txt->parent_obj = xi_get_obj(xi_get_itf(STXP(stx)->win), STXP(stx)->cid);
|
|
txt->attrib = STXP(stx)->attrib | TXT_ATR_VISIBLE;
|
|
txt->text = STXP(stx)->text;
|
|
txt->text_size = STXP(stx)->text_size;
|
|
txt->font = &(STXP(stx)->font);
|
|
txt->back_color = STXP(stx)->active_back_color;
|
|
txt->fore_color = STXP(stx)->active_color;
|
|
txt->hilight_color = STXP(stx)->hilight_color;
|
|
txt->shadow_color = STXP(stx)->shadow_color;
|
|
txt->well = STXP(stx)->well;
|
|
txt->platform = STXP(stx)->platform;
|
|
txt->auto_tab = STXP(stx)->auto_tab;
|
|
txt->win = STXP(stx)->win;
|
|
txt_reset(txt);
|
|
if (STXP(stx)->have_mouse)
|
|
{
|
|
if ((STXP(stx)->attrib & (STX_ATR_AUTOSELECT | STX_ATR_READONLY)) ==
|
|
(STX_ATR_AUTOSELECT | STX_ATR_READONLY))
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
if ((STXP(stx)->attrib & STX_ATR_AUTOSELECT) && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE))
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
}
|
|
else
|
|
{
|
|
if (STXP(stx)->attrib & STX_ATR_AUTOSELECT)
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
else
|
|
txt_set_sel(txt, 0, 0);
|
|
}
|
|
txt_caret(txt, TRUE);
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if ((STXP(stx)->attrib & STX_ATR_AUTOSELECT) == 0)
|
|
txt_set_sel(txt, 0, 0);
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void near
|
|
stx_stop_edit(STX stx)
|
|
{
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
WINDOW win;
|
|
|
|
STXP(stx)->has_focus = FALSE;
|
|
win = STXP(stx)->win;
|
|
#if XVTWS == WINWS
|
|
{ PNT _p; _p.h = -100; _p.v = -100;
|
|
xvt_win_set_caret_pos(win, _p);
|
|
xvt_win_set_caret_visible(win, TRUE); };
|
|
#endif
|
|
xi_caret_off(win);
|
|
xi_invalidate_rect(win, &STXP(stx)->rct);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
txt_hide_caret(STXP(stx)->txt);
|
|
txt_caret(STXP(stx)->txt, FALSE);
|
|
xi_tree_free((char *)STXP(stx)->txt);
|
|
STXP(stx)->txt = NULL;
|
|
STXP(stx)->has_focus = FALSE;
|
|
redraw_stx(stx, FALSE, FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
do_stx_cb: handles the STX_CB_CHAR, STX_CB_CHANGE, STX_CB_FOCUS cases.
|
|
*/
|
|
static BOOLEAN near
|
|
do_stx_cb(STX stx, STX_CB_TYPE cb_reason, EVENT *ep)
|
|
{
|
|
STX_CB_DATA stx_cb_data;
|
|
|
|
stx_cb_data.stx = stx;
|
|
stx_cb_data.cb_type = cb_reason;
|
|
stx_cb_data.cid = STXP(stx)->cid;
|
|
stx_cb_data.win = STXP(stx)->win;
|
|
if (cb_reason == STX_CB_CHAR)
|
|
{
|
|
stx_cb_data.v.chr.ch = ep->v.chr.ch;
|
|
stx_cb_data.v.chr.shift = ep->v.chr.shift;
|
|
stx_cb_data.v.chr.control = ep->v.chr.control;
|
|
stx_cb_data.v.chr.is_paste = FALSE;
|
|
stx_cb_data.v.chr.refused = FALSE;
|
|
} else
|
|
stx_cb_data.v.refused = FALSE;
|
|
(*STXP(stx)->stx_cb)(&stx_cb_data);
|
|
/* retval = FALSE if event refused */
|
|
if (cb_reason == STX_CB_CHAR)
|
|
{
|
|
if (! stx_cb_data.v.chr.refused)
|
|
ep->v.chr.ch = stx_cb_data.v.chr.ch;
|
|
return (! stx_cb_data.v.chr.refused);
|
|
}
|
|
else
|
|
return (! stx_cb_data.v.refused);
|
|
}
|
|
|
|
void
|
|
stx_focus_cb(long stx, BOOLEAN set)
|
|
{
|
|
if (set != STXP(stx)->has_focus)
|
|
{
|
|
if (set)
|
|
stx_start_edit(stx);
|
|
else
|
|
stx_stop_edit(stx);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
The parameter gaining_focus is here so that on an E_MOUSE_DOWN, if the
|
|
field is gaining the focus, and XI_PREF_AUTOSEL_ON_MOUSE is TRUE, then
|
|
txt_event knows to select the entire field, not set an insertion point.
|
|
*/
|
|
static BOOLEAN near
|
|
send_txt_event(STX stx, TXT_DATA *txt, EVENT *ep,
|
|
BOOLEAN gaining_focus)
|
|
{
|
|
BOOLEAN retval;
|
|
int ch;
|
|
|
|
if (ep->type == E_CHAR)
|
|
{
|
|
ch = ep->v.chr.ch;
|
|
if ((ch >= ' ' || ch == K_CLEAR || ch == K_DEL ||
|
|
ch == '\b') && ch != K_BTAB && ch != K_UP && ch != K_DOWN)
|
|
{
|
|
retval = do_stx_cb(stx, STX_CB_CHAR, ep);
|
|
/* retval = FALSE if event refused */
|
|
if (! retval)
|
|
return FALSE;
|
|
}
|
|
}
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
EVENT e;
|
|
|
|
e = *ep;
|
|
if (ep->type == E_CHAR && (ep->v.chr.ch == '\t' || ep->v.chr.ch == K_BTAB))
|
|
retval = FALSE;
|
|
else
|
|
{
|
|
if (xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME))
|
|
{
|
|
if (ep->type == E_MOUSE_DBL)
|
|
{
|
|
STXP(stx)->timer_id = xvt_timer_create(STXP(stx)->win,
|
|
xi_get_pref(XI_PREF_TRIPLE_CLICK_TIME));
|
|
STXP(stx)->timer_set = TRUE;
|
|
}
|
|
}
|
|
if (ep->type == E_TIMER &&
|
|
ep->v.timer.id == STXP(stx)->timer_id)
|
|
{
|
|
xvt_timer_destroy(ep->v.timer.id);
|
|
STXP(stx)->timer_id = 0;
|
|
STXP(stx)->timer_set = FALSE;
|
|
}
|
|
if (ep->type == E_MOUSE_DOWN &&
|
|
STXP(stx)->timer_set)
|
|
{
|
|
xvt_timer_destroy(STXP(stx)->timer_id);
|
|
STXP(stx)->timer_set = FALSE;
|
|
STXP(stx)->timer_id = 0;
|
|
stx_set_sel(stx, 0, 32000);
|
|
return FALSE;
|
|
}
|
|
if (ep->type == E_UPDATE)
|
|
draw_text_edit_border(STXP(stx));
|
|
if (ep->type != E_COMMAND)
|
|
retval = xvt_tx_process_event(STXP(stx)->win, &e);
|
|
if (ep->type == E_COMMAND && xi_get_pref(XI_PREF_MULTILINE_QUICK_PASTE))
|
|
retval = xvt_tx_process_event(STXP(stx)->win, &e);
|
|
if ( retval )
|
|
{
|
|
((XI_OBJ*)STXP(stx)->app_data)->itf->v.itf->chg_flag = TRUE;
|
|
do_stx_cb( stx, STX_CB_CHANGE, ep );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
retval = txt_event(txt, ep, gaining_focus);
|
|
|
|
/* check flags */
|
|
if (txt->flags & TXT_FLAG_TEXT)
|
|
{
|
|
((XI_OBJ*)STXP(stx)->app_data)->itf->v.itf->chg_flag = TRUE;
|
|
do_stx_cb(stx, STX_CB_CHANGE, ep);
|
|
}
|
|
/* reset flags */
|
|
txt->flags = 0;
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
BOOLEAN
|
|
stx_event(STX stx, EVENT *ep)
|
|
{
|
|
STX_DATA *stxp = STXP(stx);
|
|
BOOLEAN retval = TRUE;
|
|
|
|
switch(ep->type)
|
|
{
|
|
case E_SIZE:
|
|
retval = FALSE;
|
|
break;
|
|
case E_TIMER:
|
|
if (stxp->txt)
|
|
send_txt_event(stx, stxp->txt, ep, FALSE);
|
|
retval = FALSE;
|
|
break;
|
|
case E_UPDATE:
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (stxp->use_text_edit)
|
|
{
|
|
if ((stxp->attrib & STX_ATR_VISIBLE) != 0)
|
|
{
|
|
EVENT e;
|
|
CBRUSH cbrush;
|
|
RCT r;
|
|
|
|
e = *ep;
|
|
if (ep->type == E_UPDATE)
|
|
draw_text_edit_border(STXP(stx));
|
|
cbrush.color = STXP(stx)->back_color;
|
|
cbrush.pat = PAT_SOLID;
|
|
xi_set_cbrush(STXP(stx)->win, &cbrush);
|
|
xi_set_cpen(STXP(stx)->win, &hollow_cpen);
|
|
r = STXP(stx)->rct;
|
|
if (STXP(stx)->attrib & XI_ATR_BORDER || STXP(stx)->attrib & XI_ATR_FOCUSBORDER)
|
|
xi_inflate_rect(&r, -1);
|
|
xi_inflate_rect(&r, -2);
|
|
xi_draw_rect(STXP(stx)->win, &r);
|
|
xvt_tx_process_event(stxp->win, &e);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
redraw_stx(stx, TRUE, FALSE);
|
|
retval = FALSE;
|
|
break;
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
{
|
|
BOOLEAN gaining_focus = FALSE;
|
|
|
|
/* check for focus acquisition */
|
|
if (xvt_rect_has_point(&stxp->rct, ep->v.mouse.where) &&
|
|
(stxp->attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE)) ==
|
|
(XI_ATR_ENABLED | XI_ATR_VISIBLE))
|
|
{
|
|
stxp->have_mouse = TRUE;
|
|
if (!STXP(stx)->has_focus)
|
|
{
|
|
if (!do_stx_cb(stx, STX_CB_FOCUS, ep))
|
|
{
|
|
stxp->have_mouse = FALSE;
|
|
break;
|
|
}
|
|
gaining_focus = TRUE;
|
|
}
|
|
/* the stx may have lost the focus, due to a field being
|
|
disabled, in which case, stxp->txt == NULL */
|
|
if (stxp->txt || stxp->use_text_edit)
|
|
{
|
|
send_txt_event(stx, stxp->txt, ep, gaining_focus);
|
|
if (stxp->txt)
|
|
xi_trap_mouse(stxp->win);
|
|
if (ep->type == E_MOUSE_DBL)
|
|
do_stx_cb(stx, STX_CB_DBL, ep);
|
|
}
|
|
}
|
|
else
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
case E_MOUSE_UP:
|
|
if (stxp->has_focus)
|
|
{
|
|
send_txt_event(stx, stxp->txt, ep, FALSE);
|
|
xi_release_mouse();
|
|
stxp->have_mouse = FALSE;
|
|
}
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
{
|
|
unsigned long attrib;
|
|
|
|
if (stxp->has_focus)
|
|
send_txt_event(stx, stxp->txt, ep, FALSE);
|
|
attrib = stxp->attrib & (XI_ATR_ENABLED | XI_ATR_VISIBLE);
|
|
if ((attrib != (XI_ATR_ENABLED | XI_ATR_VISIBLE)) ||
|
|
(! xvt_rect_has_point(&stxp->rct, ep->v.mouse.where)))
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
case E_CHAR:
|
|
retval = send_txt_event(stx, stxp->txt, ep, FALSE);
|
|
break;
|
|
case E_KILL_WINDOW:
|
|
retval = FALSE;
|
|
break;
|
|
case E_COMMAND:
|
|
retval = send_txt_event(stx, stxp->txt, ep, FALSE);
|
|
break;
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
unsigned long
|
|
stx_get_attrib(STX stx)
|
|
{
|
|
return(STXP(stx)->attrib);
|
|
}
|
|
|
|
int
|
|
stx_get_cid(STX stx)
|
|
{
|
|
return(STXP(stx)->cid);
|
|
}
|
|
|
|
void
|
|
stx_get_sel(STX stx, int *c1, int *c2)
|
|
{
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
int accum_cnt;
|
|
T_PNUM par;
|
|
T_PNUM start_par, end_par;
|
|
T_LNUM start_line, end_line;
|
|
T_CNUM start_char, end_char;
|
|
BOOLEAN ex;
|
|
|
|
accum_cnt = 0;
|
|
xvt_tx_get_sel(STXP(stx)->txedit, &start_par, &start_line, &start_char,
|
|
&end_par, &end_line, &end_char);
|
|
ex = FALSE;
|
|
for (par = 0; par <= start_par; par++)
|
|
{
|
|
T_LNUM nbr_lins, lin;
|
|
|
|
nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
|
|
for (lin = 0; lin < nbr_lins; lin++)
|
|
{
|
|
if (par == start_par && lin == start_line)
|
|
{
|
|
accum_cnt += start_char;
|
|
ex = TRUE;
|
|
break;
|
|
}
|
|
accum_cnt += xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
|
|
}
|
|
if (ex)
|
|
break;
|
|
accum_cnt += 1; /* add eol at end of paragraph */
|
|
}
|
|
*c1 = accum_cnt;
|
|
if (start_par == end_par && start_line == end_line &&
|
|
start_char == end_char)
|
|
{
|
|
*c2 = accum_cnt;
|
|
return;
|
|
}
|
|
ex = FALSE;
|
|
for (par = start_par; par <= end_par; par++)
|
|
{
|
|
T_LNUM nbr_lins, lin;
|
|
|
|
nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
|
|
for (lin = 0; lin < nbr_lins; lin++)
|
|
{
|
|
if (par == end_par && lin == end_line)
|
|
{
|
|
accum_cnt += end_char;
|
|
if (par == start_par && lin == start_line)
|
|
accum_cnt -= start_char;
|
|
ex = TRUE;
|
|
break;
|
|
}
|
|
accum_cnt += xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
|
|
if (par == start_par && lin == start_line)
|
|
accum_cnt -= start_char;
|
|
}
|
|
if (ex)
|
|
break;
|
|
accum_cnt += 1; /* add eol at end of paragraph */
|
|
}
|
|
*c2 = accum_cnt;
|
|
return;
|
|
}
|
|
#endif
|
|
if (STXP(stx)->has_focus)
|
|
{
|
|
*c1 = STXP(stx)->txt->selstart;
|
|
*c2 = STXP(stx)->txt->selstop;
|
|
}
|
|
else
|
|
*c1 = *c2 = 0;
|
|
}
|
|
|
|
RCT *
|
|
stx_get_rect(STX stx, RCT *rct)
|
|
{
|
|
*rct = STXP(stx)->rct;
|
|
return(rct);
|
|
}
|
|
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
static void
|
|
tx_get_text(TXEDIT tx, char *string, int string_len)
|
|
{
|
|
char *s;
|
|
int slen, cnt, nbr_pars;
|
|
unsigned len;
|
|
|
|
slen = 0;
|
|
s = NULL;
|
|
nbr_pars = xvt_tx_get_num_pars(tx);
|
|
for (cnt = 0; cnt < nbr_pars; ++cnt)
|
|
{
|
|
int nbr_lines, cnt2;
|
|
|
|
nbr_lines = xvt_tx_get_num_par_lines(tx, (short)cnt);
|
|
for (cnt2 = 0; cnt2 < nbr_lines; ++cnt2)
|
|
{
|
|
char *str;
|
|
int old_len;
|
|
|
|
xvt_tx_get_line(tx, (short)cnt, A_LOCK, (short)cnt2, NULL);
|
|
str = xvt_tx_get_line(tx, (short)cnt, A_GET, (short)cnt2, &len);
|
|
old_len = slen;
|
|
slen = slen + len;
|
|
if (s)
|
|
s = (char *)xi_tree_realloc(s, slen + 2);
|
|
else
|
|
s = (char *)xi_tree_malloc(slen + 2, NULL);
|
|
|
|
gstrncpy(&s[old_len], str, len);
|
|
}
|
|
slen++;
|
|
#if XIWS == MACWS
|
|
s[slen - 1] = '\r';
|
|
#else
|
|
s[slen - 1] = '\n';
|
|
#endif
|
|
}
|
|
if (! slen)
|
|
string[0] = '\0';
|
|
else
|
|
{
|
|
s[slen - 1] = '\0';
|
|
gstrncpy(string, s, string_len);
|
|
string[string_len - 1] = '\0';
|
|
xi_tree_free(s);
|
|
}
|
|
}
|
|
|
|
static int
|
|
tx_get_len(TXEDIT tx)
|
|
{
|
|
int nbr_pars, cnt, charcnt;
|
|
|
|
charcnt = 0;
|
|
nbr_pars = xvt_tx_get_num_pars(tx);
|
|
for (cnt = 0; cnt < nbr_pars; ++cnt)
|
|
{
|
|
int nbr_lines, cnt2;
|
|
|
|
nbr_lines = xvt_tx_get_num_par_lines(tx, (short)cnt);
|
|
for (cnt2 = 0; cnt2 < nbr_lines; ++cnt2)
|
|
charcnt += (xvt_tx_get_num_chars(tx, (short)cnt, (short)cnt2) + 1);
|
|
}
|
|
return charcnt;
|
|
}
|
|
#endif
|
|
|
|
char *
|
|
stx_get_text(STX stx, char *s, int len)
|
|
{
|
|
char *b;
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
if (s)
|
|
{
|
|
tx_get_text(STXP(stx)->txedit, s, len);
|
|
b = s;
|
|
}
|
|
else
|
|
{
|
|
int len;
|
|
|
|
len = tx_get_len(STXP(stx)->txedit);
|
|
if (STXP(stx)->buf)
|
|
STXP(stx)->buf = (char*)xi_tree_realloc(STXP(stx)->buf, len);
|
|
else
|
|
STXP(stx)->buf = (char*)xi_tree_malloc(len, NULL);
|
|
tx_get_text(STXP(stx)->txedit, STXP(stx)->buf, len);
|
|
b = STXP(stx)->buf;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
b = STXP(stx)->text;
|
|
if (s)
|
|
tgstrncpy(s, b, len);
|
|
return b;
|
|
}
|
|
|
|
void
|
|
stx_set_bufsize(STX stx, short size)
|
|
{
|
|
/*
|
|
TODO
|
|
if (STXP(stx)->use_text_edit)
|
|
set buffer size
|
|
*/
|
|
STXP(stx)->text = (char *)xi_tree_realloc(STXP(stx)->text, (size_t)size);
|
|
STXP(stx)->text[size - 1] = '\0';
|
|
STXP(stx)->text_size = size;
|
|
}
|
|
|
|
void
|
|
stx_set_attrib(STX stx, unsigned long attrib)
|
|
{
|
|
unsigned long do_redraw;
|
|
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
if (attrib & XI_ATR_VISIBLE)
|
|
{
|
|
if (!(STXP(stx)->attrib & XI_ATR_VISIBLE))
|
|
xvt_tx_resume(STXP(stx)->txedit);
|
|
} else
|
|
{
|
|
if (STXP(stx)->attrib & XI_ATR_VISIBLE)
|
|
xvt_tx_suspend(STXP(stx)->txedit);
|
|
}
|
|
}
|
|
|
|
do_redraw = ((STXP(stx)->attrib ^ attrib) & STX_REDRAW_ATR);
|
|
STXP(stx)->attrib = attrib;
|
|
if (do_redraw)
|
|
xi_invalidate_rect(STXP(stx)->win, &(STXP(stx)->rct));
|
|
}
|
|
|
|
void
|
|
stx_set_focus(STX stx)
|
|
{
|
|
if (xvt_scr_get_focus_vobj()!= STXP(stx)->win)
|
|
{
|
|
xvt_scr_set_focus_vobj(STXP(stx)->win);
|
|
}
|
|
if (!STXP(stx)->has_focus)
|
|
stx_start_edit(stx);
|
|
}
|
|
|
|
void
|
|
stx_set_pos(STX stx, PNT p)
|
|
{
|
|
int dh, dv;
|
|
|
|
dh = p.h - STXP(stx)->rct.left;
|
|
dv = p.v - STXP(stx)->rct.top;
|
|
|
|
STXP(stx)->rct.top += dv;
|
|
STXP(stx)->rct.left += dh;
|
|
STXP(stx)->rct.bottom += dv;
|
|
STXP(stx)->rct.right += dh;
|
|
}
|
|
|
|
void
|
|
stx_set_sel(STX stx, int c1, int c2)
|
|
{
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
int accum_cnt, selidx;
|
|
int sel[2];
|
|
T_PNUM parsel[2], par, nbr_pars;
|
|
T_LNUM linsel[2], lin, nbr_lins;
|
|
T_CNUM chrsel[2], nbr_chrs;
|
|
|
|
accum_cnt = 0;
|
|
selidx = 0;
|
|
sel[0] = c1;
|
|
sel[1] = c2;
|
|
nbr_pars = xvt_tx_get_num_pars(STXP(stx)->txedit);
|
|
for (par = 0; par < nbr_pars; par++)
|
|
{
|
|
nbr_lins = xvt_tx_get_num_par_lines(STXP(stx)->txedit, par);
|
|
for (lin = 0; lin < nbr_lins; lin++)
|
|
{
|
|
nbr_chrs = xvt_tx_get_num_chars(STXP(stx)->txedit, par, lin);
|
|
while ((int)(accum_cnt + nbr_chrs) >= sel[selidx])
|
|
{
|
|
parsel[selidx] = par;
|
|
linsel[selidx] = lin;
|
|
chrsel[selidx] = sel[selidx] - accum_cnt;
|
|
selidx++;
|
|
if (selidx >= 2)
|
|
goto set_sel;
|
|
}
|
|
accum_cnt += nbr_chrs;
|
|
}
|
|
accum_cnt += 1; /* add eol at end of paragraph */
|
|
}
|
|
while (selidx < 2)
|
|
{
|
|
parsel[selidx] = nbr_pars-1;
|
|
linsel[selidx] = nbr_lins-1;
|
|
chrsel[selidx] = nbr_chrs-1;
|
|
if (selidx == 1)
|
|
chrsel[selidx] = nbr_chrs;
|
|
selidx++;
|
|
}
|
|
set_sel:
|
|
xvt_tx_set_sel(STXP(stx)->txedit, parsel[0], linsel[0], chrsel[0],
|
|
parsel[1], linsel[1], chrsel[1]);
|
|
return;
|
|
}
|
|
#endif
|
|
if (!STXP(stx)->has_focus)
|
|
stx_start_edit(stx);
|
|
txt_set_sel(STXP(stx)->txt, c1, c2);
|
|
}
|
|
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
static void do_tx_add_par(TXEDIT tx, int limit, char *text)
|
|
{
|
|
char *s, *bp, *ep;
|
|
int cnt, nbr_pars;
|
|
|
|
nbr_pars = xvt_tx_get_num_pars(tx);
|
|
xvt_tx_suspend(tx);
|
|
for (cnt = 0; cnt < nbr_pars; ++cnt)
|
|
xvt_tx_rem_par(tx, 0);
|
|
s = (char *)xi_tree_malloc(limit + 1, NULL);
|
|
bp = text;
|
|
if (text[0] == '\0')
|
|
{
|
|
xvt_tx_add_par(tx, (unsigned short)USHRT_MAX, s);
|
|
xvt_tx_resume(tx);
|
|
xi_tree_free(s);
|
|
return;
|
|
}
|
|
while (TRUE)
|
|
{
|
|
int cnt, min_cnt;
|
|
|
|
if (*bp == '\0')
|
|
break;
|
|
ep = bp;
|
|
cnt = 0;
|
|
while (*ep != '\r' && *ep != '\n' && *ep != '\0')
|
|
{
|
|
++ep;
|
|
++cnt;
|
|
}
|
|
min_cnt = min(limit, cnt);
|
|
gstrncpy(s, bp, min_cnt);
|
|
s[min_cnt] = '\0';
|
|
xvt_tx_add_par(tx, (unsigned short)USHRT_MAX, s);
|
|
if (*ep == '\0')
|
|
break;
|
|
bp = ep + 1;
|
|
}
|
|
xvt_tx_resume(tx);
|
|
xi_tree_free(s);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
stx_set_text(STX stx, char *s)
|
|
{
|
|
#ifndef XI_DONT_USE_TX_EDIT
|
|
if (STXP(stx)->use_text_edit)
|
|
{
|
|
do_tx_add_par(STXP(stx)->txedit, STXP(stx)->text_size, s);
|
|
xvt_tx_set_sel(STXP(stx)->txedit, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (STXP(stx)->has_focus)
|
|
txt_set_text(STXP(stx)->txt, s);
|
|
else
|
|
{
|
|
tgstrncpy(STXP(stx)->text, s, STXP(stx)->text_size);
|
|
if ((STXP(stx)->attrib & STX_ATR_VISIBLE) != 0
|
|
&& !xi_half_baked(STXP(stx)->win))
|
|
redraw_stx(stx, FALSE, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
stx_set_app_data(STX stx, long data)
|
|
{
|
|
STXP(stx)->app_data = data;
|
|
}
|
|
|
|
long
|
|
stx_get_app_data(STX stx)
|
|
{
|
|
return(STXP(stx)->app_data);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------
|
|
function: draw_text_edit_border
|
|
stxptr:
|
|
process: TODO
|
|
---------------------------------------------------------------------*/
|
|
static void
|
|
draw_text_edit_border(STX_DATA *stxptr)
|
|
{
|
|
RCT rct;
|
|
|
|
xi_set_draw_mode(stxptr->win, M_COPY);
|
|
xi_set_cpen(stxptr->win, &black_cpen);
|
|
xi_set_cbrush(stxptr->win, &hollow_cbrush);
|
|
rct = stxptr->rct;
|
|
if (stxptr->attrib & XI_ATR_BORDER)
|
|
{
|
|
xi_draw_rect(stxptr->win, &rct);
|
|
xi_inflate_rect(&rct, -1);
|
|
}
|
|
else
|
|
{
|
|
if (stxptr->attrib & XI_ATR_FOCUSBORDER)
|
|
{
|
|
COLOR pen_color;
|
|
CPEN cpen;
|
|
|
|
if (stxptr->has_focus)
|
|
{
|
|
pen_color = COLOR_BLACK;
|
|
}
|
|
else
|
|
{
|
|
static XI_OBJ *itf;
|
|
COLOR back_color;
|
|
|
|
itf = xi_get_itf(stxptr->win);
|
|
back_color = itf->v.itf->back_color;
|
|
if (back_color)
|
|
pen_color = back_color;
|
|
else
|
|
pen_color = xi_get_pref(XI_PREF_COLOR_CTRL);
|
|
}
|
|
cpen.color = pen_color;
|
|
cpen.pat = PAT_SOLID;
|
|
cpen.width = 1;
|
|
cpen.style = P_SOLID;
|
|
xi_set_cpen(stxptr->win, &cpen);
|
|
xi_draw_rect(stxptr->win, &rct);
|
|
xi_inflate_rect(&rct, -1);
|
|
}
|
|
}
|
|
if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK) == FALSE)
|
|
||((stxptr->well == FALSE) && (stxptr->platform == FALSE)))
|
|
return;
|
|
xi_draw_3d_rect(stxptr->win, &rct, stxptr->well, 1, 0L, 0L, 0L);
|
|
}
|
|
|
|
RCT*
|
|
stx_get_inside_rect( STX stx, RCT* rect )
|
|
{
|
|
STX_DATA* stx_ptr = (STX_DATA*)stx;
|
|
|
|
*rect = stx_ptr->rct;
|
|
if (((BOOLEAN)xi_get_pref(XI_PREF_3D_LOOK)) &&
|
|
((stx_ptr->well == TRUE) || (stx_ptr->platform == TRUE)))
|
|
xi_inflate_rect(rect, -2);
|
|
return rect;
|
|
}
|
|
|