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
5807 lines
158 KiB
C
Executable File
5807 lines
158 KiB
C
Executable File
/*******************************************************************************
|
|
* Copyright 1991-1995 by ORCA Software, Inc. *
|
|
* *
|
|
* All rights reserved. May not be reproduced or distribfuted, 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 "xilm.h"
|
|
#include "xiutils.h"
|
|
#include "xidisply.h"
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Metrics Documentation
|
|
lmp->rct.top and lmp->rct.bottom are the top and bottom of the list, excluding the
|
|
horizontal scroll bar.
|
|
lmp->rct.left is the physical left position of the list
|
|
lmp->rct.right is the position of the physical right position of the list. However, if the
|
|
list is a horizontal scrolling list, then lmp->rct.right will be beyond lmp->width.
|
|
It is useful for drawing using the virtual functions, but it is necessary to subtract
|
|
lmp->rct.left before calling the drawing functions, because the drawing functions will
|
|
add lmp->rct.left to the h values before drawing.
|
|
-------------------------------------------------------------------------*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
ROWS: REALIZED, and ALLOCATED-USED, and ALLOCATED-NOT USED.
|
|
|
|
In the realized rows array, there are three types of rows.
|
|
|
|
First, there are rows that are not being used at all. These are the rows
|
|
after lmp->nbr_realized_rows. The record handles for these rows are 0L.
|
|
|
|
Second, there are rows that are allocated, and used. These are the rows
|
|
after 0, and before lmp->nbr_realized_rows.
|
|
The record handles for these rows are not 0L.
|
|
|
|
Third, there are rows that are allocated, and not used. These are the rows
|
|
after 0, and less than lmp->nbr_realized_rows.
|
|
The record handles for these rows are not 0L. If one of these rows is requested
|
|
to be allocated, and the handle is not 0L, then then allocation event is not
|
|
done. If one of these rows is requested to be freed, and the handle is 0L,
|
|
then the free event is not done.
|
|
-------------------------------------------------------------------------*/
|
|
|
|
/* Error codes: 20900 - 20918 */
|
|
|
|
#define SELECT_CELLS_OFFSET 1
|
|
|
|
#define LM_COL_ATTR(lm, col) (LMP(lm)->lm_column_data[col]->attrib)
|
|
#define LM_CELL_TEXT(lm, row, col) (LMP(lm)->buffer[row] + LMP(lm)->lm_column_data[col]->text_offset)
|
|
|
|
#define LM_REDRAW_ATR (LM_ATR_VISIBLE | LM_ATR_ENABLED)
|
|
#define LM_REDRAW_COL_ATR (LM_COL_ATR_ENABLED | LM_COL_ATR_RJUST | LM_COL_ATR_PASSWORD | LM_COL_ATR_SELECTED)
|
|
#define LM_REDRAW_ROW_ATR (LM_ROW_ATR_ENABLED | LM_ROW_ATR_SELECTED)
|
|
|
|
#define LM_REDRAW_CELL_ATR (LM_CELL_ATR_SELECTED | LM_CELL_ATR_RJUST | LM_CELL_ATR_HCENTER)
|
|
|
|
#define BUFLEN 256
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_adj_v
|
|
lmp: current lmp
|
|
v: to vertical coord to convert
|
|
-------------------------------------------------------------------------*/
|
|
#define lm_adj_v(lmp, v) (v = v + lmp->mlr.top + lmp->rrr_offset)
|
|
|
|
static CBRUSH lm_white_cbrush;
|
|
static CPEN lm_black_cpen;
|
|
static DRAW_CTOOLS lm_normal_ctools;
|
|
static BOOLEAN lm_tools_inited = FALSE;
|
|
|
|
typedef struct {
|
|
BOOLEAN needs_update;
|
|
RCT rct;
|
|
RCT prct;
|
|
} ROW_INFO;
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_last_vis
|
|
lmp: current lmp
|
|
process: calculates the last fully visible column in the list
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_calc_last_vis(LM_DATA *lmp)
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
int l1;
|
|
|
|
if (! lmp->pixel_width)
|
|
lmp->last_vis = lmp->nbr_columns - 1;
|
|
else
|
|
{
|
|
lmp->last_vis = lmp->first_vis;
|
|
for (l1 = lmp->first_vis + 1; l1 < lmp->nbr_columns; ++l1)
|
|
{
|
|
column_data = lmp->lm_column_data[l1];
|
|
if ((column_data->x_pix_pos - lmp->delta_x + column_data->pix_width)
|
|
>= lmp->pixel_width)
|
|
{
|
|
lmp->last_vis = l1 - 1;
|
|
return;
|
|
}
|
|
lmp->last_vis = l1;
|
|
}
|
|
if (l1 == lmp->nbr_columns)
|
|
lmp->last_vis = l1 - 1;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_col_spacing
|
|
returns: column spacing
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_col_spacing(void)
|
|
{
|
|
return (2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET) + RULE_WIDTH_V);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_left_most_far_right_column
|
|
lmp: current lmp
|
|
nbr_columns: column, from which we will count back
|
|
notes: This function is also used when the users presses page up on the
|
|
horizontal scroll bar, to determine the new left most column.
|
|
Get the column number for the column that would be visible if the
|
|
list is scrolled entirely over to the right. This is necessary
|
|
to compute the position of the horizontal thumb, and other reasons.
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_left_most_far_right_col(LM_DATA *lmp, int nbr_columns)
|
|
{
|
|
int width, i;
|
|
|
|
#if XVTWS == WMWS
|
|
width = lmp->pixel_width;
|
|
#else
|
|
width = lmp->pixel_width + (int)xi_get_pref(XI_PREF_COLUMN_OFFSET)
|
|
+ RULE_WIDTH_V;
|
|
#endif
|
|
for (i = 0; i < min(lmp->fixed_columns, lmp->nbr_columns); ++i)
|
|
width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing();
|
|
for (i = nbr_columns - 1; i >= lmp->fixed_columns; --i)
|
|
{
|
|
width -= lmp->lm_column_data[i]->pix_width + lm_get_col_spacing();
|
|
if (width <= 0)
|
|
break;
|
|
}
|
|
return (i + 1);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_cell_rect
|
|
rctp: pointer to rectangle to be filled in
|
|
lm: current lm
|
|
row: relevant row
|
|
col: relevant column
|
|
inner: if TRUE, get the inner rectangle of the cell, else get the outer
|
|
rectangle of the cell
|
|
physical_rct: if TRUE, get the physical rectangle, else get the virtual
|
|
rectangle
|
|
notes: This function is called before starting the text edit object for the cell.
|
|
returns: rctp
|
|
-------------------------------------------------------------------------*/
|
|
RCT *
|
|
lm_get_cell_rect(RCT *rctp, LM lm, int row, int col, BOOLEAN inner, BOOLEAN physical_rct)
|
|
{
|
|
LM_COLUMN_DATA *temp_lmcd;
|
|
int col_offset;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
temp_lmcd = lmp->lm_column_data[col];
|
|
|
|
rctp->top = lmp->pix_offsets[row];
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row] - RULE_WIDTH_V;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row];
|
|
CTOS_END;
|
|
#endif
|
|
|
|
rctp->left = temp_lmcd->x_pix_pos;
|
|
rctp->right = rctp->left + temp_lmcd->pix_width + 2 *
|
|
(int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
|
|
if (inner)
|
|
{
|
|
rctp->left += col_offset;
|
|
rctp->right -= col_offset;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
rctp->top += RULE_Y_OFFSET_TOP;
|
|
rctp->bottom -= RULE_Y_OFFSET_BOTTOM;
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
if (physical_rct)
|
|
{
|
|
rctp->left += lmp->rct.left;
|
|
rctp->right += lmp->rct.left;
|
|
|
|
if (rctp->left >= lmp->vir_left)
|
|
{
|
|
rctp->left -= lmp->delta_x;
|
|
rctp->right -= lmp->delta_x;
|
|
}
|
|
|
|
rctp->top = rctp->top + lmp->rrr_offset + lmp->mlr.top;
|
|
rctp->bottom = rctp->bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
}
|
|
return(rctp);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_row_rect
|
|
rctp: pointer to rectangle to be filled in
|
|
lm: current lm
|
|
row: relevant row
|
|
returns: rctp
|
|
-------------------------------------------------------------------------*/
|
|
RCT*
|
|
lm_get_row_rect(RCT *rctp, LM lm, int row)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
rctp->top = lmp->pix_offsets[row];
|
|
rctp->bottom = rctp->top + lmp->pix_heights[row];
|
|
|
|
rctp->left = lmp->rct.left + BORDER_WIDTH;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
rctp->right = lmp->rct.right - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
rctp->right = lmp->rct.right;
|
|
CTOS_END;
|
|
#endif
|
|
if (lmp->pixel_width)
|
|
rctp->right = rctp->left + lmp->pixel_width;
|
|
|
|
return(rctp);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_adj_h
|
|
lmp: current lmp
|
|
h: pointer to horizontal coord to convert
|
|
returns: TRUE if position is visible
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_adj_h(LM_DATA *lmp, short *h)
|
|
{
|
|
if (*h >= lmp->vir_left)
|
|
{
|
|
RCT r;
|
|
|
|
*h -= lmp->delta_x;
|
|
if (*h < lmp->vir_left)
|
|
return FALSE;
|
|
r = lmp->rct;
|
|
if (lmp->pixel_width)
|
|
r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
return (*h <= r.right);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_rct
|
|
lmp: current lmp
|
|
r: pointer to rectangle to be filled in
|
|
returns: r
|
|
-------------------------------------------------------------------------*/
|
|
RCT*
|
|
lm_get_list_rct(LM_DATA *lmp, RCT *r)
|
|
{
|
|
*r = lmp->rct;
|
|
if (lmp->pixel_width)
|
|
r->right = r->left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
return r;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_fixed_columns
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_fixed_columns( LM lm, int new_fixed_count )
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
int col_spacing, i;
|
|
RCT rct_to_invalidate, rct;
|
|
|
|
if (new_fixed_count > lmp->nbr_columns)
|
|
new_fixed_count = lmp->nbr_columns;
|
|
col_spacing = lm_get_col_spacing();
|
|
lmp->fixed_columns = new_fixed_count;
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
lmp->delta_x = 0;
|
|
|
|
/* calculate the left boundary of the virtual space for the list */
|
|
lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
|
|
for (i = 0; i < min(lmp->nbr_columns, lmp->fixed_columns); ++i)
|
|
{
|
|
lmp->vir_left += lmp->lm_column_data[i]->pix_width;
|
|
lmp->vir_left += col_spacing;
|
|
}
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
lm_get_list_rct(lmp, &rct_to_invalidate);
|
|
xi_invalidate_rect(lmp->win, &rct_to_invalidate);
|
|
lm_set_hscroll_range((LM)lmp);
|
|
lm_set_hscroll_bar((LM) lmp);
|
|
xi_get_hsb_rect(lmp->list_obj, &rct);
|
|
xvt_vobj_move(lmp->list_obj->v.list->hsb_win, &rct);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_stop_edit
|
|
lm: current lm
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_stop_edit(LM lm, BOOLEAN do_update, int row, int column)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
int new_row_height;
|
|
|
|
if (lmp->txt)
|
|
{
|
|
txt_hide_caret(lmp->txt);
|
|
txt_caret(lmp->txt, FALSE);
|
|
xi_tree_free((char *)lmp->txt);
|
|
lmp->txt = NULL;
|
|
new_row_height = lm_calculate_row_height(lmp, row);
|
|
if (new_row_height != lmp->old_row_height)
|
|
{
|
|
xvt_dwin_update(lmp->win);
|
|
lm_set_row_height(lm, row, new_row_height,
|
|
FALSE, lmp->old_row_height, TRUE);
|
|
xvt_dwin_update(lmp->win);
|
|
}
|
|
}
|
|
/*
|
|
if lmp->row_focus_border is TRUE, don't redraw, because old
|
|
focus row will be invalidated
|
|
*/
|
|
if (do_update && !lmp->txt_is_invisible)
|
|
redraw_cell(lm, row, column, FALSE );
|
|
lmp->txt_is_invisible = FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_focus_cb
|
|
lm: current lm
|
|
row: relevant row
|
|
column: relevant column
|
|
set: if TRUE, start editing on specified cell
|
|
if FALSE, stop editing altogether
|
|
-------------------------------------------------------------------------*/
|
|
void lm_focus_cb( long lm, int row, int column, BOOLEAN vert_scrolled,
|
|
BOOLEAN set)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
|
|
if (set)
|
|
{
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
|
|
if ( lmp->txt == NULL || row != focus_row || column != focus_column
|
|
|| vert_scrolled != is_vert_scrolled )
|
|
{
|
|
BOOLEAN remake_vis = FALSE;
|
|
|
|
if (! lmp->focus_rec)
|
|
{
|
|
lm_make_invis(lmp);
|
|
remake_vis = TRUE;
|
|
}
|
|
lm_set_focus_cell(lmp, row, column, vert_scrolled );
|
|
if (remake_vis)
|
|
lm_force_vis(lmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20930",
|
|
20930, "lm_focus_cb: Internal Error");
|
|
#if 0
|
|
/*
|
|
the following line was never executed when doing coverage. If the
|
|
above assert gets triggered, research, and uncomment the following line.
|
|
Remove after 7/31/95.
|
|
*/
|
|
lm_start_edit(lm, row, column);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int idx;
|
|
BOOLEAN found = FALSE;
|
|
|
|
lm_stop_edit(lm, TRUE, row, column);
|
|
if (lmp->focus_rec)
|
|
{
|
|
lmp->txt_is_invisible = FALSE;
|
|
for (idx = 0; idx < lmp->nbr_realized_rows; ++idx)
|
|
{
|
|
if (lmp->recs[idx] == lmp->focus_rec)
|
|
{
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
{
|
|
lmp->focus_rec = 0L;
|
|
lmp->txt_is_invisible = FALSE;
|
|
}
|
|
else
|
|
{
|
|
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->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;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete
|
|
lm: current lm
|
|
notes: do not call this function in response to E_KILL_WINDOW.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_delete(LM lm)
|
|
{
|
|
RCT r;
|
|
LM_DATA *lmp = LMP(lm);
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
|
|
lm_stop_edit(lm, TRUE, focus_row, focus_column);
|
|
lm_remove_all_rows( lmp, TRUE );
|
|
lm_get_list_rct(lmp, &r);
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
xi_tree_free((char *)lm);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_x_pix_pos
|
|
lm: current lm
|
|
lcdata: column data pointer
|
|
position: position of column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calc_x_pix_pos(LM lm, LM_COLUMN_DATA *lcdata, int position)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
LM_COLUMN_DATA *lmcd;
|
|
|
|
if (position)
|
|
lmcd = lmp->lm_column_data[position - 1];
|
|
lcdata->x_pix_pos = (! position) ? BORDER_WIDTH :
|
|
lmcd->x_pix_pos + lmcd->pix_width + lm_get_col_spacing();
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to invalidate
|
|
adj_h: adjust the horizontal coords
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_h)
|
|
{
|
|
RCT r;
|
|
|
|
r = *rctp;
|
|
if (adj_h)
|
|
{
|
|
lm_adj_h(lmp, &r.left);
|
|
lm_adj_h(lmp, &r.right);
|
|
}
|
|
|
|
lm_adj_v(lmp, r.top);
|
|
lm_adj_v(lmp, r.bottom);
|
|
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rect2
|
|
lmp: current lmp
|
|
rctp: rectangle to invalidate
|
|
adj_left: if TRUE, adjust left of rctp
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rect2(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_left)
|
|
{
|
|
RCT r;
|
|
|
|
r = *rctp;
|
|
if (adj_left)
|
|
lm_adj_h(lmp, &r.left);
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_fixed_columns
|
|
-------------------------------------------------------------------------*/
|
|
int lm_get_fixed_columns( LM lm )
|
|
{
|
|
return ((LM_DATA*)lm)->fixed_columns;
|
|
}
|
|
|
|
|
|
void
|
|
lm_local_hscroll(LM lm, int nbr_columns)
|
|
{
|
|
LM_DATA *lmp;
|
|
XI_LIST_DATA *list_data;
|
|
XI_OBJ *other_list;
|
|
|
|
lmp = (LM_DATA *)lm;
|
|
list_data = lmp->list_obj->v.list;
|
|
lm_hscroll(lm, nbr_columns, 0);
|
|
if (list_data->horz_sync_list &&
|
|
! list_data->scrolling_in_progress)
|
|
{
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj(lmp->itf_obj,
|
|
list_data->horz_sync_list);
|
|
if (other_list)
|
|
lm_hscroll(other_list->v.list->lm, nbr_columns, 0);
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
void lm_make_vis(LM_DATA *lmp)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
BOOLEAN is_hscrolled;
|
|
|
|
if (! lm_list_has_focus(lmp))
|
|
return;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
if (v_scrolled)
|
|
return;
|
|
if (lm_is_cell_visible(lmp, focus_row, focus_column, TRUE, &is_hscrolled))
|
|
{
|
|
TXT_DATA *txt;
|
|
LM_COLUMN_DATA *column_data;
|
|
DRAW_CTOOLS ct;
|
|
RCT cell_r;
|
|
unsigned long attrib, cell_attrib;
|
|
LM_CELL_DATA *cell_data;
|
|
BOOLEAN button;
|
|
BOOLEAN button_on_left;
|
|
RCT mr;
|
|
COLOR color;
|
|
int leading, ascent, descent, char_width;
|
|
BOOLEAN text_was_invisible;
|
|
|
|
if (lmp->focus_rec && lmp->txt_is_invisible && ! is_hscrolled)
|
|
{
|
|
int cnt;
|
|
|
|
/*
|
|
the following loop should *always* find a row, because
|
|
lmp->txt_is_invisible is TRUE, and the cell is now visible.
|
|
*/
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
|
|
{
|
|
if (lmp->recs[cnt] == lmp->focus_rec)
|
|
{
|
|
lm_set_focus_cell(lmp, cnt, focus_column, FALSE );
|
|
focus_row = cnt;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
mr = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
column_data = lmp->lm_column_data[focus_column];
|
|
attrib = column_data->attrib;
|
|
cell_data = &lmp->cell_data[focus_row][focus_column];
|
|
button = cell_data->button;
|
|
button_on_left = cell_data->button_on_left;
|
|
cell_attrib = cell_data->attrib &
|
|
(XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
if (cell_attrib)
|
|
{
|
|
attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
attrib |= cell_attrib;
|
|
}
|
|
txt = lmp->txt = (TXT_DATA *)xi_tree_malloc(sizeof(TXT_DATA), lmp);
|
|
lm_get_cell_rect(&cell_r, (LM)lmp, focus_row, focus_column, FALSE, TRUE);
|
|
if (button)
|
|
{
|
|
RCT r2;
|
|
|
|
r2 = cell_r;
|
|
xi_inflate_rect(&r2, 1);
|
|
if (button_on_left)
|
|
cell_r.left = r2.left + lmp->pix_row_spacing;
|
|
else
|
|
cell_r.right = r2.right - lmp->pix_row_spacing;
|
|
}
|
|
txt->parent_obj = lmp->list_obj;
|
|
txt->attrib = attrib | (TXT_ATR_ENABLED | TXT_ATR_VISIBLE);
|
|
txt->attrib &= ~XI_ATR_VCENTER;
|
|
txt->inside_only = TRUE;
|
|
txt->attrib &= ~TXT_ATR_BORDER;
|
|
if (lmp->min_cell_height && (! column_data->wrap_text))
|
|
txt->attrib |= XI_ATR_VCENTER;
|
|
txt->text = lmp->buffer[focus_row] + column_data->text_offset;
|
|
txt->text_size = column_data->text_size;
|
|
txt->auto_tab = column_data->auto_tab;
|
|
cell_data = &(lmp->cell_data[focus_row][focus_column]);
|
|
if (cell_data->font)
|
|
txt->font = cell_data->font;
|
|
else
|
|
txt->font = lmp->font;
|
|
xi_get_font_metrics_font(txt->font, &leading, &ascent, &descent, &char_width);
|
|
if (column_data->vertical_align_center)
|
|
{
|
|
int height, delta, new_top, new_bottom;
|
|
|
|
height = leading + ascent + descent;
|
|
delta = (cell_r.bottom - cell_r.top - height) / 2;
|
|
new_top = cell_r.top + delta;
|
|
new_bottom = cell_r.bottom - delta;
|
|
cell_r.top = max(cell_r.top, new_top);
|
|
cell_r.bottom = min(cell_r.bottom, new_bottom);
|
|
}
|
|
else if (column_data->vertical_align_bottom)
|
|
{
|
|
int new_top;
|
|
|
|
new_top = cell_r.bottom - (leading + ascent + descent) - 3;
|
|
cell_r.top = max(cell_r.top, new_top);
|
|
}
|
|
else
|
|
{
|
|
int new_bottom;
|
|
#if XVTWS != WMWS
|
|
new_bottom = cell_r.top + leading + ascent + descent + 4;
|
|
#else
|
|
new_bottom = cell_r.top + leading + ascent + descent;
|
|
#endif
|
|
cell_r.bottom = min(cell_r.bottom, new_bottom);
|
|
}
|
|
txt->rct = cell_r;
|
|
#if XVTWS != WMWS
|
|
txt->rct.top++;
|
|
txt->rct.bottom--;
|
|
#endif
|
|
txt->back_color = lmp->active_back_color;
|
|
txt->fore_color = lmp->active_color;
|
|
txt->win = lmp->win;
|
|
xvt_app_get_default_ctools(&ct);
|
|
ct.pen = hollow_cpen;
|
|
ct.fore_color = lmp->enabled_color;
|
|
ct.brush.color = lmp->back_color;
|
|
xi_set_draw_ctools(lmp->win, &ct);
|
|
xi_set_xvt_font(lmp->win, lmp->font, FALSE);
|
|
text_was_invisible = lmp->txt_is_invisible;
|
|
lmp->old_row_height = lmp->pix_heights[focus_row];
|
|
lmp->txt_is_invisible = FALSE;
|
|
lmp->focus_rec = 0L;
|
|
redraw_cell((LM)lmp, focus_row, focus_column, FALSE );
|
|
color = lmp->cell_data[focus_row][focus_column].back_color;
|
|
if (color)
|
|
txt->back_color = color;
|
|
txt_reset(txt);
|
|
if (text_was_invisible)
|
|
{
|
|
txt_set_text(txt, lmp->focus_cell_text);
|
|
txt_set_sel(txt, lmp->focus_cell_ip1, lmp->focus_cell_ip2);
|
|
}
|
|
else
|
|
{
|
|
if (lmp->have_mouse)
|
|
{
|
|
if ((column_data->attrib & (LM_COL_ATR_AUTOSELECT | LM_COL_ATR_READONLY)) ==
|
|
(LM_COL_ATR_AUTOSELECT | LM_COL_ATR_READONLY))
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
if ((column_data->attrib & LM_COL_ATR_AUTOSELECT) && xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE))
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
}
|
|
else
|
|
{
|
|
if (column_data->attrib & LM_COL_ATR_AUTOSELECT)
|
|
txt_set_sel(txt, 0, SHRT_MAX);
|
|
else
|
|
txt_set_sel(txt, 0, 0);
|
|
}
|
|
}
|
|
txt_caret(txt, TRUE);
|
|
}
|
|
else
|
|
{
|
|
if (lmp->focus_rec && is_hscrolled && lmp->txt_is_invisible)
|
|
{
|
|
int cnt;
|
|
|
|
/*
|
|
the following loop should *always* find a row, because
|
|
the only reason the cell is not visible is because the
|
|
list is horizontally scrolled.
|
|
*/
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
|
|
{
|
|
if (lmp->recs[cnt] == lmp->focus_rec)
|
|
{
|
|
lm_set_focus_cell(lmp, cnt, focus_column, FALSE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_text
|
|
lm: current lm
|
|
row: row
|
|
col: column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
do_lm_cb_text(LM_DATA *lmp, int row, int col, BOOLEAN preserve_focus )
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_COLUMN_DATA *lm_column_data;
|
|
|
|
lm_cb_data.lm = (LM)lmp;
|
|
lm_cb_data.cb_type = LM_CB_TEXT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)row;
|
|
lm_cb_data.rec = lmp->recs[row];
|
|
lm_cb_data.column = (unsigned char)col;
|
|
lm_column_data = lmp->lm_column_data[col];
|
|
lm_cb_data.v.text.text = lmp->buffer[row] + lm_column_data->text_offset;
|
|
lm_cb_data.v.text.len = lm_column_data->text_size;
|
|
lm_cb_data.v.text.text[0] = '\0';
|
|
lm_cb_data.v.text.font = NULL;
|
|
lm_cb_data.v.text.font_id = 0L;
|
|
cell_data = &(lmp->cell_data[row][col]);
|
|
lm_cb_data.v.text.icon_rid = cell_data->icon_rid;
|
|
lm_cb_data.v.text.attrib = cell_data->attrib;
|
|
lm_cb_data.v.text.color = 0;
|
|
lm_cb_data.v.text.back_color = 0;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
cell_data->valid_data = TRUE;
|
|
cell_data->icon_rid = lm_cb_data.v.text.icon_rid;
|
|
cell_data->attrib = lm_cb_data.v.text.attrib;
|
|
cell_data->color = lm_cb_data.v.text.color;
|
|
cell_data->back_color = lm_cb_data.v.text.back_color;
|
|
if (lmp->txt_is_invisible) /* update the focus_cell_text */
|
|
{
|
|
XI_OBJ* focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
XI_CELL_DATA* focus_cell;
|
|
focus_cell = &focus_obj->v.cell;
|
|
if ( focus_cell->row == row && focus_cell->column == col )
|
|
{
|
|
if (preserve_focus && lmp->focus_cell_text != NULL)
|
|
strncpy( lm_cb_data.v.text.text, lmp->focus_cell_text,
|
|
lm_column_data->text_size - 1 );
|
|
else
|
|
{
|
|
lm_set_focus_text( lmp, lm_cb_data.v.text.text );
|
|
lmp->focus_cell_ip1 = 0;
|
|
lmp->focus_cell_ip2 = strlen( lmp->focus_cell_text );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XI_OBJ* focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
XI_CELL_DATA* focus_cell;
|
|
focus_cell = &focus_obj->v.cell;
|
|
if ( focus_cell->row == row && focus_cell->column == col )
|
|
{
|
|
if (lmp->txt)
|
|
{
|
|
lm_set_focus_text( lmp, lm_cb_data.v.text.text );
|
|
lmp->focus_cell_ip1 = 0;
|
|
lmp->focus_cell_ip2 = strlen( lmp->focus_cell_text );
|
|
txt_set_text(lmp->txt, lm_cb_data.v.text.text);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
/* cell buttons not supported for XVT/CH */
|
|
cell_data->button = lm_cb_data.v.text.button;
|
|
cell_data->button_on_left = lm_cb_data.v.text.button_on_left;
|
|
cell_data->button_on_focus = lm_cb_data.v.text.button_on_focus;
|
|
cell_data->button_icon_rid = lm_cb_data.v.text.button_icon_rid;
|
|
CTOS_END;
|
|
#endif
|
|
if (lm_cb_data.v.text.font_id)
|
|
{
|
|
XVT_FNTID old_font_id;
|
|
if (! cell_data->font)
|
|
cell_data->font = (FONT_OBJ *)
|
|
xi_tree_malloc(sizeof(FONT_OBJ), lmp);
|
|
old_font_id = *cell_data->font;
|
|
*cell_data->font = xi_create_copy_font_id(lmp->itf_obj,
|
|
lm_cb_data.v.text.font_id, old_font_id);
|
|
}
|
|
else
|
|
{
|
|
if (cell_data->font)
|
|
{
|
|
xi_free_font_id(lmp->itf_obj, *cell_data->font);
|
|
xi_tree_free(cell_data->font);
|
|
cell_data->font = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_attrib
|
|
lm: current lm
|
|
lm_part: may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL
|
|
returns: attribute
|
|
notes: all rows are
|
|
-------------------------------------------------------------------------*/
|
|
unsigned long lm_get_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
|
|
BOOLEAN v_scrolled)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
switch (lm_part)
|
|
{
|
|
case LM_LIST:
|
|
return(lmp->attrib);
|
|
case LM_ROW:
|
|
return(lmp->row_attribs[idx]);
|
|
case LM_COLUMN:
|
|
return(lmp->lm_column_data[idx]->attrib);
|
|
case LM_CELL:
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if (! cell_data->valid_data)
|
|
{
|
|
do_lm_cb_text(lmp, idx, idx2, TRUE );
|
|
}
|
|
if (v_scrolled)
|
|
return lmp->focus_rec_attrib;
|
|
return(cell_data->attrib);
|
|
}
|
|
}
|
|
xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20907",
|
|
20907, "lm_get_attrib: Invalid LM part");
|
|
return 0L;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_buf_size
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_buf_size(LM lm, LM_PART part, int idx)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
NOREF(part);
|
|
return(lmp->lm_column_data[idx]->text_size);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_cid
|
|
lm: current lm
|
|
returns: control id of list
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_get_cid(LM lm)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
return lmp->cid;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_rect
|
|
lm: current lm
|
|
part: may be LM_LIST, LM_COLUMN, or LM_ROW
|
|
idx: if LM_LIST, not used
|
|
if LM_COLUMN, column number
|
|
if LM_ROW, row number
|
|
rct: rectangle to be filled in
|
|
returns: rct
|
|
-------------------------------------------------------------------------*/
|
|
RCT *
|
|
lm_get_rect(LM lm, LM_PART part, int idx, RCT *rct)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
switch (part)
|
|
{
|
|
case LM_LIST:
|
|
*rct = lmp->rct;
|
|
if (lmp->pixel_width)
|
|
rct->right = rct->left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
break;
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[idx];
|
|
if (idx >= lmp->fixed_columns)
|
|
rct->left = lmp->rct.left + column_data->x_pix_pos - lmp->delta_x;
|
|
else
|
|
rct->left = lmp->rct.left + column_data->x_pix_pos;
|
|
rct->right = rct->left + column_data->pix_width +
|
|
2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
rct->top = lmp->rct.top;
|
|
rct->bottom = lmp->rct.bottom;
|
|
break;
|
|
}
|
|
case LM_ROW:
|
|
{
|
|
int con;
|
|
|
|
con = lmp->rrr_offset + lmp->mlr.top;
|
|
|
|
rct->top = lmp->pix_offsets[idx] + con;
|
|
rct->bottom = rct->top + lmp->pix_heights[idx];
|
|
|
|
rct->left = lmp->rct.left;
|
|
rct->right = lmp->rct.right;
|
|
break;
|
|
}
|
|
}
|
|
return rct;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_text
|
|
lm: current lm
|
|
s: string to be filled in
|
|
NULL is valid
|
|
len: size of string to be filled in
|
|
if the length of the text is longer than the size of the buffer s,
|
|
then len-1 characters will be copied, and s[len-1] will be set
|
|
to '\0'
|
|
row: row number of cell
|
|
column: column number of cell
|
|
returns: s
|
|
-------------------------------------------------------------------------*/
|
|
char* lm_get_text( LM lm, char *s, int len, int row, int column,
|
|
BOOLEAN v_scrolled )
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
char *b;
|
|
|
|
if (row == LM_HEADING_TEXT)
|
|
b = lmp->lm_column_data[column]->heading_text;
|
|
else if (v_scrolled)
|
|
b = lmp->focus_cell_text;
|
|
else
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[row][column];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, column, TRUE );
|
|
b = LM_CELL_TEXT(lm, row, column);
|
|
}
|
|
if (s)
|
|
{
|
|
tgstrncpy(s, b, len);
|
|
return s;
|
|
}
|
|
else
|
|
return b;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_sel
|
|
lm: current lm
|
|
c1: pointer to integer to contain selection start
|
|
c2: pointer to integer to contain selection stop
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_sel(LM lm, int *c1, int *c2)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
if (lm_list_has_focus(lmp) && lmp->txt)
|
|
{
|
|
*c1 = lmp->txt->selstart;
|
|
*c2 = lmp->txt->selstop;
|
|
}
|
|
else
|
|
*c1 = *c2 = 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rows_internal
|
|
lm: current lm
|
|
row_start: starting row
|
|
row_end: ending row
|
|
redraw: if TRUE, then redraw the rows
|
|
column: if -1, then do for all columns
|
|
if set, then do for a specific column
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rows_internal( LM lm, int row_start, int row_end,
|
|
BOOLEAN redraw, int column,
|
|
BOOLEAN preserve_focus_text )
|
|
{
|
|
int row, col;
|
|
RCT rct1, rct2;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
row_end = min(row_end, lmp->nbr_realized_rows - 1);
|
|
if (row_start > row_end || row_start < 0)
|
|
return;
|
|
for (row = row_start; row <= row_end; row++)
|
|
{
|
|
for (col = (column == -1) ? 0 : column;
|
|
col < ((column == -1) ? (lmp->nbr_columns) : (column + 1));
|
|
col++)
|
|
{
|
|
if (xi_get_pref(XI_PREF_OPTIMIZE_CELL_REQUESTS))
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
cell_data = &(lmp->cell_data[row][col]);
|
|
cell_data->valid_data = FALSE;
|
|
}
|
|
else
|
|
{
|
|
do_lm_cb_text(lmp, row, col, preserve_focus_text );
|
|
}
|
|
}
|
|
}
|
|
if (redraw)
|
|
{
|
|
if( (column == -1) && (row_start == 0) &&
|
|
(row_end == lmp->nbr_realized_rows - 1) ){
|
|
lm_get_row_rect(&rct1, lm, row_start);
|
|
lm_get_row_rect(&rct2, lm, row_end);
|
|
rct1.bottom = rct2.bottom;
|
|
lm_invalidate_rect(lmp, &rct1, FALSE);
|
|
}else{
|
|
int col_start, col_end;
|
|
if( column == -1 ){
|
|
col_start = 0;
|
|
col_end = lmp->nbr_columns - 1;
|
|
}else
|
|
col_start = col_end = column;
|
|
draw_cell_range( lmp, row_start, row_end, col_start,
|
|
col_end, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_invalidate_rows
|
|
lm: current lm
|
|
row_start: starting row
|
|
row_end: ending row
|
|
redraw: if TRUE, then redraw the rows
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_invalidate_rows(LM lm, int row_start, int row_end, BOOLEAN redraw)
|
|
{
|
|
lm_invalidate_rows_internal(lm, row_start, row_end, redraw, -1, TRUE );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: find_selection
|
|
-------------------------------------------------------------------------*/
|
|
static int find_selection( LM_DATA* lmp )
|
|
{
|
|
int row_num;
|
|
for ( row_num = 0; row_num < lmp->nbr_realized_rows; row_num++ )
|
|
if ( lm_get_attrib( (LM)lmp, LM_ROW, row_num, 0, FALSE )
|
|
& LM_ROW_ATR_SELECTED )
|
|
return row_num;
|
|
return -1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_attrib
|
|
lm: current lm
|
|
lm_part: must be LM_LIST, LM_COLUMN, LM_ROW, or LM_CELL
|
|
idx: if LM_LIST, not used
|
|
if LM_COLUMN, column number
|
|
if LM_ROW, row number
|
|
if LM_CELL, row number
|
|
idx2: if LM_LIST, not used
|
|
if LM_COLUMN, not used
|
|
if LM_ROW, not used
|
|
if LM_CELL, column number
|
|
attrib: attribute to set
|
|
half_baked: if set, don't redraw
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_attrib( LM lm, LM_PART lm_part, int idx, int idx2,
|
|
BOOLEAN v_scrolled, unsigned long attrib, int half_baked)
|
|
{
|
|
unsigned long do_redraw;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
switch (lm_part)
|
|
{
|
|
case LM_LIST:
|
|
{
|
|
RCT r;
|
|
|
|
lmp->attrib = attrib;
|
|
xi_get_rect(lmp->list_obj, &r);
|
|
r.right += 10;
|
|
r.bottom += 4;
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
break;
|
|
}
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
RCT rct;
|
|
|
|
column_data = lmp->lm_column_data[idx];
|
|
do_redraw = ((column_data->attrib ^ attrib) & LM_REDRAW_COL_ATR);
|
|
column_data->attrib = attrib;
|
|
if (do_redraw)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_get_rect(lm, LM_COLUMN, idx, &rct);
|
|
xi_invalidate_rect(lmp->win, &rct);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
|
|
if ((! is_vert_scrolled) && (focus_column == idx) && (lmp->txt))
|
|
txt_redraw(lmp->txt, FALSE);
|
|
}
|
|
break;
|
|
}
|
|
case LM_ROW:
|
|
{
|
|
unsigned long old_attrib;
|
|
|
|
do_redraw = ((lmp->row_attribs[idx] ^ attrib) & LM_REDRAW_ROW_ATR);
|
|
old_attrib = lmp->row_attribs[idx];
|
|
if ( lmp->single_select && (attrib & XI_ATR_SELECTED))
|
|
{
|
|
int old_row;
|
|
|
|
old_row = find_selection( lmp );
|
|
if (old_row != -1 && old_row != idx)
|
|
lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE,
|
|
lmp->row_attribs[old_row] & ~XI_ATR_SELECTED,
|
|
half_baked );
|
|
}
|
|
lmp->row_attribs[idx] = attrib;
|
|
if (! half_baked && do_redraw)
|
|
{
|
|
if ((old_attrib & XI_ATR_SELECTED) != (attrib & XI_ATR_SELECTED))
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_redraw_row(lmp, idx, FALSE );
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
|
|
if ((! is_vert_scrolled) && (focus_row == idx) && (lmp->txt))
|
|
txt_redraw(lmp->txt, FALSE);
|
|
}
|
|
else
|
|
{
|
|
RCT r;
|
|
|
|
lm_get_row_rect(&r, lm, idx);
|
|
xi_set_clip(lmp->win, NULL);
|
|
lm_invalidate_rect(lmp, &r, FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case LM_CELL:
|
|
{
|
|
unsigned long old_attrib;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if (! cell_data->valid_data)
|
|
return;
|
|
if (v_scrolled)
|
|
lmp->focus_rec_attrib = attrib;
|
|
else
|
|
{
|
|
old_attrib = lmp->cell_data[idx][idx2].attrib;
|
|
do_redraw = ((old_attrib ^ attrib) & LM_REDRAW_CELL_ATR);
|
|
cell_data->attrib = attrib;
|
|
if (! half_baked && do_redraw)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
redraw_cell(lm, idx, idx2, FALSE );
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
|
|
if ((! is_vert_scrolled) && (focus_row == idx) && (focus_column == idx2) && (lmp->txt))
|
|
txt_redraw(lmp->txt, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_color
|
|
lm: current lm
|
|
part: must be LM_ROW, or LM_CELL
|
|
idx: if LM_ROW, row number
|
|
if LM_CELL, row number
|
|
idx2: if LM_ROW, not used
|
|
if LM_CELL, column number
|
|
color: color to set
|
|
half_baked: if set, don't redraw
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_color( LM lm, LM_PART part, int idx, int idx2, BOOLEAN v_scrolled,
|
|
COLOR color, BOOLEAN half_baked)
|
|
{
|
|
BOOLEAN do_redraw;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
switch (part)
|
|
{
|
|
case LM_ROW:
|
|
do_redraw = (color != lmp->row_colors[idx]);
|
|
lmp->row_colors[idx] = color;
|
|
if (! half_baked && do_redraw)
|
|
{
|
|
RCT r;
|
|
|
|
lm_get_row_rect(&r, lm, idx);
|
|
lm_invalidate_rect(lmp, &r, FALSE);
|
|
}
|
|
break;
|
|
case LM_CELL:
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if (! cell_data->valid_data)
|
|
return;
|
|
if (v_scrolled)
|
|
lmp->focus_rec_color = color;
|
|
else
|
|
cell_data->color = color;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to draw
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_v)
|
|
{
|
|
RCT r;
|
|
BOOLEAN leftb, rightb;
|
|
|
|
r = *rctp;
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
if (adj_v)
|
|
{
|
|
lm_adj_v(lmp, r.top);
|
|
lm_adj_v(lmp, r.bottom);
|
|
}
|
|
|
|
leftb = lm_adj_h(lmp, &r.left);
|
|
rightb = lm_adj_h(lmp, &r.right);
|
|
if ( ! leftb && ! rightb )
|
|
return;
|
|
xi_draw_rect(lmp->win, &r);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_3d_rect
|
|
lmp: current lmp
|
|
rctp: rectangle
|
|
well: or platform
|
|
depth: in pixels
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_3d_rect(LM_DATA *lmp, RCT *rctp, BOOLEAN well, int depth, BOOLEAN adj_v)
|
|
{
|
|
RCT r;
|
|
BOOLEAN left, right;
|
|
|
|
r = *rctp;
|
|
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
if (adj_v)
|
|
{
|
|
lm_adj_v(lmp, r.top);
|
|
lm_adj_v(lmp, r.bottom);
|
|
}
|
|
|
|
left = lm_adj_h(lmp, &r.left);
|
|
right = lm_adj_h(lmp, &r.right);
|
|
if (! left && ! right)
|
|
return;
|
|
xi_draw_3d_rect(lmp->win, &r, well, depth, 0L, 0L, 0L);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_icon
|
|
lmp: current lmp
|
|
left: h position
|
|
top: v position
|
|
icon_rid: resource id
|
|
vir_clip: virtual clip rectangle
|
|
phys_rct:
|
|
fore_color: desired colors if icons
|
|
back_color:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_icon(LM_DATA *lmp, int left, int top, int icon_rid, RCT *vir_clip,
|
|
RCT *phys_rct, BOOLEAN adj_v, COLOR fore_color, COLOR back_color)
|
|
{
|
|
RCT crct, r;
|
|
short sleft;
|
|
BOOLEAN leftb, rightb;
|
|
|
|
left += lmp->rct.left;
|
|
r = *vir_clip;
|
|
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
if (adj_v)
|
|
{
|
|
lm_adj_v(lmp, r.top);
|
|
lm_adj_v(lmp, r.bottom);
|
|
}
|
|
|
|
leftb = lm_adj_h(lmp, &r.left);
|
|
rightb = lm_adj_h(lmp, &r.right);
|
|
if ( ! leftb && ! rightb )
|
|
return;
|
|
if (adj_v)
|
|
lm_adj_v(lmp, top);
|
|
xi_rect_intersect(&crct, &r, phys_rct);
|
|
xi_set_clip(lmp->win, &crct);
|
|
sleft = left;
|
|
if (lm_adj_h(lmp, &sleft))
|
|
xi_draw_icon(lmp->win, sleft, top, icon_rid, fore_color, back_color);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_move_to
|
|
lmp: current lmp
|
|
p: point
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_move_to(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h)
|
|
{
|
|
|
|
if (adj_h)
|
|
{
|
|
p.h += lmp->rct.left;
|
|
lm_adj_h(lmp, &p.h);
|
|
}
|
|
|
|
if (adj_v)
|
|
lm_adj_v(lmp, p.v);
|
|
|
|
xi_move_to(lmp->win, p);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_line
|
|
lmp: current lmp
|
|
p: point
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_draw_line(LM_DATA *lmp, PNT p, BOOLEAN adj_v, BOOLEAN adj_h)
|
|
{
|
|
if (adj_h)
|
|
{
|
|
p.h += lmp->rct.left;
|
|
if (lm_adj_h(lmp, &p.h))
|
|
{
|
|
if (adj_v)
|
|
lm_adj_v(lmp, p.v);
|
|
xi_draw_line(lmp->win, p);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (adj_v)
|
|
lm_adj_v(lmp, p.v);
|
|
xi_draw_line(lmp->win, p);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: redraw_cell_button
|
|
lmp: current lmp
|
|
row:
|
|
col: 0
|
|
clip_rct: clip rectangle
|
|
down: if TRUE, then button is depressed
|
|
-------------------------------------------------------------------------*/
|
|
static void near
|
|
redraw_cell_button(LM_DATA *lmp, int row, int col, RCT *clip_rct,
|
|
BOOLEAN down, BOOLEAN clear_button)
|
|
{
|
|
RCT r, outer_rct, col_rct, clip_rect;
|
|
int cell_btn_icon_x, cell_btn_icon_y;
|
|
LM_CELL_DATA *cell_data;
|
|
BOOLEAN button_on_left;
|
|
int button_icon_rid;
|
|
LM_COLUMN_DATA *column_data;
|
|
PNT p;
|
|
DRAW_CTOOLS ct;
|
|
RCT actual_rct;
|
|
int actual_r;
|
|
|
|
actual_rct = lmp->rct;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
column_data = lmp->lm_column_data[col];
|
|
col_rct.left = column_data->x_pix_pos;
|
|
col_rct.right = col_rct.left + column_data->pix_width +
|
|
2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
col_rct.top = clip_rct->top;
|
|
col_rct.bottom = clip_rct->bottom;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
button_on_left = cell_data->button_on_left;
|
|
button_icon_rid = cell_data->button_icon_rid;
|
|
lm_get_cell_rect(&outer_rct, (LM)lmp, row, col, FALSE, FALSE);
|
|
r = outer_rct;
|
|
xi_inflate_rect(&r, 1);
|
|
if (button_on_left)
|
|
{
|
|
r.right = r.left + lmp->pix_row_spacing;
|
|
p.h = r.right - 1;
|
|
}
|
|
else
|
|
{
|
|
r.left = r.right - lmp->pix_row_spacing;
|
|
p.h = r.left;
|
|
}
|
|
xi_set_cpen(lmp->win, &black_cpen);
|
|
xi_set_draw_mode(lmp->win, M_COPY);
|
|
clip_rect = col_rct;
|
|
clip_rect.left += lmp->rct.left;
|
|
clip_rect.right += lmp->rct.left;
|
|
|
|
lm_adj_h(lmp, &clip_rect.left);
|
|
lm_adj_h(lmp, &clip_rect.right);
|
|
xi_rect_intersect(&clip_rect, &clip_rect, &lmp->mlr);
|
|
xi_rect_intersect(&clip_rect, &clip_rect, &actual_rct);
|
|
xi_set_clip(lmp->win, &clip_rect);
|
|
if (clear_button)
|
|
{
|
|
if (lmp->no_horz_lines)
|
|
{
|
|
/* if there is a button below, then decrement r.bottom */
|
|
int nr;
|
|
LM_CELL_DATA *cd;
|
|
|
|
nr = row;
|
|
cd = &lmp->cell_data[nr + 1][col];
|
|
if (row < lmp->nbr_realized_rows - 1 &&
|
|
cd->button &&
|
|
cd->button_on_left == lmp->cell_data[nr][col].button_on_left &&
|
|
(! cd->button_on_focus))
|
|
r.bottom--;
|
|
|
|
xi_set_cpen(lmp->win, &hollow_cpen);
|
|
xi_set_cbrush(lmp->win, &white_cbrush);
|
|
lm_draw_rect(lmp, &r, TRUE);
|
|
}
|
|
return;
|
|
}
|
|
if (lmp->no_horz_lines || lmp->no_vert_lines)
|
|
lm_draw_rect(lmp, &r, TRUE);
|
|
else
|
|
{
|
|
p.v = r.top;
|
|
lm_move_to(lmp, p, TRUE, TRUE);
|
|
p.v = r.bottom;
|
|
lm_draw_line(lmp, p, TRUE, TRUE);
|
|
}
|
|
xi_inflate_rect(&r, -1);
|
|
lm_draw_3d_rect(lmp, &r, down, 2, TRUE);
|
|
xi_inflate_rect(&r, -2);
|
|
cell_btn_icon_x = (int)xi_get_pref(XI_PREF_CELL_BTN_ICON_X);
|
|
cell_btn_icon_y = (int)xi_get_pref(XI_PREF_CELL_BTN_ICON_Y);
|
|
r.left = max(r.left, col_rct.left);
|
|
r.right = min(r.right, col_rct.right);
|
|
xi_get_draw_ctools(lmp->win, &ct);
|
|
ct.fore_color = lmp->enabled_color;
|
|
ct.back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
|
|
ct.opaque_text = TRUE;
|
|
if (lmp->row_colors[row])
|
|
ct.fore_color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
ct.fore_color = cell_data->color;
|
|
xi_set_draw_ctools(lmp->win, &ct);
|
|
lm_draw_icon(lmp, r.left + cell_btn_icon_x, r.top + cell_btn_icon_y + down,
|
|
button_icon_rid ? button_icon_rid : (int)xi_get_pref(XI_PREF_COMBO_ICON),
|
|
&r, clip_rct, TRUE, COLOR_BLACK, xi_get_pref(XI_PREF_COLOR_CTRL));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: xvtch_draw_line
|
|
lmp: current lm pointer
|
|
from: from point
|
|
to: to point
|
|
-------------------------------------------------------------------------*/
|
|
#if XI_IS_CH
|
|
static void
|
|
xvtch_draw_line(LM_DATA *lmp, PNT *from, PNT *to, BOOLEAN adj_h)
|
|
{
|
|
int i, len;
|
|
|
|
#if XVT_OS != XVT_OS_CTOS
|
|
|
|
char c_v = (char)C_V;
|
|
#else
|
|
char c_v = 225;
|
|
#endif
|
|
char *s, *s2;
|
|
|
|
if (from->h == to->h)
|
|
{
|
|
/* draw vertical line */
|
|
if (adj_h)
|
|
{
|
|
from->h += lmp->rct.left;
|
|
if (lm_adj_h(lmp, &from->h))
|
|
{
|
|
for (i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH)
|
|
xi_draw_text(lmp->win, from->h, i, &c_v, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = from->v + VPIX_PER_CH; i <= to->v; i += VPIX_PER_CH)
|
|
xi_draw_text(lmp->win, from->h, i, &c_v, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = (to->h - from->h) / VPIX_PER_CH;
|
|
s = xi_tree_malloc(len + 4, NULL);
|
|
s2 = s;
|
|
for (i = 0; i < len; ++i)
|
|
{
|
|
|
|
#if XVT_OS != XVT_OS_CTOS
|
|
*s2 = C_H;
|
|
|
|
#else
|
|
*s2 = 218;
|
|
#endif
|
|
++s2;
|
|
}
|
|
xi_draw_text(lmp->win, from->h, from->v + VPIX_PER_CH, s, len);
|
|
xi_tree_free(s);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if XI_IS_CH
|
|
static char c_xd, c_xu, c_v, c_xx;
|
|
#endif
|
|
|
|
/*********** draw border around entire list ***********/
|
|
static void
|
|
draw_list_rect(LM_DATA *lmp, RCT *vr, RCT *hr)
|
|
{
|
|
RCT r;
|
|
XI_OBJ *list_obj = lmp->list_obj;
|
|
XI_LIST_DATA *list_data = list_obj->v.list;
|
|
|
|
r = lmp->rct;
|
|
if (list_data->sb_win)
|
|
r.right = vr->right;
|
|
else
|
|
r.right += BORDER_WIDTH;
|
|
if (list_data->hsb_win)
|
|
r.bottom = hr->bottom;
|
|
xi_draw_rect(lmp->win, &r);
|
|
}
|
|
|
|
|
|
/*********** draw heading rules ***********/
|
|
static void
|
|
draw_heading_rules(LM_DATA *lmp, int hrule_h)
|
|
{
|
|
if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
|
|
{
|
|
if (! lmp->no_heading)
|
|
{
|
|
int r2, i;
|
|
PNT p;
|
|
WINDOW win = lmp->win;
|
|
|
|
#if XI_IS_CH
|
|
NOREF(r2);
|
|
NOREF(win);
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
/* heading rule, Release 3.0 */
|
|
p.h = lmp->rct.left;
|
|
p.v = lmp->pix_hdr_bottom;
|
|
xi_move_to(lmp->win, p);
|
|
p.h = hrule_h - VPIX_PER_CH;
|
|
xi_draw_line(lmp->win, p);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
r2 = lmp->rct.right - lmp->delta_x;
|
|
r2 = min(r2, hrule_h);
|
|
WIDTHLOOP(i, BORDER_WIDTH)
|
|
{
|
|
p.h = lmp->rct.left;
|
|
p.v = lmp->pix_row1_top - BORDER_WIDTH + i;
|
|
xi_move_to(win, p);
|
|
p.h = r2;
|
|
xi_draw_line(win, p);
|
|
}
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*********** draw column rules ***********/
|
|
static void
|
|
draw_column_rules(LM_DATA *lmp)
|
|
{
|
|
LM_COLUMN_DATA * *lmcd;
|
|
int col;
|
|
PNT p;
|
|
#if XI_IS_CH
|
|
PNT from_p;
|
|
#endif
|
|
|
|
if (lmp->no_vert_lines)
|
|
{
|
|
CPEN back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.color = lmp->back_color;
|
|
xi_set_cpen(lmp->win, &back_cpen);
|
|
}
|
|
else
|
|
{
|
|
CPEN back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.color = lmp->rule_color;
|
|
xi_set_cpen(lmp->win, &back_cpen);
|
|
}
|
|
for (col = 1, lmcd = &lmp->lm_column_data[1]; col < lmp->nbr_columns; col++, ++lmcd)
|
|
{
|
|
p.h = (*lmcd)->x_pix_pos - RULE_WIDTH_V;
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
p.v = lmp->pix_top;
|
|
lm_move_to(lmp, p, FALSE, TRUE);
|
|
p.v = lmp->mlr.bottom - VPIX_PER_CH;
|
|
lm_draw_line(lmp, p, FALSE, TRUE);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
/* if RULE_WIDTH_V were used, this is where it would be used */
|
|
p.v = lmp->rct.top;
|
|
lm_move_to(lmp, p, FALSE, TRUE);
|
|
p.v = min(lmp->rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top);
|
|
lm_draw_line(lmp, p, FALSE, TRUE);
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_needs_update
|
|
lmp: current lmp
|
|
rctp: rectangle to test
|
|
adj_h: adjust h
|
|
adj_v: adjust v
|
|
returns: TRUE if rectangle needs update
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_needs_update(LM_DATA *lmp, RCT *rctp, BOOLEAN adj_h, BOOLEAN adj_v)
|
|
{
|
|
RCT r;
|
|
|
|
r = *rctp;
|
|
if (adj_h)
|
|
{
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
}
|
|
|
|
if (adj_v)
|
|
{
|
|
lm_adj_v(lmp, r.top);
|
|
lm_adj_v(lmp, r.bottom);
|
|
}
|
|
|
|
if (adj_h)
|
|
{
|
|
BOOLEAN leftb, rightb;
|
|
|
|
leftb = lm_adj_h(lmp, &r.left);
|
|
rightb = lm_adj_h(lmp, &r.right);
|
|
if ( ! leftb && ! rightb )
|
|
return FALSE;
|
|
else
|
|
return xi_needs_update(lmp->win, &r);
|
|
}
|
|
else
|
|
{
|
|
return xi_needs_update(lmp->win, &r);
|
|
}
|
|
}
|
|
|
|
|
|
/*********** draw row rules ***********/
|
|
static void
|
|
draw_row_rules(LM_DATA *lmp, int first_row_to_draw, int last_row_to_draw, BOOLEAN update)
|
|
{
|
|
int r2, first_row, last_row;
|
|
int row, actual_r, hrule_h, col;
|
|
PNT p;
|
|
RCT r;
|
|
RCT actual_rct = lmp->mlr;
|
|
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
hrule_h = actual_r;
|
|
xi_set_clip(lmp->win, &actual_rct);
|
|
|
|
if (lmp->no_horz_lines)
|
|
{
|
|
CPEN back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.color = lmp->back_color;
|
|
xi_set_cpen(lmp->win, &back_cpen);
|
|
}
|
|
else
|
|
{
|
|
#if XIWS != WMWS
|
|
CPEN back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.color = lmp->rule_color;
|
|
xi_set_cpen(lmp->win, &back_cpen);
|
|
#else
|
|
xi_set_cpen(lmp->win, &black_cpen);
|
|
#endif
|
|
}
|
|
r2 = lmp->rct.right - lmp->delta_x;
|
|
r2 = min(r2, hrule_h);
|
|
|
|
first_row = max(0, lmp->first_fully_vis - 1);
|
|
last_row = min(lmp->nbr_realized_rows, lmp->last_fully_vis + 1);
|
|
|
|
if (lmp->update_rows_at_top)
|
|
{
|
|
RCT row_rct;
|
|
int old_last_row = last_row;
|
|
|
|
last_row = min(last_row, first_row + lmp->update_rows_at_top + 1);
|
|
lm_get_row_rect(&row_rct, (LM)lmp, last_row);
|
|
row_rct.bottom = lmp->mlr.bottom - lmp->mlr.top;
|
|
if (update && lm_needs_update(lmp, &row_rct, FALSE, TRUE))
|
|
last_row = old_last_row;
|
|
}
|
|
if (lmp->update_rows_at_bottom)
|
|
{
|
|
RCT row_rct;
|
|
int old_first_row = first_row;
|
|
|
|
first_row = max(first_row, lmp->last_fully_vis - lmp->update_rows_at_bottom);
|
|
lm_get_row_rect(&row_rct, (LM)lmp, first_row);
|
|
row_rct.top = 0;
|
|
if (update && lm_needs_update(lmp, &row_rct, FALSE, TRUE))
|
|
first_row = old_first_row;
|
|
}
|
|
|
|
if (first_row_to_draw != -1)
|
|
{
|
|
first_row = max(first_row_to_draw - 1, first_row);
|
|
last_row = min(last_row_to_draw + 1, last_row);
|
|
}
|
|
|
|
r = lmp->rct;
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
if (! lmp->lm_column_data[col]->suppress_update_cells)
|
|
break;
|
|
if (col)
|
|
r.left = lmp->lm_column_data[col]->x_pix_pos;
|
|
|
|
for (row = first_row; row < last_row; ++row)
|
|
{
|
|
p.h = r.left;
|
|
p.v = lmp->pix_offsets[row] + lmp->pix_heights[row] - 1;
|
|
lm_move_to(lmp, p, TRUE, FALSE);
|
|
p.h = r2;
|
|
lm_draw_line(lmp, p, TRUE, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_clipped_text
|
|
lmp: current lmp
|
|
s: string
|
|
bound_rctp:
|
|
clip_rctp:
|
|
attrib:
|
|
set_the_cpen:
|
|
rule_and_space:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_draw_clipped_text(LM_DATA *lmp, char *s, RCT *bound_rctp,
|
|
RCT *clip_rctp, unsigned long attrib, BOOLEAN set_the_cpen,
|
|
int rule_and_space, BOOLEAN adj_v)
|
|
{
|
|
RCT br, cr;
|
|
BOOLEAN left, right;
|
|
|
|
br = *bound_rctp;
|
|
br.left += lmp->rct.left;
|
|
br.right += lmp->rct.left;
|
|
|
|
if (adj_v)
|
|
{
|
|
lm_adj_v(lmp, br.top);
|
|
lm_adj_v(lmp, br.bottom);
|
|
}
|
|
|
|
left = lm_adj_h(lmp, &br.left);
|
|
right = lm_adj_h(lmp, &br.right);
|
|
if ( ! left && ! right )
|
|
return;
|
|
xi_rect_intersect(&cr, &br, clip_rctp);
|
|
xi_draw_clipped_text(lmp->win, s, &br, &cr, attrib, set_the_cpen,
|
|
rule_and_space, -1);
|
|
}
|
|
|
|
/*********** draw column headings ***********/
|
|
static void
|
|
draw_column_headings(LM_DATA *lmp, RCT *actual_rct)
|
|
{
|
|
WINDOW win = lmp->win;
|
|
LM lm = (LM)lmp;
|
|
|
|
if (! lmp->update_cells_only)
|
|
{
|
|
if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
|
|
{
|
|
if ( !lmp->no_heading)
|
|
{
|
|
int col;
|
|
|
|
for (col = 0; col < lmp->nbr_columns; col++)
|
|
{
|
|
RCT heading_rct, cell_rct;
|
|
LM_COLUMN_DATA *col_data;
|
|
unsigned long attrib;
|
|
|
|
col_data = lmp->lm_column_data[col];
|
|
if (col_data->suppress_update_heading)
|
|
continue;
|
|
|
|
lm_get_cell_rect(&heading_rct, lm, 1, col, FALSE, FALSE);
|
|
heading_rct.top = lmp->pix_top + BORDER_WIDTH;
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
heading_rct.bottom = lmp->pix_hdr_bottom - VPIX_PER_CH;
|
|
lm_get_cell_rect(&cell_rct, lm, 1, col, TRUE, FALSE);
|
|
cell_rct.top = lmp->rct.top + VPIX_PER_CH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
heading_rct.bottom = lmp->pix_hdr_bottom;
|
|
lm_get_cell_rect(&cell_rct, lm, 1, col, TRUE, FALSE);
|
|
cell_rct.top = lmp->rct.top + 2 * BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
cell_rct.bottom = lmp->pix_hdr_bottom;
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
xi_set_cbrush(win, &white_cbrush);
|
|
xi_set_draw_mode(win, M_COPY);
|
|
xi_set_clip(win, actual_rct);
|
|
if (col_data->font)
|
|
xi_set_xvt_font(win, col_data->font, FALSE);
|
|
else
|
|
xi_set_xvt_font(win, lmp->font, FALSE);
|
|
|
|
if (col_data->heading_well || col_data->heading_platform)
|
|
{
|
|
COLOR fore_color, back_color;
|
|
|
|
lm_draw_3d_rect(lmp, &heading_rct,
|
|
(BOOLEAN)(COLUMN_IS_SELECTED(lm, col) ?
|
|
!col_data->heading_well :
|
|
col_data->heading_well),
|
|
2, FALSE);
|
|
if (COLUMN_IS_ENABLED(lm, col))
|
|
{
|
|
if (LIST_IS_ENABLED(lmp))
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->disabled_back_color;
|
|
}
|
|
if (col_data->heading_well || col_data->heading_platform)
|
|
back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
|
|
xi_set_xvt_fore_color(win, fore_color);
|
|
xi_set_xvt_back_color(win, back_color);
|
|
}
|
|
else
|
|
{
|
|
COLOR fore_color;
|
|
|
|
if (COLUMN_IS_ENABLED(lm, col))
|
|
{
|
|
if (LIST_IS_ENABLED(lmp))
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
xi_set_xvt_fore_color(win, fore_color);
|
|
xi_set_xvt_back_color(win, lmp->back_color);
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
xi_set_xvt_fore_color(win, fore_color);
|
|
xi_set_xvt_back_color(win, lmp->disabled_back_color);
|
|
}
|
|
if (COLUMN_IS_SELECTED(lm, col))
|
|
{
|
|
CBRUSH cb;
|
|
|
|
cb = white_cbrush;
|
|
cb.color = fore_color;
|
|
xi_set_cbrush(win, &cb);
|
|
xi_set_xvt_fore_color(win, COLOR_WHITE);
|
|
}
|
|
lm_draw_rect(lmp, &heading_rct, FALSE);
|
|
}
|
|
if (col_data->heading_well || col_data->heading_platform)
|
|
{
|
|
cell_rct.left++;
|
|
cell_rct.right--;
|
|
}
|
|
attrib = ((LM_COL_ATTR(lm, col) | XI_ATR_VISIBLE) &
|
|
~XI_ATR_PASSWORD) |
|
|
(lmp->min_heading_height ? XI_ATR_VCENTER : 0);
|
|
if (col_data->center_heading)
|
|
{
|
|
attrib |= XI_ATR_HCENTER;
|
|
attrib &= ~XI_ATR_RJUST;
|
|
}
|
|
if (col_data->icon_rid)
|
|
{
|
|
COLOR fore_color, back_color;
|
|
|
|
if (COLUMN_IS_ENABLED(lm, col))
|
|
{
|
|
if (LIST_IS_ENABLED(lmp))
|
|
fore_color = lmp->enabled_color;
|
|
else
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->back_color;
|
|
}
|
|
else
|
|
{
|
|
fore_color = lmp->disabled_color;
|
|
back_color = lmp->disabled_back_color;
|
|
}
|
|
if (col_data->heading_well || col_data->heading_platform)
|
|
back_color = xi_get_pref(XI_PREF_COLOR_CTRL);
|
|
lm_draw_icon(lmp, cell_rct.left + col_data->icon_x,
|
|
cell_rct.top + col_data->icon_y, col_data->icon_rid,
|
|
&cell_rct, actual_rct, FALSE, fore_color, back_color);
|
|
}
|
|
else
|
|
{
|
|
char *ch;
|
|
int lines;
|
|
#if 0
|
|
#if XI_IS_CH
|
|
char buf[BUFLEN];
|
|
int i;
|
|
|
|
CTOS_IS_CH;
|
|
for (i = 0; i < BUFLEN; ++i)
|
|
buf[i] = ' ';
|
|
buf[BUFLEN - 1] = '\0';
|
|
lm_draw_clipped_text(lmp, buf, &cell_rct, &actual_rct,
|
|
((LM_COL_ATTR(lm, col) | XI_ATR_VISIBLE) & ~XI_ATR_PASSWORD) |
|
|
(col_data->center_heading ? XI_ATR_HCENTER : 0),
|
|
TRUE, 0, FALSE);
|
|
CTOS_END;
|
|
#endif
|
|
#endif
|
|
ch = col_data->heading_text;
|
|
lines = 1;
|
|
while (*ch != '\0')
|
|
{
|
|
if (*ch == '\n')
|
|
++lines;
|
|
++ch;
|
|
}
|
|
if (lines == 1)
|
|
{
|
|
lm_draw_clipped_text(lmp, col_data->heading_text, &cell_rct,
|
|
actual_rct,
|
|
attrib, TRUE, 0, FALSE);
|
|
}
|
|
else
|
|
{
|
|
char *s;
|
|
char *first_char;
|
|
char *ch;
|
|
BOOLEAN bk = FALSE;
|
|
int leading, ascent, descent;
|
|
|
|
s = xvt_mem_alloc(strlen(col_data->heading_text) + 1);
|
|
strcpy(s, col_data->heading_text);
|
|
ch = s;
|
|
first_char = ch;
|
|
xi_get_font_metrics(win, &leading, &ascent, &descent);
|
|
cell_rct.top +=
|
|
(cell_rct.bottom - cell_rct.top -
|
|
(leading + ascent + descent) * lines) / 2;
|
|
cell_rct.bottom = cell_rct.top + leading + ascent + descent;
|
|
while (TRUE)
|
|
{
|
|
while (*ch != '\n' && *ch != '\0')
|
|
++ch;
|
|
if (*ch == '\0')
|
|
bk = TRUE;
|
|
*ch = 0;
|
|
lm_draw_clipped_text(lmp, first_char, &cell_rct,
|
|
actual_rct,
|
|
attrib & ~XI_ATR_VCENTER, TRUE, 0, FALSE);
|
|
if (bk)
|
|
break;
|
|
cell_rct.top += (leading + ascent + descent);
|
|
cell_rct.bottom += (leading + ascent + descent);
|
|
++ch;
|
|
first_char = ch;
|
|
}
|
|
xvt_mem_free(s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* fast_calc_col_needs_update */
|
|
/* ------------------------------------------------------------------------- */
|
|
static void
|
|
fast_calc_col_needs_update(LM_DATA *lmp, int first_col, int last_col,
|
|
BOOLEAN update)
|
|
{
|
|
int col;
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
#if XVTWS == WMWS
|
|
NOREF(update);
|
|
#endif
|
|
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
lmp->lm_column_data[col]->needs_update = FALSE;
|
|
for (col = first_col; col <= last_col; ++col)
|
|
{
|
|
RCT rct;
|
|
BOOLEAN rightb, leftb;
|
|
|
|
column_data = lmp->lm_column_data[col];
|
|
if (column_data->suppress_update_cells)
|
|
continue;
|
|
rct.left = lmp->rct.left + column_data->x_pix_pos;
|
|
rct.right = rct.left + column_data->pix_width +
|
|
2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
rct.top = lmp->rct.top;
|
|
rct.bottom = lmp->rct.bottom;
|
|
column_data->column_rct = rct;
|
|
#if XIWS != WMWS
|
|
leftb = lm_adj_h(lmp, &rct.left);
|
|
rightb = lm_adj_h(lmp, &rct.right);
|
|
column_data->prct = rct;
|
|
if (! leftb && !rightb)
|
|
column_data->needs_update = FALSE;
|
|
else
|
|
{
|
|
if (update)
|
|
{
|
|
if (xi_needs_update(lmp->win, &column_data->prct))
|
|
column_data->needs_update = TRUE;
|
|
else
|
|
column_data->needs_update = FALSE;
|
|
}
|
|
else
|
|
column_data->needs_update = TRUE;
|
|
}
|
|
#else
|
|
leftb = lm_adj_h(lmp, &rct.left);
|
|
rightb = lm_adj_h(lmp, &rct.right);
|
|
column_data->prct = rct;
|
|
if (! leftb && !rightb)
|
|
column_data->needs_update = FALSE;
|
|
else
|
|
column_data->needs_update = TRUE;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void
|
|
fast_draw_exception_rects(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info, int first_row, int last_row)
|
|
{
|
|
COLOR last_brush_color;
|
|
int col, row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
extern CPEN hollow_cpen;
|
|
|
|
/* draw exception rectangles - draw enabled, not selected cells */
|
|
last_brush_color = 0L;
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
COLOR brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
BOOLEAN do_draw;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
do_draw = lm_cell_has_focus( lmp, row, col, FALSE );
|
|
if ((CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
|
|
do_draw = TRUE;
|
|
if (do_draw)
|
|
{
|
|
RCT rct;
|
|
|
|
brush_color = lmp->back_color;
|
|
if (cell_data->back_color)
|
|
brush_color = cell_data->back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if (brush_color != last_brush_color)
|
|
{
|
|
CBRUSH cbrush;
|
|
|
|
cbrush.color = brush_color;
|
|
cbrush.pat = PAT_SOLID;
|
|
xi_set_cbrush(win, &cbrush);
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect(win, &rct);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw exception rectangles - draw disabled, not selected cells */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
COLOR brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (! (CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
|
|
{
|
|
RCT rct;
|
|
|
|
brush_color = lmp->disabled_back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if (brush_color != last_brush_color)
|
|
{
|
|
CBRUSH cbrush;
|
|
|
|
cbrush.color = brush_color;
|
|
cbrush.pat = PAT_SOLID;
|
|
xi_set_cbrush(win, &cbrush);
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect(win, &rct);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw exception rectangles - draw selected cells */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
COLOR brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (CELL_IS_SELECTED(lmp, row, col) && ! lm_cell_has_focus(lmp, row, col, FALSE))
|
|
{
|
|
RCT rct;
|
|
|
|
if (CELL_IS_ENABLED(lmp, row, col))
|
|
{
|
|
brush_color = lmp->enabled_color;
|
|
if (lmp->row_colors[row])
|
|
brush_color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
brush_color = cell_data->color;
|
|
}
|
|
else
|
|
brush_color = lmp->disabled_color;
|
|
if (cell_data->back_color && lmp->retain_back_color_on_select)
|
|
brush_color = cell_data->back_color;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE NEXT TWO LINES
|
|
if (brush_color == lmp->back_color)
|
|
continue;
|
|
*/
|
|
if (brush_color != last_brush_color)
|
|
{
|
|
CBRUSH cbrush;
|
|
|
|
cbrush.color = brush_color;
|
|
cbrush.pat = PAT_SOLID;
|
|
xi_set_cbrush(win, &cbrush);
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect(win, &rct);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if XVTWS != WMWS
|
|
/* draw 3d rectangles */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
RCT rct;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
if (column_data->column_well || column_data->column_platform)
|
|
xi_draw_3d_rect(win, &rct, (BOOLEAN)(CELL_IS_SELECTED(lmp, row, col) ? ! column_data->column_well :
|
|
column_data->column_well), 2, 0L, 0L, 0L);
|
|
}
|
|
}
|
|
#else
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
COLOR brush_color;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
BOOLEAN do_draw;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col);
|
|
do_draw = lm_cell_has_focus( lmp, row, col, FALSE );
|
|
if ((CELL_IS_ENABLED(lmp, row, col)) && ! (CELL_IS_SELECTED(lmp, row, col)))
|
|
do_draw = TRUE;
|
|
if (do_draw)
|
|
{
|
|
if (column_data->column_well || column_data->column_platform)
|
|
{
|
|
RCT rct;
|
|
|
|
brush_color = lmp->back_color;
|
|
if (cell_data->back_color)
|
|
brush_color = cell_data->back_color;
|
|
if (brush_color != last_brush_color)
|
|
{
|
|
CBRUSH cbrush;
|
|
|
|
cbrush.color = brush_color;
|
|
cbrush.pat = PAT_SOLID;
|
|
xi_set_cbrush(win, &cbrush);
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
xi_draw_rect(win, &rct);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
fast_draw_cell_icons(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info, int first_row, int last_row)
|
|
{
|
|
int col, row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
DRAW_CTOOLS ct;
|
|
#if XIWS != PMWS
|
|
COLOR last_fore_color, last_back_color;
|
|
#endif
|
|
|
|
xi_get_draw_ctools(win, &ct);
|
|
ct.fore_color = lmp->enabled_color;
|
|
ct.back_color = lmp->back_color;
|
|
ct.opaque_text = TRUE;
|
|
xi_set_draw_ctools(win, &ct);
|
|
|
|
#if XIWS != PMWS
|
|
last_back_color = 0L;
|
|
last_fore_color = 0L;
|
|
#endif
|
|
/* draw cell icons */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
RCT rct;
|
|
LM_CELL_DATA *cell_data = &lmp->cell_data[row][col];
|
|
COLOR fore_color, back_color;
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
rct = column_data->prct;
|
|
rct.top = ri->rct.top;
|
|
rct.bottom = ri->rct.bottom;
|
|
lm_adj_v(lmp, rct.top);
|
|
lm_adj_v(lmp, rct.bottom);
|
|
{
|
|
RCT mlr = lmp->mlr;
|
|
|
|
if (lmp->pixel_width)
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_rect_intersect(&mlr, &mlr, &rct);
|
|
xi_set_clip(win, &mlr);
|
|
}
|
|
fore_color = ct.fore_color;
|
|
back_color = ct.back_color;
|
|
if (lmp->row_colors[row])
|
|
fore_color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
fore_color = cell_data->color;
|
|
if (cell_data->back_color)
|
|
{
|
|
back_color = cell_data->back_color;
|
|
}
|
|
if (! cell_data->icon_rid)
|
|
continue;
|
|
#if XIWS == PMWS
|
|
xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, fore_color, back_color);
|
|
#else
|
|
if (fore_color != last_fore_color || back_color != last_back_color)
|
|
xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, fore_color, back_color);
|
|
else
|
|
xi_draw_icon(win, rct.left, rct.top, cell_data->icon_rid, 0L, 0L);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
fast_draw_cell_buttons(LM_DATA *lmp, ROW_INFO *row_info, int first_row, int last_row)
|
|
{
|
|
int col, row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
|
|
/* draw exception rectangles - draw enabled, not selected cells */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
RCT mr;
|
|
BOOLEAN button;
|
|
BOOLEAN button_on_focus;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
mr = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
button = cell_data->button;
|
|
button_on_focus = cell_data->button_on_focus;
|
|
if ((button && ! button_on_focus) ||
|
|
(button && button_on_focus &&
|
|
lm_row_has_focus(lmp, row, FALSE)))
|
|
redraw_cell_button(lmp, row, col, &mr, FALSE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
fast_draw_cell_text(LM_DATA *lmp, LM_CELL_DATA *cell_data, LM_COLUMN_DATA *column_data,
|
|
int row, int col, ROW_INFO *ri, int col_offset, int leading, int ascent,
|
|
int descent, BOOLEAN xvt_dwin_set_clip)
|
|
{
|
|
RCT rct;
|
|
unsigned long attrib, cell_attrib;
|
|
char *s;
|
|
int len, rule_and_space, baseline, wid;
|
|
char buf[256];
|
|
WINDOW win = lmp->win;
|
|
BOOLEAN button, button_on_left;
|
|
|
|
#if XVTWS == WMWS
|
|
NOREF(rule_and_space);
|
|
#endif
|
|
if (lm_cell_has_focus( lmp, row, col, FALSE ))
|
|
return;
|
|
button = cell_data->button;
|
|
button_on_left = cell_data->button_on_left;
|
|
cell_attrib = cell_data->attrib &
|
|
(XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
attrib = LM_COL_ATTR(lmp, col) | XI_ATR_VISIBLE |
|
|
(lmp->min_cell_height ? XI_ATR_VCENTER : 0);
|
|
if (cell_attrib)
|
|
{
|
|
attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
attrib |= cell_attrib;
|
|
}
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
rct.left += col_offset;
|
|
rct.right -= col_offset;
|
|
if (! column_data->wrap_text)
|
|
{
|
|
if (column_data->vertical_align_bottom)
|
|
{
|
|
int new_top;
|
|
|
|
#if XVTWS == WMWS
|
|
new_top = rct.bottom - (leading + ascent + descent);
|
|
#else
|
|
new_top = rct.bottom - (leading + ascent + descent) - 3;
|
|
#endif
|
|
rct.top = max(rct.top, new_top);
|
|
}
|
|
else if (! column_data->vertical_align_center)
|
|
{
|
|
int new_bottom;
|
|
|
|
#if XVTWS == WMWS
|
|
new_bottom = rct.top + leading + ascent + descent;
|
|
#else
|
|
new_bottom = rct.top + leading + ascent + descent + 4;
|
|
#endif
|
|
rct.bottom = min(rct.bottom, new_bottom);
|
|
}
|
|
}
|
|
if (button)
|
|
{
|
|
RCT r;
|
|
|
|
r = rct;
|
|
xi_inflate_rect(&r, 1);
|
|
if (button_on_left)
|
|
{
|
|
r.right = r.left + lmp->pix_row_spacing;
|
|
rct.left = r.right;
|
|
}
|
|
else
|
|
{
|
|
r.left = r.right - lmp->pix_row_spacing;
|
|
rct.right = r.left - (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
}
|
|
}
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
rct.top += RULE_Y_OFFSET_TOP;
|
|
rct.bottom -= RULE_Y_OFFSET_BOTTOM;
|
|
CTOS_END;
|
|
#endif
|
|
|
|
if (column_data->column_well || column_data->column_platform)
|
|
{
|
|
rct.left++;
|
|
rct.right--;
|
|
}
|
|
if (xvt_dwin_set_clip)
|
|
{
|
|
RCT mlr = lmp->mlr;
|
|
|
|
if (lmp->pixel_width)
|
|
mlr.right = mlr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_rect_intersect(&mlr, &mlr, &rct);
|
|
xi_set_clip(win, &mlr);
|
|
}
|
|
if (column_data->wrap_text)
|
|
{
|
|
int nbr_lines, cnt;
|
|
char* s;
|
|
|
|
lm_wrap_text(lmp, row, col, FALSE);
|
|
nbr_lines = min(cell_data->nbr_lines, lmp->max_lines_in_cell);
|
|
s = LM_CELL_TEXT(lmp, row, col);
|
|
for (cnt = 0; cnt < nbr_lines; ++cnt)
|
|
{
|
|
int len = -1;
|
|
|
|
if (cnt < nbr_lines - 1)
|
|
len = cell_data->line_breaks[cnt + 1] - cell_data->line_breaks[cnt];
|
|
#if XIWS == WMWS
|
|
baseline = rct.top + 8;
|
|
#else
|
|
baseline = rct.top + leading + ascent;
|
|
#endif
|
|
if ((&s[cell_data->line_breaks[cnt]])[len - 1] == '\n')
|
|
len--;
|
|
xi_draw_text(win, rct.left, baseline, &s[cell_data->line_breaks[cnt]], len);
|
|
#if XVTWS == WMWS
|
|
rct.top += cell_data->font_height;
|
|
#else
|
|
rct.top += cell_data->font_height - 1;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = lmp->buffer[row] + column_data->text_offset;
|
|
len = strlen(s);
|
|
len = min(len, sizeof(buf) - 1);
|
|
if (attrib & XI_ATR_PASSWORD)
|
|
memset(buf, XI_PASSWORD_CHAR, len);
|
|
else
|
|
gstrncpy(buf, s, len);
|
|
buf[len] = '\0';
|
|
rule_and_space = lmp->min_cell_height ? RULE_Y_OFFSET_TOP : 0;
|
|
#if XIWS == WMWS
|
|
baseline = rct.top + 8;
|
|
#else
|
|
if (attrib & XI_ATR_VCENTER)
|
|
baseline = rct.top + leading + ascent + rule_and_space +
|
|
(rct.bottom - rct.top - leading - ascent - descent) / 2 - 1;
|
|
else
|
|
baseline = rct.top + leading + ascent + rule_and_space;
|
|
#endif
|
|
if (attrib & XI_ATR_RJUST)
|
|
{
|
|
wid = xi_xvt_get_text_width(win, buf, -1);
|
|
xi_draw_text(win, rct.right - wid, baseline, buf, len);
|
|
}
|
|
else
|
|
{
|
|
if (attrib & XI_ATR_HCENTER)
|
|
{
|
|
int x;
|
|
|
|
wid = xi_xvt_get_text_width(win, buf, len);
|
|
x = (rct.left + rct.right) / 2 - wid / 2;
|
|
if (x < rct.left)
|
|
x = rct.left;
|
|
xi_draw_text(win, x, baseline, buf, len);
|
|
}
|
|
else
|
|
xi_draw_text(win, rct.left, baseline, buf, len);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
fast_draw_all_cell_text(LM_DATA *lmp, WINDOW win, ROW_INFO *row_info,
|
|
int col_offset, int first_row, int last_row, RCT* list_rect)
|
|
{
|
|
DRAW_CTOOLS ctools;
|
|
int row, col;
|
|
ROW_INFO *ri;
|
|
LM_COLUMN_DATA *column_data;
|
|
int leading, ascent, descent;
|
|
BOOLEAN have_last_font;
|
|
XVT_FNTID *last_font;
|
|
|
|
ctools = lm_normal_ctools;
|
|
|
|
/* the following two lines must come before the xi_set_xvt_font, because in
|
|
R3, setting the draw ctools also sets the font.
|
|
*/
|
|
|
|
if (LIST_IS_ENABLED(lmp))
|
|
ctools.fore_color = lmp->enabled_color;
|
|
else
|
|
ctools.fore_color = lmp->disabled_color;
|
|
#if XVTWS == WMWS
|
|
ctools.back_color = lmp->back_color;
|
|
#endif
|
|
xi_set_draw_ctools(win, &ctools);
|
|
|
|
xi_set_xvt_font(win, lmp->font, FALSE);
|
|
xi_get_font_metrics(win, &leading, &ascent, &descent);
|
|
|
|
/* draw default font, not wrapped text, not selected cells */
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
RCT clip_rect;
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
if (column_data->wrap_text)
|
|
continue;
|
|
if ((column_data->attrib & XI_ATR_ENABLED) == 0)
|
|
xi_set_xvt_fore_color(win, lmp->disabled_color);
|
|
else
|
|
xi_set_xvt_fore_color(win, ctools.fore_color);
|
|
if (!xi_rect_intersect( &clip_rect, &column_data->prct, list_rect ))
|
|
continue;
|
|
xi_set_clip(win, &clip_rect);
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (lmp->row_colors[row])
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (cell_data->color)
|
|
continue;
|
|
if (cell_data->font)
|
|
continue;
|
|
if (cell_data->icon_rid)
|
|
continue;
|
|
if (CELL_IS_SELECTED(lmp, row, col))
|
|
continue;
|
|
fast_draw_cell_text(lmp, cell_data, column_data,
|
|
row, col, ri, col_offset, leading, ascent,
|
|
descent, FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
draw default font, colored text
|
|
*/
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
RCT clip_rect;
|
|
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
if (column_data->wrap_text)
|
|
continue;
|
|
if (!xi_rect_intersect( &clip_rect, &column_data->prct, list_rect ))
|
|
continue;
|
|
xi_set_clip(win, &clip_rect);
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
COLOR color;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (cell_data->font)
|
|
continue;
|
|
if (cell_data->icon_rid)
|
|
continue;
|
|
if (CELL_IS_SELECTED(lmp, row, col))
|
|
{
|
|
color = lmp->back_color;
|
|
if (column_data->column_well || column_data->column_platform)
|
|
color = lmp->enabled_color;
|
|
if (cell_data->back_color)
|
|
if (lmp->retain_back_color_on_select)
|
|
color = lmp->enabled_color;
|
|
else
|
|
color = cell_data->back_color;
|
|
}
|
|
else
|
|
{
|
|
color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
color = cell_data->color;
|
|
if ((column_data->attrib & XI_ATR_ENABLED) == 0)
|
|
color = lmp->disabled_color;
|
|
}
|
|
if (! color)
|
|
continue;
|
|
xi_set_xvt_fore_color(win, color);
|
|
#if XVTWS == WMWS
|
|
xi_set_xvt_back_color(win, lmp->enabled_color);
|
|
#endif
|
|
fast_draw_cell_text(lmp, cell_data, column_data,
|
|
row, col, ri, col_offset, leading, ascent,
|
|
descent, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/* draw default font, black text, wrapped text */
|
|
/*
|
|
this needs to be a separate loop from above, because this loop sets the
|
|
clipping region for each cell, and the above loop sets the clipping region
|
|
for each column.
|
|
*/
|
|
xi_set_xvt_fore_color(win, COLOR_BLACK);
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
if (! column_data->wrap_text)
|
|
continue;
|
|
if ((column_data->attrib & XI_ATR_ENABLED) == 0)
|
|
xi_set_xvt_fore_color(win, lmp->disabled_color);
|
|
else
|
|
xi_set_xvt_fore_color(win, COLOR_BLACK);
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (lmp->row_colors[row])
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (cell_data->color)
|
|
continue;
|
|
if (cell_data->font)
|
|
continue;
|
|
if (cell_data->icon_rid)
|
|
continue;
|
|
if (CELL_IS_SELECTED(lmp, row, col))
|
|
continue;
|
|
fast_draw_cell_text(lmp, cell_data, column_data,
|
|
row, col, ri, col_offset, leading, ascent,
|
|
descent, TRUE);
|
|
}
|
|
}
|
|
|
|
/* draw default font, colored text, wrapped text */
|
|
/*
|
|
this needs to be a separate loop from above, because this loop sets the
|
|
colors for each cell, and the above loop only draws black.
|
|
*/
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
if (! column_data->wrap_text)
|
|
continue;
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
COLOR color;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (cell_data->font)
|
|
continue;
|
|
if (cell_data->icon_rid)
|
|
continue;
|
|
if (CELL_IS_SELECTED(lmp, row, col))
|
|
{
|
|
color = lmp->back_color;
|
|
if (column_data->column_well || column_data->column_platform)
|
|
color = lmp->enabled_color;
|
|
if (cell_data->back_color)
|
|
if (lmp->retain_back_color_on_select)
|
|
color = lmp->enabled_color;
|
|
else
|
|
color = cell_data->back_color;
|
|
}
|
|
else
|
|
{
|
|
color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
color = cell_data->color;
|
|
if ((column_data->attrib & XI_ATR_ENABLED) == 0)
|
|
color = lmp->disabled_color;
|
|
}
|
|
if (! color)
|
|
continue;
|
|
xi_set_xvt_fore_color(win, color);
|
|
fast_draw_cell_text(lmp, cell_data, column_data,
|
|
row, col, ri, col_offset, leading, ascent,
|
|
descent, TRUE);
|
|
}
|
|
}
|
|
|
|
/* draw all of the rest of the text */
|
|
have_last_font = FALSE;
|
|
last_font = NULL;
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
COLOR color;
|
|
BOOLEAN need_to_set;
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
cell_data = &lmp->cell_data[row][col];
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
if (! cell_data->font)
|
|
continue;
|
|
if (cell_data->icon_rid)
|
|
continue;
|
|
need_to_set = FALSE;
|
|
if (! have_last_font)
|
|
need_to_set = TRUE;
|
|
if (have_last_font && ! font_compare(*last_font, *cell_data->font))
|
|
need_to_set = TRUE;
|
|
if (need_to_set)
|
|
{
|
|
int char_width;
|
|
|
|
xi_set_xvt_font(win, cell_data->font, FALSE);
|
|
xi_get_font_metrics_font(cell_data->font, &leading, &ascent,
|
|
&descent, &char_width);
|
|
last_font = cell_data->font;
|
|
have_last_font = TRUE;
|
|
}
|
|
if (CELL_IS_SELECTED(lmp, row, col))
|
|
{
|
|
color = lmp->back_color;
|
|
if (cell_data->back_color)
|
|
if (lmp->retain_back_color_on_select)
|
|
color = lmp->enabled_color;
|
|
else
|
|
color = cell_data->back_color;
|
|
}
|
|
else
|
|
{
|
|
color = lmp->row_colors[row];
|
|
if (cell_data->color)
|
|
color = cell_data->color;
|
|
if ((column_data->attrib & XI_ATR_ENABLED) == 0)
|
|
color = lmp->disabled_color;
|
|
}
|
|
xi_set_xvt_fore_color(win, color);
|
|
|
|
fast_draw_cell_text(lmp, cell_data, column_data,
|
|
row, col, ri, col_offset, leading, ascent,
|
|
descent, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if XVTWS != WMWS
|
|
static void
|
|
fast_draw_row_focus_border(LM_DATA *lmp, ROW_INFO *row_info, int first_row, int last_row)
|
|
{
|
|
int col, row;
|
|
LM_COLUMN_DATA *column_data;
|
|
ROW_INFO *ri;
|
|
CPEN color_cpen;
|
|
CPEN rule_cpen;
|
|
BOOLEAN last_was_rule = TRUE;
|
|
RCT mr;
|
|
|
|
if (! lmp->row_focus_border)
|
|
return;
|
|
color_cpen.width = 1;
|
|
color_cpen.color = lmp->row_focus_border_color;
|
|
color_cpen.pat = PAT_SOLID;
|
|
color_cpen.style = P_SOLID;
|
|
rule_cpen.width = 1;
|
|
rule_cpen.color = lmp->rule_color;
|
|
rule_cpen.pat = PAT_SOLID;
|
|
rule_cpen.style = P_SOLID;
|
|
xi_set_cpen(lmp->win, &rule_cpen);
|
|
{
|
|
mr = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
xi_set_clip(lmp->win, &mr);
|
|
}
|
|
for (row = first_row, ri = &row_info[first_row]; row <= last_row; ++row, ++ri)
|
|
{
|
|
RCT rct;
|
|
PNT p;
|
|
WINDOW win = lmp->win;
|
|
BOOLEAN row_has_focus = lm_row_has_focus(lmp, row, FALSE);
|
|
|
|
if (! ri->needs_update)
|
|
continue;
|
|
if (row_has_focus)
|
|
{
|
|
if (last_was_rule)
|
|
{
|
|
xi_set_cpen(lmp->win, &color_cpen);
|
|
last_was_rule = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (! last_was_rule)
|
|
{
|
|
xi_set_cpen(lmp->win, &rule_cpen);
|
|
last_was_rule = TRUE;
|
|
}
|
|
}
|
|
for (col = 0; col < lmp->nbr_columns; ++col)
|
|
{
|
|
column_data = lmp->lm_column_data[col];
|
|
if (! column_data->needs_update)
|
|
continue;
|
|
rct = column_data->prct;
|
|
rct.top = ri->prct.top;
|
|
rct.bottom = ri->prct.bottom;
|
|
|
|
/* draw top line */
|
|
p.h = rct.left;
|
|
p.v = rct.top - 1;
|
|
xi_move_to(win, p);
|
|
p.h = rct.right;
|
|
xi_draw_line(win, p);
|
|
|
|
if (row_has_focus)
|
|
{
|
|
/* draw next line down */
|
|
p.v++;
|
|
p.h = rct.left;
|
|
xi_move_to(win, p);
|
|
p.h = rct.right;
|
|
xi_draw_line(win, p);
|
|
}
|
|
|
|
/* draw bottom line */
|
|
p.h = rct.left;
|
|
p.v = rct.bottom;
|
|
xi_move_to(win, p);
|
|
p.h = rct.right;
|
|
xi_draw_line(win, p);
|
|
|
|
if (row_has_focus)
|
|
{
|
|
/* draw line above bottom line */
|
|
p.v--;
|
|
p.h = rct.left;
|
|
xi_move_to(win, p);
|
|
p.h = rct.right;
|
|
xi_draw_line(win, p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* draw_cell_block */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
draw_cell_block( LM_DATA* lmp, int first_row, int last_row,
|
|
ROW_INFO* row_info )
|
|
{
|
|
WINDOW win = lmp->win;
|
|
RCT actual_rct = lmp->mlr;
|
|
int actual_r;
|
|
int col_offset;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->mlr.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->mlr.right;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->mlr.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->mlr.right;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
|
|
xi_set_clip(win, &actual_rct);
|
|
|
|
/* draw all rectangles that are not white */
|
|
fast_draw_exception_rects(lmp, win, row_info, first_row, last_row);
|
|
|
|
/* draw all of the text in the cells */
|
|
fast_draw_all_cell_text(lmp, win, row_info, col_offset, first_row, last_row,
|
|
&actual_rct );
|
|
|
|
/* draw cell buttons */
|
|
fast_draw_cell_buttons(lmp, row_info, first_row, last_row);
|
|
|
|
fast_draw_cell_icons(lmp, win, row_info, first_row, last_row);
|
|
|
|
#if XVTWS != WMWS
|
|
draw_row_rules(lmp, first_row, last_row, FALSE);
|
|
|
|
fast_draw_row_focus_border(lmp, row_info, first_row, last_row);
|
|
#endif
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* draw_cell_range */
|
|
/* ------------------------------------------------------------------------- */
|
|
void
|
|
draw_cell_range( LM_DATA* lmp, int first_row, int last_row,
|
|
int first_col, int last_col,
|
|
BOOLEAN in_event_update )
|
|
{
|
|
int row, col;
|
|
ROW_INFO* row_info;
|
|
ROW_INFO* row_ptr;
|
|
|
|
if (lmp->list_obj->nbr_children <= 0) return;
|
|
if (xi_get_attrib(lmp->list_obj) & XI_ATR_VISIBLE)
|
|
{
|
|
row_info = (ROW_INFO *)xvt_mem_alloc(sizeof(ROW_INFO) * (last_row + 1));
|
|
for ( row = first_row, row_ptr = row_info + first_row; row <= last_row;
|
|
++row, ++row_ptr)
|
|
{
|
|
lm_get_row_rect(&row_ptr->rct, (LM)lmp, row);
|
|
/* don't need to test for the rule, it is drawn elsewhere */
|
|
#if XVTWS != WMWS
|
|
row_ptr->rct.bottom--;
|
|
if (row_ptr->rct.bottom < row_ptr->rct.top)
|
|
row_ptr->rct.bottom = row_ptr->rct.top;
|
|
#endif
|
|
row_ptr->prct = row_ptr->rct;
|
|
lm_adj_v(lmp, row_ptr->prct.top);
|
|
lm_adj_v(lmp, row_ptr->prct.bottom);
|
|
if (in_event_update)
|
|
{
|
|
if (lm_needs_update(lmp, &row_ptr->rct, FALSE, TRUE))
|
|
row_ptr->needs_update = TRUE;
|
|
else
|
|
row_ptr->needs_update = FALSE;
|
|
}
|
|
else
|
|
row_ptr->needs_update = TRUE;
|
|
}
|
|
|
|
/*
|
|
force cell requests for cells that have suppress_update_cells set to true
|
|
*/
|
|
for (col = first_col; col <= last_col; ++col)
|
|
{
|
|
if (lmp->lm_column_data[col]->suppress_update_cells)
|
|
{
|
|
for (row = first_row; row <= last_row; ++row)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &(lmp->cell_data[row][col]);
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, col, TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
determine which columns need to be updated
|
|
*/
|
|
fast_calc_col_needs_update(lmp, first_col, last_col, in_event_update);
|
|
|
|
/*
|
|
at this point, we should never need to call lm_needs_update again in this function
|
|
or any called functions.
|
|
*/
|
|
draw_cell_block( lmp, first_row, last_row, row_info );
|
|
xvt_mem_free((char *)row_info);
|
|
}
|
|
}
|
|
|
|
/*********** draw cells ***********/
|
|
static void
|
|
fast_draw_cells(LM_DATA *lmp, BOOLEAN update)
|
|
{
|
|
int first_row;
|
|
int last_row;
|
|
|
|
first_row = lmp->first_fully_vis;
|
|
if (first_row < 0)
|
|
first_row = 0;
|
|
last_row = min(lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1);
|
|
if (last_row < 0)
|
|
return;
|
|
draw_cell_range( lmp, first_row, last_row, 0, lmp->nbr_columns - 1, update );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: redraw_cell
|
|
lm: current lm
|
|
row:
|
|
col:
|
|
update: if TRUE, redraw_cell is being called due to an E_UPDATE event.
|
|
clip_rct: clip rectangle
|
|
-------------------------------------------------------------------------*/
|
|
/*-------------------------------------------------------------------------*/
|
|
/* redraw_cell */
|
|
/*-------------------------------------------------------------------------*/
|
|
void redraw_cell( LM lm, int row, int col, BOOLEAN update )
|
|
{
|
|
draw_cell_range( (LM_DATA*)lm, row, row, col, col, update );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_redraw_row */
|
|
/*-------------------------------------------------------------------------*/
|
|
void lm_redraw_row(LM_DATA *lmp, int row, BOOLEAN update )
|
|
{
|
|
draw_cell_range( lmp, row, row, 0, lmp->nbr_columns - 1, update );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* draw_other_rectangles */
|
|
/*-------------------------------------------------------------------------*/
|
|
static void
|
|
draw_other_rectangles(LM_DATA *lmp, RCT *actual_rct)
|
|
{
|
|
WINDOW win = lmp->win;
|
|
RCT lmp_rct, vr, hr;
|
|
int i, actual_r, hrule_h;
|
|
CBRUSH cbrush;
|
|
XI_LIST_DATA *list_data;
|
|
XI_OBJ *list_obj;
|
|
|
|
#if XVTWS == WMWS
|
|
NOREF(lmp_rct);
|
|
NOREF(hrule_h);
|
|
NOREF(list_data);
|
|
#endif
|
|
lmp_rct = lmp->rct;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
list_obj = lmp->list_obj;
|
|
list_data = list_obj->v.list;
|
|
hrule_h = actual_r;
|
|
|
|
/*********** Graphical: border at right of last column ***********/
|
|
/*********** Graphical: rectangle around entire list ***********/
|
|
/*********** Graphical: rectangle at bottom of list ***********/
|
|
/* NOTE: GRAPHICAL SYSTEMS ONLY, HERE. CH is in beginning of draw_lm */
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
xi_set_clip(win, actual_rct);
|
|
xi_set_cpen(win, &black_cpen);
|
|
xi_set_draw_mode(win, M_COPY);
|
|
if (lmp->pixel_width)
|
|
{
|
|
PNT p, p2;
|
|
int width;
|
|
RCT r;
|
|
|
|
p.h = lmp->rct.right - 1 - lmp->rct.left;
|
|
p.v = lmp_rct.top;
|
|
p2 = p;
|
|
p2.v = min(lmp_rct.bottom, lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top);
|
|
width = BORDER_WIDTH;
|
|
if (lmp->no_vert_lines)
|
|
{
|
|
CPEN back_cpen;
|
|
|
|
back_cpen = black_cpen;
|
|
back_cpen.color = lmp->back_color;
|
|
xi_set_cpen(win, &back_cpen);
|
|
} else
|
|
xi_set_cpen(win, &black_cpen);
|
|
WIDTHLOOP(i, width)
|
|
{
|
|
lm_move_to(lmp, p, FALSE, TRUE);
|
|
lm_draw_line(lmp, p2, FALSE, TRUE);
|
|
--p.h;
|
|
--p2.h;
|
|
}
|
|
r = lmp->rct;
|
|
r.left = lmp->rct.right - lmp->rct.left;
|
|
if (lmp->list_obj->nbr_children <= 0) r.left -= lmp->pixel_width;
|
|
r.right = 9999;
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
cbrush.pat = PAT_SOLID;
|
|
cbrush.color = lmp->white_space_color;
|
|
xi_set_cbrush(win, &cbrush);
|
|
xi_set_clip(win, actual_rct);
|
|
|
|
#if XIWS == XOLWS || XIWS == MTFWS
|
|
/* X GRAY SCALE HACK */
|
|
xi_set_xvt_back_color(win, COLOR_WHITE);
|
|
{
|
|
DRAW_CTOOLS ct;
|
|
|
|
xi_get_draw_ctools(win, &ct);
|
|
ct.opaque_text = FALSE;
|
|
xi_set_draw_ctools(win, &ct);
|
|
xi_draw_text(win, r.left, r.top, " ", -1);
|
|
}
|
|
#endif
|
|
|
|
lm_draw_rect(lmp, &r, FALSE);
|
|
|
|
/* draw border around entire list */
|
|
lmp_rct.right = actual_r;
|
|
{
|
|
RCT r;
|
|
CBRUSH cb;
|
|
|
|
r = lmp->rct;
|
|
if (list_data->sb_win)
|
|
{
|
|
xi_get_sb_rect(list_obj, &vr);
|
|
/*
|
|
add one, so that one pixel of the double border will overlap one pixel of the
|
|
scroll bar.
|
|
*/
|
|
r.right = vr.right + 1;
|
|
}
|
|
else
|
|
if (list_data->hsb_win)
|
|
r.right = r.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
xi_get_hsb_rect(list_obj, &hr);
|
|
r.bottom = hr.bottom + 1;
|
|
xi_set_cbrush(win, &hollow_cbrush);
|
|
xi_set_cpen(win, &black_cpen);
|
|
xi_set_clip(win, NULL);
|
|
xi_draw_rect(win, &r);
|
|
xi_inflate_rect(&r, -1);
|
|
xi_draw_rect(win, &r);
|
|
|
|
cb = white_cbrush;
|
|
cb.color = lmp->white_space_color;
|
|
xi_set_cbrush(win, &cb);
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
r.left += 1;
|
|
r.top = lmp->rct.bottom;
|
|
r.right -= 1;
|
|
r.bottom -= 1;
|
|
xi_draw_rect(win, &r);
|
|
}
|
|
}
|
|
|
|
{ /* rectangle at bottom of list */
|
|
RCT r;
|
|
RCT hsb_rect;
|
|
|
|
xi_get_hsb_rect(lmp->list_obj, &hsb_rect);
|
|
cbrush.pat = PAT_SOLID;
|
|
cbrush.color = lmp->white_space_color;
|
|
xi_set_cbrush(win, &cbrush);
|
|
r = lmp->mlr;
|
|
r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
r.top = min(r.top, hsb_rect.top);
|
|
r.bottom = hsb_rect.bottom;
|
|
r.right = lmp->rct.right;
|
|
if (lmp->pixel_width)
|
|
r.right = lmp->rct.left + lmp->pixel_width + 2;
|
|
if (r.top < r.bottom)
|
|
{
|
|
#if XIWS == XOLWS || XIWS == MTFWS
|
|
/* X GRAY SCALE HACK */
|
|
xi_set_xvt_back_color(win, COLOR_WHITE);
|
|
{
|
|
DRAW_CTOOLS ct;
|
|
|
|
xi_get_draw_ctools(win, &ct);
|
|
ct.opaque_text = FALSE;
|
|
xi_set_draw_ctools(win, &ct);
|
|
xi_draw_text(win, r.left, r.top, " ", -1);
|
|
}
|
|
#endif
|
|
}
|
|
xi_draw_rect(win, &r);
|
|
}
|
|
|
|
/* border around entire list */
|
|
if (! (lmp->update_rows_at_top + lmp->update_rows_at_bottom))
|
|
{
|
|
xi_set_cpen(win, &black_cpen);
|
|
xi_set_cbrush(win, &hollow_cbrush);
|
|
xi_set_draw_mode(win, M_COPY);
|
|
xi_set_clip(win, NULL);
|
|
lmp_rct = lmp->rct;
|
|
if (lmp->pixel_width)
|
|
lmp_rct.right = hrule_h;
|
|
WIDTHLOOP(i, BORDER_WIDTH)
|
|
{
|
|
xi_draw_rect(win, &lmp_rct);
|
|
xi_inflate_rect(&lmp_rct, -1);
|
|
}
|
|
CTOS_END;
|
|
}
|
|
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
xi_set_clip(win, actual_rct);
|
|
xi_set_cpen(win, &black_cpen);
|
|
xi_set_draw_mode(win, M_COPY);
|
|
if (lmp->pixel_width)
|
|
{
|
|
RCT r;
|
|
PNT p1, p2;
|
|
|
|
r = lmp->rct;
|
|
r.left = lmp->rct.right - lmp->rct.left + BORDER_WIDTH;
|
|
r.top += BORDER_WIDTH;
|
|
r.right = 9999;
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
cbrush.pat = PAT_SOLID;
|
|
cbrush.color = lmp->white_space_color;
|
|
xi_set_cbrush(win, &cbrush);
|
|
xi_set_clip(win, actual_rct);
|
|
lm_draw_rect(lmp, &r, FALSE);
|
|
|
|
xi_set_cpen(win, &black_cpen);
|
|
p1.h = r.left;
|
|
p1.v = lmp->rct.top;
|
|
p2.h = r.left;
|
|
p2.v = r.bottom;
|
|
lm_move_to(lmp, p1, FALSE, TRUE);
|
|
lm_draw_line(lmp, p2, FALSE, TRUE);
|
|
|
|
}
|
|
|
|
{ /* rectangle at bottom of list */
|
|
RCT r;
|
|
|
|
cbrush.pat = PAT_SOLID;
|
|
cbrush.color = lmp->white_space_color;
|
|
xi_set_cbrush(win, &cbrush);
|
|
xi_set_cpen(win, &hollow_cpen);
|
|
r = lmp->mlr;
|
|
r.left += BORDER_WIDTH;
|
|
r.top = lmp->rrr_bottom + lmp->rrr_offset + lmp->mlr.top;
|
|
r.right = lmp->rct.right;
|
|
if (lmp->pixel_width)
|
|
r.right = lmp->rct.left + 2 * lmp->pixel_width;
|
|
if (r.top < r.bottom)
|
|
xi_draw_rect(win, &r);
|
|
}
|
|
CTOS_END;
|
|
#endif
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
lmp->update_cells_only = FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
lm: current lm
|
|
update: if TRUE, draw_lm is being called due to an E_UPDATE event
|
|
-------------------------------------------------------------------------*/
|
|
static void near
|
|
draw_lm(LM lm, BOOLEAN update)
|
|
{
|
|
int hrule_h, actual_r, idx;
|
|
RCT lmp_rct, actual_rct, clip_rct;
|
|
RCT hr, vr, urct;
|
|
XI_OBJ *list_obj;
|
|
XI_LIST_DATA *list_data;
|
|
LM_DATA *lmp = LMP(lm);
|
|
WINDOW win = lmp->win;
|
|
CBRUSH back_cbrush;
|
|
#if XI_IS_CH
|
|
CBRUSH lm_cbrush;
|
|
PNT from_p;
|
|
|
|
#if XVTWS == WMWS
|
|
NOREF(urct);
|
|
#endif
|
|
/***********************************************************************/
|
|
/* set up variables for drawing */
|
|
#if XVT_OS != XVT_OS_CTOS
|
|
c_xd = C_XD;
|
|
c_xu = C_XU;
|
|
c_v = C_V;
|
|
c_xx = C_XX;
|
|
#else
|
|
c_xd = 220;
|
|
c_xu = 221;
|
|
c_v = 225;
|
|
c_xx = 218;
|
|
c_xr = 226;
|
|
c_xl = 227;
|
|
#endif
|
|
#endif
|
|
if (! (lmp->attrib & LM_ATR_VISIBLE))
|
|
{
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
return;
|
|
}
|
|
list_obj = lmp->list_obj;
|
|
list_data = list_obj->v.list;
|
|
lmp_rct = lmp->rct;
|
|
actual_rct = lmp_rct;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
else
|
|
actual_r = lmp->rct.right;
|
|
actual_rct.right = actual_r - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
actual_r = lmp->rct.left + lmp->pixel_width;
|
|
else
|
|
actual_r = lmp->rct.right + 8;
|
|
actual_rct.right = actual_r;
|
|
CTOS_END;
|
|
#endif
|
|
hrule_h = actual_r;
|
|
if (lmp->pixel_width)
|
|
lmp_rct.right = hrule_h;
|
|
urct = lmp_rct;
|
|
if (list_data->sb_win)
|
|
{
|
|
if (list_data->have_sb_rct)
|
|
vr = list_data->sb_rct;
|
|
else
|
|
xi_get_sb_rect(list_obj, &vr);
|
|
urct.right = vr.right;
|
|
}
|
|
if (list_data->hsb_win)
|
|
{
|
|
if (list_data->have_hsb_rct)
|
|
hr = list_data->hsb_rct;
|
|
else
|
|
xi_get_hsb_rect(list_obj, &hr);
|
|
urct.bottom = hr.bottom;
|
|
}
|
|
#if XIWS != WMWS
|
|
if (update && !xi_needs_update(win, &urct))
|
|
{
|
|
lmp->update_rows_at_top = 0;
|
|
lmp->update_rows_at_bottom = 0;
|
|
return;
|
|
}
|
|
#endif
|
|
lmp_rct = lmp->rct;
|
|
if (lmp->nbr_realized_rows)
|
|
{
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
|
|
}
|
|
else
|
|
lmp->rrr_bottom = 0;
|
|
if (! lm_tools_inited)
|
|
{
|
|
lm_white_cbrush.color = COLOR_WHITE;
|
|
lm_white_cbrush.pat = PAT_SOLID;
|
|
lm_black_cpen.width = 1;
|
|
lm_black_cpen.color = COLOR_BLACK;
|
|
lm_black_cpen.pat = PAT_SOLID;
|
|
lm_black_cpen.style = P_SOLID;
|
|
xvt_app_get_default_ctools(&lm_normal_ctools);
|
|
}
|
|
|
|
/***********************************************************************/
|
|
/* draw anything other than in the cell region */
|
|
/* prior to this, there are no calls to XVT for drawing */
|
|
|
|
back_cbrush = lm_white_cbrush;
|
|
/*
|
|
TO OPTIMIZE BACKGROUND DRAWING, USE THE FOLLOWING LINE, AND DON'T SET TO HOLLOW
|
|
back_cbrush.color = lmp->back_color;
|
|
*/
|
|
#if XIWS != WMWS
|
|
back_cbrush.pat = PAT_HOLLOW;
|
|
#endif
|
|
xi_set_cbrush(win, &back_cbrush);
|
|
xi_set_cpen(win, &lm_black_cpen);
|
|
clip_rct = actual_rct;
|
|
#if XVTWS == WMWS
|
|
if (list_data->hsb_win)
|
|
clip_rct.bottom += 8;
|
|
clip_rct.right += 8;
|
|
#endif
|
|
xi_set_clip(win, &clip_rct);
|
|
xi_set_draw_mode(win, M_COPY);
|
|
|
|
/*
|
|
CBRUSH: white_cbrush
|
|
CPEN: black_cpen
|
|
CLIP: actual_rct
|
|
*/
|
|
|
|
/*********** draw the rectangle around the list ***********/
|
|
draw_list_rect(lmp, &vr, &hr);
|
|
|
|
#if XVTWS == WMWS
|
|
xi_set_clip(win, &actual_rct);
|
|
#endif
|
|
|
|
/*********** draw the rules between the heading and the cells ***********/
|
|
if (! lmp->update_cells_only)
|
|
draw_heading_rules(lmp, hrule_h);
|
|
|
|
/*********** draw column rules ***********/
|
|
draw_column_rules(lmp);
|
|
|
|
/*
|
|
CBRUSH: white_cbrush
|
|
CPEN: black_cpen OR back_color cpen
|
|
CLIP: actual_rct
|
|
*/
|
|
|
|
#if 0
|
|
/*********** draw row rules ***********/
|
|
/* this was moved to draw_cell_block */
|
|
draw_row_rules(lmp, -1, -1, update);
|
|
#endif
|
|
|
|
/*********** draw column headings ***********/
|
|
if (! lmp->update_cells_only)
|
|
draw_column_headings(lmp, &actual_rct);
|
|
xi_set_clip(win, NULL);
|
|
|
|
/*********** draw text in cells ***********/
|
|
fast_draw_cells(lmp, update);
|
|
|
|
draw_other_rectangles(lmp, &actual_rct);
|
|
|
|
/*********** draw column rules ***********/
|
|
/* Moved after the draw row rules otherwise
|
|
no_horz_lines results in spotted vertical lines */
|
|
if (lmp->no_horz_lines && ! lmp->no_vert_lines)
|
|
draw_column_rules(lmp);
|
|
|
|
|
|
xi_set_clip(win, NULL);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
oevt: original xvt event, without virtual space coordinate conversions
|
|
rowp: if set, to be filled in with the results of the row hit test
|
|
columnp: if set, to be filled in with the results of the column hit test
|
|
is_vis: row is fully visible
|
|
is_part_vis:row is partially visible
|
|
returns: 0 - no hit
|
|
1 - hit
|
|
5 - hit on cell button
|
|
-------------------------------------------------------------------------*/
|
|
static int near
|
|
lm_hit_test(LM lm, EVENT *ep, EVENT *oevt, int *rowp, int *columnp,
|
|
BOOLEAN *is_vis, BOOLEAN *is_hit, BOOLEAN *is_part_vis)
|
|
{
|
|
int row, column, temp, col_offset, tmp_v, i, first, last;
|
|
int *pix_offsetsp, *pix_heightsp;
|
|
LM_DATA *lmp = LMP(lm);
|
|
PNT where;
|
|
|
|
if (is_vis)
|
|
*is_vis = TRUE;
|
|
if (is_hit)
|
|
*is_hit = FALSE;
|
|
if (is_part_vis)
|
|
*is_part_vis = FALSE;
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
where = ep->v.mouse.where;
|
|
|
|
/* if the mouse is to the left or the right of the list, return 0 */
|
|
if (oevt->v.mouse.where.h < 0)
|
|
return 0;
|
|
if (lmp->pixel_width &&
|
|
(oevt->v.mouse.where.h > (lmp->rct.left + lmp->pixel_width
|
|
+ BORDER_WIDTH)))
|
|
return 0;
|
|
|
|
/* if the mouse is in the column headings */
|
|
if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top)
|
|
{
|
|
for (column = 0; column < lmp->nbr_columns; column++)
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos + col_offset;
|
|
if (where.h >= temp && where.h < temp + column_data->pix_width)
|
|
{
|
|
*rowp = -1;
|
|
*columnp = column;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* if the mouse is above the list, return 0 */
|
|
if (where.v < lmp->pix_row1_top)
|
|
return 0;
|
|
|
|
/* figure out what row the mouse is in */
|
|
tmp_v = where.v - lmp->mlr.top - lmp->rrr_offset;
|
|
first = max(lmp->first_fully_vis - 1, 0);
|
|
last = min(lmp->last_fully_vis + 1, lmp->nbr_realized_rows - 1);
|
|
for (i = first,
|
|
pix_offsetsp = &lmp->pix_offsets[i],
|
|
pix_heightsp = &lmp->pix_heights[i];
|
|
i <= last; ++i, ++pix_offsetsp, ++pix_heightsp)
|
|
{
|
|
if (tmp_v >= *pix_offsetsp && tmp_v < (*pix_offsetsp + *pix_heightsp))
|
|
{
|
|
row = i;
|
|
break;
|
|
}
|
|
}
|
|
if (i > last)
|
|
{
|
|
if (is_vis)
|
|
*is_vis = FALSE;
|
|
return 0;
|
|
}
|
|
if (is_vis)
|
|
{
|
|
if (i < lmp->first_fully_vis || i > lmp->last_fully_vis)
|
|
{
|
|
*is_vis = FALSE;
|
|
if ((i == lmp->last_fully_vis + 1) && (ep->v.mouse.where.v < lmp->mlr.bottom))
|
|
{
|
|
if (is_part_vis)
|
|
*is_part_vis = TRUE;
|
|
}
|
|
}
|
|
else
|
|
*is_vis = TRUE;
|
|
}
|
|
else
|
|
if (i < lmp->first_fully_vis || i > lmp->last_fully_vis)
|
|
return 0;
|
|
for (column = 0; column < lmp->nbr_columns; column++)
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos + col_offset;
|
|
if (where.h >= temp && where.h < temp + column_data->pix_width)
|
|
{
|
|
if (((lmp->attrib & (LM_ATR_ENABLED | LM_ATR_VISIBLE)) == (LM_ATR_ENABLED | LM_ATR_VISIBLE))
|
|
&& (lmp->lm_column_data[column]->attrib & (LM_COL_ATR_ENABLED | LM_COL_ATR_SELECTABLE)))
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
*rowp = row;
|
|
*columnp = column;
|
|
if (is_hit)
|
|
*is_hit = TRUE;
|
|
cell_data = &lmp->cell_data[row][column];
|
|
if (cell_data->button)
|
|
{
|
|
RCT outer_rct;
|
|
PNT p;
|
|
|
|
lm_get_cell_rect(&outer_rct, lm, row, column, FALSE, FALSE);
|
|
xi_inflate_rect(&outer_rct, 1);
|
|
if (cell_data->button_on_left)
|
|
outer_rct.right = outer_rct.left + lmp->pix_row_spacing;
|
|
else
|
|
outer_rct.left = outer_rct.right - lmp->pix_row_spacing;
|
|
p = ep->v.mouse.where;
|
|
p.v = tmp_v;
|
|
if (xvt_rect_has_point(&outer_rct, p))
|
|
{
|
|
return 5;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
*rowp = row;
|
|
*columnp = column;
|
|
if (is_hit)
|
|
*is_hit = TRUE;
|
|
if (is_part_vis)
|
|
*is_part_vis = FALSE;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if (is_part_vis)
|
|
*is_part_vis = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_vsize_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
rowp: row, to be filled in
|
|
columnp: column, to be filled in
|
|
returns: FALSE if hit test did not fall on place where column could be vertically sized.
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN near
|
|
lm_vsize_hit_test(LM_DATA *lmp, EVENT *ep, int *rowp, int *columnp)
|
|
{
|
|
int i, n, v;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
|
|
if (lmp->lm_column_data[*columnp]->size_rows)
|
|
{
|
|
v = ep->v.mouse.where.v - lmp->rrr_offset - lmp->mlr.top;
|
|
for (i = 0,
|
|
pix_offsetsp = &lmp->pix_offsets[i],
|
|
pix_heightsp = &lmp->pix_heights[i];
|
|
i < lmp->nbr_realized_rows;
|
|
++i, ++pix_offsetsp, ++pix_heightsp)
|
|
{
|
|
n = *pix_offsetsp + *pix_heightsp;
|
|
if (v >= n - 3 && v <= n + 1)
|
|
{
|
|
*rowp = i;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_size_hit_test
|
|
lm: current lm
|
|
ep: xvt event
|
|
columnp: column, to be filled in
|
|
returns: FALSE if hit test did not fall on place where column could be sized.
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN near
|
|
lm_size_hit_test(LM lm, EVENT *ep, int *columnp)
|
|
{
|
|
int column, temp, col_offset;
|
|
LM_DATA *lmp = LMP(lm);
|
|
PNT where;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
where = ep->v.mouse.where;
|
|
if (where.h < 0)
|
|
return FALSE;
|
|
if (lmp->pixel_width && (where.h > (lmp->pixel_width + lmp->delta_x)
|
|
+ 2 * BORDER_WIDTH))
|
|
return FALSE;
|
|
if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top)
|
|
{
|
|
for (column = 0; column < lmp->nbr_columns; column++)
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
if (column >= lmp->fixed_columns && column < lmp->first_vis)
|
|
continue;
|
|
column_data = lmp->lm_column_data[column];
|
|
temp = column_data->x_pix_pos +
|
|
col_offset +
|
|
column_data->pix_width;
|
|
if (where.h >= temp &&
|
|
where.h < temp + col_offset * 2 + RULE_WIDTH_V)
|
|
{
|
|
*columnp = column;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_y
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
returns: Calculates and returns the Y pixel position of the rubber band line.
|
|
Used only when sizing rows.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calc_y(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
int row = lmp->row_being_sized;
|
|
int temp;
|
|
int min_height_in_pix = 4;
|
|
int v;
|
|
|
|
v = min(lmp->mlr.bottom, ep->v.mouse.where.v) - lmp->rrr_offset - lmp->mlr.top;
|
|
temp = lmp->pix_offsets[row] + min_height_in_pix;
|
|
temp = max(v, temp);
|
|
return temp;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_y
|
|
lmp: current lmp
|
|
y: draw a rubber line at position y
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_y(LM_DATA *lmp, int y)
|
|
{
|
|
#if XI_IS_NOT_CH
|
|
int left, right;
|
|
DRAW_CTOOLS new_ctools;
|
|
PNT pnt;
|
|
WINDOW win = lmp->win;
|
|
|
|
CTOS_IS_PM;
|
|
left = lmp->mlr.left;
|
|
right = lmp->mlr.right;
|
|
if (lmp->pixel_width)
|
|
right = left + lmp->pixel_width + BORDER_WIDTH;
|
|
xvt_app_get_default_ctools(&new_ctools);
|
|
xi_set_draw_ctools(win, &new_ctools);
|
|
xi_set_cpen(win, &rubber_cpen);
|
|
xi_set_draw_mode(win, M_XOR);
|
|
xi_set_clip(win, NULL);
|
|
pnt.h = left;
|
|
pnt.v = y;
|
|
lm_move_to(lmp, pnt, TRUE, FALSE);
|
|
pnt.h = right;
|
|
lm_draw_line(lmp, pnt, TRUE, FALSE);
|
|
CTOS_END;
|
|
#endif
|
|
NOREF(lmp);
|
|
NOREF(y);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_vsize_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_vsize_event(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
int y;
|
|
|
|
switch (ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
y = calc_y(lmp, ep);
|
|
lmp->last_y = y;
|
|
rubber_y(lmp, y);
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
y = calc_y(lmp, ep);
|
|
rubber_y(lmp, lmp->last_y);
|
|
lmp->last_y = y;
|
|
rubber_y(lmp, y);
|
|
break;
|
|
case E_MOUSE_UP:
|
|
{
|
|
int delta, row;
|
|
XI_OBJ row_obj;
|
|
|
|
row = lmp->row_being_sized;
|
|
y = calc_y(lmp, ep);
|
|
rubber_y(lmp, lmp->last_y);
|
|
delta = y - lmp->pix_offsets[row] + 1;
|
|
XI_MAKE_ROW(&row_obj, lmp->list_obj, row);
|
|
if (do_lm_cb((LM)lmp, LM_CB_ROW_SIZE, row, 0, NULL, NULL, delta))
|
|
{
|
|
xi_set_row_height(&row_obj, delta);
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
}
|
|
lm_make_vis(lmp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: send_txt_event
|
|
lm: current lm
|
|
txt: txt object
|
|
ep: xvt event
|
|
gaining_focus: if TRUE, the edit control is gaining focus as this function is called
|
|
returns: TRUE if the event was used
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN near
|
|
send_txt_event(LM lm, TXT_DATA *txt, EVENT *ep,
|
|
BOOLEAN gaining_focus, BOOLEAN send_to_txt)
|
|
{
|
|
BOOLEAN retval = FALSE;
|
|
int ch;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
if (! lmp->txt)
|
|
return FALSE;
|
|
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 )
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
retval = do_lm_cb( lm, LM_CB_CHAR, focus_row, focus_column, ep, NULL, 0);
|
|
/* retval = FALSE if event refused */
|
|
if (! retval)
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (send_to_txt)
|
|
{
|
|
retval = txt_event(txt, ep, gaining_focus);
|
|
|
|
/* check flags */
|
|
if (txt->flags & TXT_FLAG_TEXT)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lmp->itf_obj->v.itf->chg_flag = TRUE;
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
do_lm_cb(lm, LM_CB_CHANGE, focus_row, focus_column, NULL, NULL, 0);
|
|
}
|
|
/* reset flags */
|
|
txt->flags = 0;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_select_cells_hit_test
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
rowp: row number, to be filled in
|
|
columnp: column number, to be filled in
|
|
on_disabled: if TRUE, then the hit was on a disabled column
|
|
returns: TRUE if there was a hit
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
lm_select_cells_hit_test(LM_DATA *lmp, EVENT *ep, int *rowp,
|
|
int *columnp, BOOLEAN *on_disabled)
|
|
{
|
|
int delta_top, column, col_offset, last_vis, row, idx;
|
|
LM_COLUMN_DATA *column_data;
|
|
BOOLEAN retval;
|
|
BOOLEAN inv_v, inv_h; /* if set to TRUE, then invalid v or invalid h */
|
|
|
|
retval = TRUE;
|
|
if (columnp)
|
|
*columnp = 0;
|
|
if (on_disabled)
|
|
*on_disabled = FALSE;
|
|
inv_v = FALSE;
|
|
inv_h = FALSE;
|
|
last_vis = lmp->last_vis;
|
|
delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
|
|
|
|
/* If list has no columns */
|
|
if (lmp->nbr_columns <= 0) return FALSE;
|
|
/*
|
|
If mouse is above the top of the first row
|
|
*/
|
|
if (ep->v.mouse.where.v < lmp->pix_row1_top - RULE_WIDTH_V -
|
|
RULE_Y_OFFSET_TOP)
|
|
{
|
|
if (rowp)
|
|
*rowp = 0;
|
|
retval = FALSE;
|
|
inv_v = TRUE;
|
|
}
|
|
|
|
/*
|
|
if mouse is below the bottom of the list, or if the mouse is
|
|
below the bottom of the last row if there are fewer rows than
|
|
can be displayed in the list
|
|
*/
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
if (ep->v.mouse.where.v >= lmp->mlr.bottom ||
|
|
delta_top > lmp->pix_offsets[idx] + lmp->pix_heights[idx])
|
|
{
|
|
if (rowp)
|
|
*rowp = lmp->nbr_realized_rows;
|
|
retval = FALSE;
|
|
inv_v = TRUE;
|
|
}
|
|
|
|
/*
|
|
if mouse is to the right of the list, or if the mouse is to the right of the
|
|
rightmost column
|
|
*/
|
|
column_data = lmp->lm_column_data[lmp->nbr_columns - 1];
|
|
if ((ep->v.mouse.where.h >= (lmp->rct.right - lmp->rct.left)) ||
|
|
(ep->v.mouse.where.h >= (column_data->x_pix_pos + column_data->pix_width)))
|
|
{
|
|
if (columnp)
|
|
*columnp = last_vis + 1;
|
|
retval = FALSE;
|
|
inv_h = TRUE;
|
|
}
|
|
|
|
/*
|
|
if mouse has a valid y coordinate
|
|
*/
|
|
if (! inv_v)
|
|
{
|
|
|
|
if (rowp)
|
|
*rowp = 0;
|
|
retval = FALSE;
|
|
for (row = 0; row < lmp->nbr_realized_rows; ++row)
|
|
{
|
|
int pix_offset, pix_height;
|
|
|
|
pix_offset = lmp->pix_offsets[row];
|
|
pix_height = lmp->pix_heights[row];
|
|
if (delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= pix_offset + SELECT_CELLS_OFFSET)
|
|
{
|
|
if (rowp)
|
|
*rowp = row;
|
|
if (! inv_h)
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if (delta_top >= (pix_offset + pix_height) - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= (pix_offset + pix_height) + SELECT_CELLS_OFFSET)
|
|
{
|
|
if (rowp)
|
|
*rowp = row + 1;
|
|
if (! inv_h)
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if (delta_top >= pix_offset &&
|
|
delta_top <= pix_offset + pix_height)
|
|
{
|
|
if (rowp)
|
|
*rowp = row;
|
|
}
|
|
}
|
|
if (rowp && ! retval && *rowp < lmp->down_row)
|
|
++*rowp;
|
|
}
|
|
|
|
/*
|
|
if mouse has a valid x coordinate
|
|
*/
|
|
if (! inv_h)
|
|
{
|
|
column_data = lmp->lm_column_data[0];
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
if (((! (column_data->attrib & XI_ATR_ENABLED) || lmp->down_on_disabled) &&
|
|
(! (column_data->attrib & XI_ATR_SELECTABLE))) &&
|
|
((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
|
|
(ep->v.mouse.where.h < (column_data->x_pix_pos + column_data->pix_width))))
|
|
{
|
|
if (columnp)
|
|
*columnp = 0;
|
|
if (on_disabled)
|
|
*on_disabled = TRUE;
|
|
}
|
|
else if ((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
|
|
(ep->v.mouse.where.h < (column_data->x_pix_pos + col_offset)))
|
|
{
|
|
if (columnp)
|
|
*columnp = 0;
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN found = FALSE;
|
|
int last_col;
|
|
|
|
last_col = -1;
|
|
for (column = 0; column < lmp->nbr_columns; column++)
|
|
{
|
|
int temp;
|
|
|
|
column_data = lmp->lm_column_data[column];
|
|
if (((! (column_data->attrib & XI_ATR_ENABLED) || lmp->down_on_disabled) &&
|
|
(! (column_data->attrib & XI_ATR_SELECTABLE))) &&
|
|
((ep->v.mouse.where.h >= column_data->x_pix_pos) &&
|
|
(ep->v.mouse.where.h <
|
|
(column_data->x_pix_pos + column_data->pix_width))))
|
|
{
|
|
if (columnp)
|
|
*columnp = column;
|
|
if (on_disabled)
|
|
*on_disabled = TRUE;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
temp = column_data->x_pix_pos +
|
|
col_offset +
|
|
column_data->pix_width - SELECT_CELLS_OFFSET;
|
|
if (ep->v.mouse.where.h >= temp &&
|
|
ep->v.mouse.where.h < (temp + col_offset * 2
|
|
+ 2 * SELECT_CELLS_OFFSET
|
|
+ RULE_WIDTH_V))
|
|
{
|
|
if (columnp)
|
|
*columnp = column + 1;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
if (ep->v.mouse.where.h >= temp)
|
|
last_col = column;
|
|
}
|
|
if (! found)
|
|
{
|
|
retval = FALSE;
|
|
if (columnp)
|
|
{
|
|
if ((last_col + 1) < lmp->down_column)
|
|
*columnp = last_col + 2;
|
|
else
|
|
*columnp = last_col + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
If v is not invalid, and if h is not invalid, and if the column is valid, then
|
|
if the column is enabled, then the hit test must be within a range of the rules.
|
|
If the column is not enabled, then the hit test may be anywhere within the cell.
|
|
*/
|
|
if (! inv_v)
|
|
{
|
|
BOOLEAN enabled_col = FALSE;
|
|
|
|
if (columnp && ! inv_h)
|
|
{
|
|
if (*columnp >= lmp->nbr_columns)
|
|
enabled_col = FALSE;
|
|
else
|
|
enabled_col = (lmp->lm_column_data[*columnp]->attrib & XI_ATR_ENABLED &&
|
|
! lmp->down_on_disabled);
|
|
if (enabled_col)
|
|
{
|
|
delta_top = ep->v.mouse.where.v - lmp->mlr.top - lmp->rrr_offset;
|
|
retval = FALSE;
|
|
for (row = 0; row < lmp->nbr_realized_rows; ++row)
|
|
{
|
|
int pix_offset, pix_height;
|
|
|
|
pix_offset = lmp->pix_offsets[row];
|
|
pix_height = lmp->pix_heights[row];
|
|
if (delta_top >= pix_offset - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= pix_offset + SELECT_CELLS_OFFSET)
|
|
{
|
|
if (rowp)
|
|
*rowp = row;
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
if (delta_top >= (pix_offset + pix_height) - SELECT_CELLS_OFFSET - 2
|
|
&& delta_top <= (pix_offset + pix_height) + SELECT_CELLS_OFFSET)
|
|
{
|
|
if (rowp)
|
|
*rowp = row + 1;
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: invert_selection
|
|
lmp: current lmp
|
|
r: row
|
|
c: column
|
|
-------------------------------------------------------------------------*/
|
|
static void invert_selection(LM_DATA *lmp, int r, int c, BOOLEAN v_scrolled)
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lm_get_attrib((LM)lmp, LM_CELL, r, c, v_scrolled);
|
|
if (attrib & LM_CELL_ATR_SELECTED)
|
|
lm_set_attrib((LM)lmp, LM_CELL, r, c, v_scrolled,
|
|
attrib & ~LM_CELL_ATR_SELECTED, FALSE);
|
|
else
|
|
lm_set_attrib((LM)lmp, LM_CELL, r, c, v_scrolled,
|
|
attrib | LM_CELL_ATR_SELECTED, FALSE);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: in_rct
|
|
rct: rectangle
|
|
r: row
|
|
c: column
|
|
returns: TRUE if c and r are in rct
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
in_rct(RCT *rct, int r, int c)
|
|
{
|
|
if (c >= rct->left && c < rct->right && r >= rct->top && r < rct->bottom)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_select_cell_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_select_cell_event(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
int row, column;
|
|
|
|
switch (ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
if (! ep->v.mouse.shift)
|
|
{
|
|
int r, c;
|
|
|
|
for (r = 0; r < lmp->nbr_realized_rows; ++r)
|
|
for (c = 0; c < lmp->nbr_columns; ++c)
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lm_get_attrib((LM)lmp, LM_CELL, r, c, FALSE);
|
|
if (attrib & LM_CELL_ATR_SELECTED)
|
|
lm_set_attrib((LM)lmp, LM_CELL, r, c, FALSE,
|
|
attrib & ~LM_CELL_ATR_SELECTED, FALSE);
|
|
}
|
|
}
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
case E_MOUSE_UP:
|
|
{
|
|
int last_cur_row, last_cur_column, r, c, down_row, down_column;
|
|
RCT old_rct, new_rct, enclosing_rct;
|
|
|
|
lm_select_cells_hit_test(lmp, ep, &row, &column, NULL);
|
|
last_cur_row = lmp->cur_row;
|
|
last_cur_column = lmp->cur_column;
|
|
down_row = lmp->down_row;
|
|
down_column = lmp->down_column;
|
|
if (lmp->down_on_disabled)
|
|
{
|
|
if (ep->type == E_MOUSE_UP)
|
|
lmp->down_on_disabled = FALSE;
|
|
if (row >= lmp->down_row)
|
|
lmp->cur_row = row + 1;
|
|
else
|
|
lmp->cur_row = row;
|
|
if (column >= lmp->down_column)
|
|
lmp->cur_column = column + 1;
|
|
else
|
|
lmp->cur_column = column;
|
|
}
|
|
else
|
|
{
|
|
lmp->cur_row = row;
|
|
lmp->cur_column = column;
|
|
}
|
|
if (lmp->cur_row == last_cur_row && lmp->cur_column == last_cur_column &&
|
|
(ep->type == E_MOUSE_MOVE || ep->type == E_MOUSE_UP))
|
|
break;
|
|
old_rct.left = min(down_column, last_cur_column);
|
|
old_rct.right = max(down_column, last_cur_column);
|
|
old_rct.top = min(down_row, last_cur_row);
|
|
old_rct.bottom = max(down_row, last_cur_row);
|
|
new_rct.left = min(down_column, lmp->cur_column);
|
|
new_rct.right = max(down_column, lmp->cur_column);
|
|
new_rct.top = min(down_row, lmp->cur_row);
|
|
new_rct.bottom = max(down_row, lmp->cur_row);
|
|
enclosing_rct.top = min(old_rct.top, new_rct.top);
|
|
enclosing_rct.bottom = max(old_rct.bottom, new_rct.bottom);
|
|
enclosing_rct.left = min(old_rct.left, new_rct.left);
|
|
enclosing_rct.right = max(old_rct.right, new_rct.right);
|
|
for (c = enclosing_rct.left; c <= enclosing_rct.right; ++c)
|
|
{
|
|
for (r = enclosing_rct.top; r <= enclosing_rct.bottom; ++r)
|
|
{
|
|
if ((in_rct(&old_rct, r, c) &&
|
|
in_rct(&new_rct, r, c)) ||
|
|
(! in_rct(&old_rct, r, c) &&
|
|
! in_rct(&new_rct, r, c)))
|
|
continue;
|
|
if (r >= lmp->nbr_realized_rows || c >= lmp->nbr_columns ||
|
|
r < 0 || c < 0)
|
|
continue;
|
|
invert_selection(lmp, r, c, FALSE);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_cell_btn_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
oevp: xvt event, without virtual coordinate conversion
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_cell_btn_event(LM_DATA *lmp, EVENT *ep, EVENT *oevp)
|
|
{
|
|
RCT mr;
|
|
int hit_test_value, row, col;
|
|
|
|
mr = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
mr.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
|
|
hit_test_value = lm_hit_test((LM)lmp, ep, oevp, &row, &col, NULL, NULL, NULL);
|
|
|
|
if (hit_test_value)
|
|
{
|
|
switch (ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
lmp->down_in_btn = TRUE;
|
|
lmp->btn_down = TRUE;
|
|
lmp->btn_down_row = row;
|
|
lmp->btn_down_col = col;
|
|
xi_trap_mouse(lmp->win);
|
|
xi_set_trap_obj(lmp->list_obj);
|
|
redraw_cell_button(lmp, row, col, &mr, lmp->btn_down, FALSE);
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
{
|
|
BOOLEAN last = lmp->btn_down;
|
|
|
|
if (hit_test_value != 5 || row != lmp->btn_down_row || col != lmp->btn_down_col)
|
|
lmp->btn_down = FALSE;
|
|
else
|
|
lmp->btn_down = TRUE;
|
|
if (last != lmp->btn_down)
|
|
{
|
|
redraw_cell_button(lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
|
|
lmp->btn_down, FALSE);
|
|
last = lmp->btn_down;
|
|
}
|
|
break;
|
|
}
|
|
case E_MOUSE_UP:
|
|
if (lmp->btn_down)
|
|
redraw_cell_button(lmp, lmp->btn_down_row, lmp->btn_down_col, &mr,
|
|
FALSE, FALSE);
|
|
lmp->btn_down = FALSE;
|
|
lmp->down_in_btn = FALSE;
|
|
if (hit_test_value == 5 && row == lmp->btn_down_row && col == lmp->btn_down_col)
|
|
do_lm_cb((LM)lmp, LM_CB_CELL_BTN, row, col, ep, NULL, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_select_column
|
|
-------------------------------------------------------------------------*/
|
|
static int get_select_column( LM_DATA* lmp )
|
|
{
|
|
int col;
|
|
|
|
for ( col = 0; col < lmp->nbr_columns; col++ )
|
|
if ( LM_COL_ATTR( (LM)lmp, col ) & XI_ATR_SELECTABLE )
|
|
return col;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: select_row
|
|
-------------------------------------------------------------------------*/
|
|
void select_row( LM lm, int row, int column, BOOLEAN dbl_click )
|
|
{
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
XI_OBJ *old_itf;
|
|
int old_row;
|
|
LM_DATA* lmp = LMP(lm);
|
|
|
|
old_row = find_selection( lmp );
|
|
if ( old_row != row && old_row != -1 )
|
|
{
|
|
attrib = lm_get_attrib( lm, LM_ROW, old_row, 0, FALSE );
|
|
attrib &= ~LM_ROW_ATR_SELECTED;
|
|
lm_set_attrib( lm, LM_ROW, old_row, 0, FALSE, attrib, FALSE );
|
|
}
|
|
attrib = lm_get_attrib( lm, LM_ROW, row, 0, FALSE );
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)row;
|
|
if ( column == -1 )
|
|
column = (unsigned char)get_select_column( lmp );
|
|
lm_cb_data.column = column;
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = dbl_click;
|
|
lm_cb_data.v.select.shift = FALSE;
|
|
lm_cb_data.v.select.control = FALSE;
|
|
old_itf = lmp->itf_obj;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
if (xi_is_itf(old_itf))
|
|
if ( !lm_cb_data.v.select.refused && old_row != row )
|
|
lm_set_attrib( lm, LM_ROW, row, 0, FALSE, attrib, FALSE );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_event
|
|
lm: current lm
|
|
ep: xvt event
|
|
return: TRUE if event is consumed
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_event(LM lm, EVENT *ep)
|
|
{
|
|
int row, column;
|
|
LM_DATA *lmp = LMP(lm);
|
|
BOOLEAN send_event = FALSE;
|
|
int retval = 1;
|
|
EVENT oevt;
|
|
XI_OBJ *itf = lmp->itf_obj;
|
|
|
|
oevt = *ep;
|
|
switch(ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
case E_MOUSE_MOVE:
|
|
case E_MOUSE_UP:
|
|
{
|
|
RCT rct;
|
|
|
|
if (lmp->attrib & XI_ATR_VISIBLE)
|
|
{
|
|
/*
|
|
COORDINATE CONVERSION
|
|
changes horizontal coordinates - moves mouse to the right -
|
|
increases where.h if where.h is > lmp->vir_left, so that where.h
|
|
is in the correct virtual horizontal space - also makes where.h
|
|
be relative to the list, not the window.
|
|
*/
|
|
lm_get_rect(lm, LM_LIST, 0, &rct);
|
|
if (xvt_rect_has_point(&rct, ep->v.mouse.where) ||
|
|
lmp->selecting_cells || lmp->sizing_column || lmp->moving_column ||
|
|
lmp->down_in_btn || lmp->selecting_text || lmp->sizing_row)
|
|
{
|
|
if (ep->type == E_MOUSE_DOWN)
|
|
{
|
|
if (ep->v.mouse.where.h >= lmp->vir_left)
|
|
lmp->down_in_hscrolling = TRUE;
|
|
else
|
|
lmp->down_in_hscrolling = FALSE;
|
|
}
|
|
if (! lmp->sizing_column)
|
|
{
|
|
if ((lmp->pixel_width && (ep->v.mouse.where.h >= lmp->vir_left)))
|
|
{
|
|
ep->v.mouse.where.h += lmp->delta_x;
|
|
lmp->in_hscrolling = TRUE;
|
|
}
|
|
else
|
|
lmp->in_hscrolling = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (lmp->down_in_hscrolling)
|
|
ep->v.mouse.where.h += lmp->delta_x;
|
|
}
|
|
ep->v.mouse.where.h -= lmp->rct.left;
|
|
}
|
|
else
|
|
{
|
|
*ep = oevt;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ep = oevt;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
switch(ep->type)
|
|
{
|
|
case E_UPDATE:
|
|
/* the following code sends the event directly on to redraw_cell
|
|
if text is being scrolled in a text object. This speeds horizontal
|
|
scrolling. see also lm_text_scrolling.
|
|
*/
|
|
if (lmp->text_scrolling)
|
|
{
|
|
int row, col;
|
|
BOOLEAN is_vert_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &row, &col, &is_vert_scrolled);
|
|
draw_cell_range(lmp, row, row, col, col, FALSE);
|
|
if ( lmp->txt != NULL )
|
|
send_txt_event( lm, lmp->txt, &oevt, FALSE, TRUE );
|
|
lmp->text_scrolling = FALSE;
|
|
}
|
|
else
|
|
{
|
|
draw_lm(lm, TRUE);
|
|
if ( lmp->txt != NULL )
|
|
send_txt_event( lm, lmp->txt, &oevt, FALSE, TRUE );
|
|
}
|
|
retval = 0;
|
|
break;
|
|
case E_SIZE:
|
|
{
|
|
int new_height, new_width;
|
|
RCT hr, vr, cr;
|
|
XI_OBJ *list_obj;
|
|
|
|
if (lmp->resize_with_window)
|
|
{
|
|
RCT rct, wrct;
|
|
|
|
list_obj = lmp->list_obj;
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
lm_make_invis(lmp);
|
|
else
|
|
{
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
if (! xi_move_focus(list_obj->itf))
|
|
{
|
|
retval = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
xi_get_hsb_rect(list_obj, &hr);
|
|
xi_get_sb_rect(list_obj, &vr);
|
|
xvt_vobj_get_client_rect(lmp->win, &cr);
|
|
new_height = cr.bottom - lmp->pix_top;
|
|
new_width = cr.right - lmp->rct.left;
|
|
xi_set_list_size(list_obj, new_height, new_width);
|
|
if ((BOOLEAN)xi_get_pref( XI_PREF_LIMIT_MIN_WIN_SIZE ))
|
|
{
|
|
xi_get_rect(list_obj, &rct);
|
|
if (abs(rct.bottom - cr.bottom) > 4 ||
|
|
abs(rct.right - cr.right) > 4)
|
|
{
|
|
wrct = cr;
|
|
wrct.bottom = max(rct.bottom, cr.bottom);
|
|
wrct.right = max(rct.right, cr.right);
|
|
if ( wrct.bottom != cr.bottom || wrct.right != cr.right )
|
|
{
|
|
xvt_vobj_translate_points(lmp->win, xvt_vobj_get_parent(lmp->win), (PNT *)&wrct, 2);
|
|
xvt_vobj_move(lmp->win, &wrct);
|
|
}
|
|
}
|
|
}
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
lm_make_vis(lmp);
|
|
}
|
|
retval = 0;
|
|
break;
|
|
}
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
{
|
|
RCT rct;
|
|
int last_vis, hit_test_value;
|
|
BOOLEAN is_vis, is_hit, is_part_vis;
|
|
|
|
if (ep->v.mouse.button > 0)
|
|
break;
|
|
|
|
hit_test_value = lm_hit_test(lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis);
|
|
if (is_part_vis && ep->type != E_MOUSE_DBL)
|
|
{
|
|
EVENT lep;
|
|
LM_SCROLL_ARG lm_scroll_arg;
|
|
static BOOLEAN in_here = FALSE;
|
|
|
|
if (in_here)
|
|
return FALSE;
|
|
MEMCLEAR(lm_scroll_arg);
|
|
lm_scroll_arg.lm = lm;
|
|
lm_scroll_arg.nbr_lines = 1;
|
|
/*
|
|
lm_scroll_arg.percent = 0;
|
|
lm_scroll_arg.same_cell = 0;
|
|
lm_scroll_arg.rec = 0L;
|
|
lm_scroll_arg.have_rec = FALSE;
|
|
lm_scroll_arg.color = 0L;
|
|
lm_scroll_arg.attrib = 0L;
|
|
lm_scroll_arg.row_height = 0;
|
|
lm_scroll_arg.rec_at_top = FALSE;
|
|
*/
|
|
lm_scroll(&lm_scroll_arg);
|
|
lep = oevt;
|
|
lep.v.mouse.where.v -= lm_scroll_arg.pixels_scrolled;
|
|
in_here = TRUE;
|
|
lm_event(lm, &lep);
|
|
in_here = FALSE;
|
|
return TRUE;
|
|
}
|
|
if (is_hit)
|
|
{
|
|
if (lm_vsize_hit_test(lmp, ep, &row, &column))
|
|
{
|
|
XI_OBJ *itf, *list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
lm_make_invis(lmp);
|
|
xi_set_trap_obj(list);
|
|
lmp->row_being_sized = row;
|
|
lmp->sizing_row = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_vsize_event(lmp, ep);
|
|
}
|
|
else
|
|
{
|
|
if (list && xi_move_focus(itf))
|
|
{
|
|
xi_set_trap_obj(list);
|
|
lmp->row_being_sized = row;
|
|
lmp->sizing_row = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_vsize_event(lmp, ep);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (lmp->select_cells)
|
|
{
|
|
int row, column;
|
|
BOOLEAN on_disabled;
|
|
|
|
if (lm_select_cells_hit_test(lmp, ep, &row, &column, &on_disabled))
|
|
{
|
|
XI_OBJ *list;
|
|
|
|
list = lmp->list_obj;
|
|
xi_set_trap_obj(list);
|
|
lmp->selecting_cells = TRUE;
|
|
lmp->down_row = row;
|
|
lmp->cur_row = row;
|
|
lmp->down_column = column;
|
|
lmp->cur_column = column;
|
|
lmp->down_on_disabled = on_disabled;
|
|
lm_select_cell_event(lmp, ep);
|
|
xi_trap_mouse(lmp->win);
|
|
if (on_disabled)
|
|
{
|
|
invert_selection(lmp, row, column, FALSE );
|
|
lmp->cur_row = row + 1;
|
|
lmp->cur_column = column + 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* check for cell button hit */
|
|
if (hit_test_value == 5)
|
|
if (LIST_IS_ENABLED(lm))
|
|
lm_cell_btn_event(lmp, ep, &oevt);
|
|
|
|
/* check for focus acquisition */
|
|
if (hit_test_value == 1)
|
|
{
|
|
if (row == -1)
|
|
{
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
COLUMN_IS_SELECTABLE(lm, column) &&
|
|
(ep->type == E_MOUSE_DBL ||
|
|
(ep->type == E_MOUSE_DOWN && !
|
|
lmp->movable_columns)
|
|
))
|
|
{
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
attrib = lm_get_attrib(lm, LM_COLUMN, column, 0, FALSE);
|
|
if (ep->type == E_MOUSE_DBL && !lmp->movable_columns)
|
|
attrib |= LM_COL_ATR_SELECTED;
|
|
else
|
|
{
|
|
if (attrib & LM_COL_ATR_SELECTED)
|
|
attrib &= ~LM_COL_ATR_SELECTED;
|
|
else
|
|
attrib |= LM_COL_ATR_SELECTED;
|
|
}
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)255;
|
|
lm_cb_data.column = (unsigned char)column;
|
|
lm_cb_data.v.select.selected =
|
|
((attrib & LM_COL_ATR_SELECTED) != 0);
|
|
lm_cb_data.v.select.dbl_click =
|
|
(ep->type == E_MOUSE_DBL);
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
if (! lm_cb_data.v.select.refused)
|
|
lm_set_attrib( lm, LM_COLUMN, column, 0, FALSE, attrib,
|
|
FALSE);
|
|
}
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
(ep->type == E_MOUSE_DOWN ||
|
|
(ep->type == E_MOUSE_DBL &&
|
|
! COLUMN_IS_SELECTABLE(lm, column))) &&
|
|
lmp->movable_columns)
|
|
{
|
|
XI_OBJ *itf, *list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
lm_make_invis(lmp);
|
|
xi_set_trap_obj(list);
|
|
lmp->column_being_moved = column;
|
|
lmp->moving_column = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_move_event(lmp, ep);
|
|
}
|
|
else
|
|
{
|
|
if (list && xi_move_focus(itf))
|
|
{
|
|
xi_set_trap_obj(list);
|
|
lmp->column_being_moved = column;
|
|
lmp->moving_column = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_move_event(lmp, ep);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (CELL_IS_SELECTABLE(lm, row, column))
|
|
{
|
|
if ( lmp->single_select )
|
|
select_row( lm, row, column, (BOOLEAN)(ep->type == E_MOUSE_DBL) );
|
|
else
|
|
{
|
|
unsigned long attrib;
|
|
LM_CB_DATA lm_cb_data;
|
|
XI_OBJ *old_itf;
|
|
|
|
attrib = lm_get_attrib(lm, LM_ROW, row, 0, FALSE);
|
|
if (ep->type == E_MOUSE_DBL)
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
else
|
|
{
|
|
if (attrib & LM_ROW_ATR_SELECTED)
|
|
attrib &= ~LM_ROW_ATR_SELECTED;
|
|
else
|
|
attrib |= LM_ROW_ATR_SELECTED;
|
|
}
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)row;
|
|
lm_cb_data.column = (unsigned char)column;
|
|
lm_cb_data.v.select.selected =
|
|
((attrib & LM_COL_ATR_SELECTED) != 0);
|
|
lm_cb_data.v.select.dbl_click = (ep->type == E_MOUSE_DBL);
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
old_itf = lmp->itf_obj;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
if (xi_is_itf(old_itf))
|
|
if (! lm_cb_data.v.select.refused)
|
|
lm_set_attrib(lm, LM_ROW, row, 0, FALSE, attrib, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN gaining_focus = FALSE;
|
|
|
|
if (! is_vis)
|
|
break;
|
|
|
|
if (! lmp->cell_data[row][column].icon_rid)
|
|
{
|
|
/* set this flag here, not later! */
|
|
lmp->have_mouse = TRUE;
|
|
|
|
if (! lm_list_has_focus(lmp))
|
|
{
|
|
send_event = do_lm_cb(lm, LM_CB_FOCUS, row, column,
|
|
NULL, NULL, 0);
|
|
gaining_focus = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (! lm_cell_has_focus(lmp, row, column, FALSE))
|
|
{
|
|
send_event = do_lm_cb(lm, LM_CB_FOCUS, row, column, NULL, NULL, 0);
|
|
/* send_event = FALSE if refused */
|
|
|
|
gaining_focus = send_event;
|
|
}
|
|
else
|
|
send_event = TRUE;
|
|
}
|
|
if (send_event)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
if ( ( lmp->lm_column_data[focus_column]->attrib
|
|
& LM_COL_ATR_AUTOSELECT )
|
|
&& xi_get_pref(XI_PREF_AUTOSEL_ON_MOUSE)
|
|
&& gaining_focus)
|
|
;
|
|
else
|
|
{
|
|
xi_trap_mouse(lmp->win);
|
|
lmp->selecting_text = TRUE;
|
|
send_txt_event( lm, lmp->txt, &oevt, gaining_focus, TRUE);
|
|
}
|
|
}
|
|
else
|
|
lmp->have_mouse = FALSE;
|
|
if (ep->type == E_MOUSE_DBL)
|
|
do_lm_cb(lm, LM_CB_DBL, row, column, NULL, NULL, 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
lmp->sizable_columns &&
|
|
lm_size_hit_test(lm, ep, &column))
|
|
{
|
|
XI_OBJ *itf, *list;
|
|
|
|
itf = lmp->itf_obj;
|
|
list = lmp->list_obj;
|
|
if (list && xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
lm_make_invis(lmp);
|
|
xi_set_trap_obj(list);
|
|
lmp->column_being_sized = column;
|
|
lmp->sizing_column = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_size_event(lmp, ep);
|
|
}
|
|
else
|
|
{
|
|
if (list && xi_move_focus(itf))
|
|
{
|
|
xi_set_trap_obj(list);
|
|
lmp->column_being_sized = column;
|
|
lmp->sizing_column = TRUE;
|
|
xi_trap_mouse(lmp->win);
|
|
lm_size_event(lmp, ep);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
retval = 0;
|
|
}
|
|
/*
|
|
The following code implements the behavor where if the user clicks on a partially
|
|
visible column, then the list scrolls to the left.
|
|
*/
|
|
|
|
if (xi_is_itf( itf ))
|
|
{
|
|
if (! (lmp->attrib & XI_ATR_VISIBLE))
|
|
break;
|
|
if (lmp->pixel_width)
|
|
{
|
|
last_vis = lmp->last_vis;
|
|
if (last_vis >= lmp->fixed_columns && last_vis < lmp->nbr_columns - 1)
|
|
{
|
|
lm_get_rect(lm, LM_COLUMN, last_vis + 1, &rct);
|
|
rct.left += (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
rct.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
if (xvt_rect_has_point(&rct, oevt.v.mouse.where))
|
|
{
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
lm_make_invis(lmp);
|
|
lm_local_hscroll(lm, 1);
|
|
lm_make_vis(lmp);
|
|
}
|
|
else
|
|
{
|
|
if (xi_move_focus(lmp->itf_obj))
|
|
{
|
|
lm_local_hscroll(lm, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case E_MOUSE_UP:
|
|
if (lmp->selecting_cells)
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_select_cell_event(lmp, ep);
|
|
xi_release_mouse();
|
|
lmp->selecting_cells = FALSE;
|
|
lmp->down_row = 0;
|
|
lmp->down_column = 0;
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)255;
|
|
lm_cb_data.column = (unsigned char)255;
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = FALSE;
|
|
lm_cb_data.v.select.shift = ep->v.mouse.shift;
|
|
lm_cb_data.v.select.control = ep->v.mouse.control;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
}
|
|
if (lmp->sizing_column)
|
|
{
|
|
lm_size_event(lmp, ep);
|
|
xi_release_mouse();
|
|
lmp->sizing_column = FALSE;
|
|
lmp->column_being_sized = 0;
|
|
break;
|
|
}
|
|
if (lmp->sizing_row)
|
|
{
|
|
lm_vsize_event(lmp, ep);
|
|
xi_release_mouse();
|
|
lmp->sizing_row = FALSE;
|
|
lmp->row_being_sized = 0;
|
|
break;
|
|
}
|
|
if (lmp->moving_column)
|
|
{
|
|
lm_move_event(lmp, ep);
|
|
xi_release_mouse();
|
|
lmp->moving_column = FALSE;
|
|
lmp->column_being_moved = 0;
|
|
break;
|
|
}
|
|
if (lmp->down_in_btn)
|
|
{
|
|
lm_cell_btn_event(lmp, ep, &oevt);
|
|
xi_release_mouse();
|
|
lmp->down_in_btn = FALSE;
|
|
lmp->btn_down = FALSE;
|
|
break;
|
|
}
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
send_txt_event(lm, lmp->txt, &oevt, FALSE, TRUE);
|
|
lmp->selecting_text = FALSE;
|
|
xi_release_mouse();
|
|
lmp->have_mouse = FALSE;
|
|
break;
|
|
}
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
{
|
|
BOOLEAN is_vis, is_hit, is_part_vis;
|
|
|
|
if (! (lmp->attrib & XI_ATR_VISIBLE))
|
|
{
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
if (lmp->selecting_cells)
|
|
{
|
|
lm_select_cell_event(lmp, ep);
|
|
break;
|
|
}
|
|
if (lmp->sizing_column)
|
|
{
|
|
lm_size_event(lmp, ep);
|
|
break;
|
|
}
|
|
if (lmp->sizing_row)
|
|
{
|
|
lm_vsize_event(lmp, ep);
|
|
break;
|
|
}
|
|
if (lmp->moving_column)
|
|
{
|
|
lm_move_event(lmp, ep);
|
|
break;
|
|
}
|
|
if (lmp->down_in_btn)
|
|
{
|
|
lm_cell_btn_event(lmp, ep, &oevt);
|
|
break;
|
|
}
|
|
if (lm_list_has_focus(lmp))
|
|
send_txt_event(lm, lmp->txt, &oevt, FALSE, TRUE);
|
|
retval = lm_hit_test(lm, ep, &oevt, &row, &column, &is_vis, &is_hit, &is_part_vis);
|
|
if (is_part_vis)
|
|
{
|
|
unsigned long attrib;
|
|
|
|
attrib = lmp->lm_column_data[column]->attrib;
|
|
if (attrib & XI_ATR_SELECTABLE)
|
|
return 0;
|
|
if (! retval)
|
|
retval = 1;
|
|
return retval;
|
|
}
|
|
if (is_hit)
|
|
{
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
lm_vsize_hit_test(lmp, ep, &row, &column))
|
|
{
|
|
*ep = oevt;
|
|
return 6;
|
|
}
|
|
}
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
lmp->select_cells &&
|
|
lm_select_cells_hit_test(lmp, ep, NULL, NULL, NULL))
|
|
{
|
|
*ep = oevt;
|
|
return 4;
|
|
}
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
lmp->sizable_columns &&
|
|
lm_size_hit_test(lm, ep, &column))
|
|
{
|
|
*ep = oevt;
|
|
return 2;
|
|
}
|
|
if (retval)
|
|
{
|
|
if (! is_vis)
|
|
{
|
|
*ep = oevt;
|
|
return 5;
|
|
}
|
|
if (CELL_IS_SELECTABLE(lm, row, column))
|
|
retval = 5;
|
|
if (row == -1)
|
|
retval = 5;
|
|
if (row >= 0 && lmp->cell_data[row][column].icon_rid)
|
|
retval = 5;
|
|
if (LIST_IS_ENABLED(lm) &&
|
|
lmp->movable_columns &&
|
|
lm_hit_test(lm, ep, &oevt, &row, &column, NULL, NULL, NULL))
|
|
if (row == -1)
|
|
retval = 3;
|
|
}
|
|
break;
|
|
}
|
|
case E_CHAR:
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
if (lmp->focus_rec)
|
|
{
|
|
LM_SCROLL_ARG lm_scroll_arg;
|
|
int row;
|
|
BOOLEAN found = FALSE;
|
|
|
|
for (row = 0; row < lmp->nbr_realized_rows; ++row)
|
|
{
|
|
if (lmp->focus_rec == lmp->recs[row])
|
|
{
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (! found)
|
|
{
|
|
MEMCLEAR(lm_scroll_arg);
|
|
lm_scroll_arg.lm = lm;
|
|
/*
|
|
lm_scroll_arg.nbr_lines = 0;
|
|
lm_scroll_arg.percent = 0;
|
|
lm_scroll_arg.same_cell = 0;
|
|
*/
|
|
lm_scroll_arg.rec = lmp->focus_rec;
|
|
lm_scroll_arg.have_rec = TRUE;
|
|
lm_scroll_arg.color = lmp->focus_rec_color;
|
|
lm_scroll_arg.attrib = lmp->focus_rec_attrib;
|
|
lm_scroll_arg.row_height = lmp->focus_rec_height;
|
|
lm_scroll_arg.rec_at_top = lmp->focus_rec_is_above;
|
|
lm_scroll(&lm_scroll_arg);
|
|
|
|
lmp->focus_rec = 0L;
|
|
xvt_dwin_update(lmp->win);
|
|
}
|
|
}
|
|
if (lmp->txt_is_invisible)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
if (focus_column >= lmp->fixed_columns)
|
|
{
|
|
if (focus_column < lmp->first_vis)
|
|
{
|
|
lm_local_hscroll((LM)lmp, focus_column - lmp->first_vis);
|
|
}
|
|
else if (focus_column > lmp->last_vis)
|
|
{
|
|
int first_col, c;
|
|
|
|
c = focus_column;
|
|
c++;
|
|
c = min(c, lmp->nbr_columns);
|
|
first_col = lm_get_left_most_far_right_col(lmp, c);
|
|
lm_local_hscroll((LM)lmp, first_col - lmp->first_vis);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
long button_key;
|
|
BOOLEAN shift, control;
|
|
int focus_row, focus_column;
|
|
BOOLEAN h_scrolled;
|
|
|
|
button_key = xi_get_pref(XI_PREF_BUTTON_KEY);
|
|
shift = (BOOLEAN)((button_key & XI_MOD_SHIFT) != 0);
|
|
control = (BOOLEAN)((button_key & XI_MOD_CONTROL) != 0);
|
|
button_key &= 0xffffffL;
|
|
if ( button_key == ep->v.chr.ch &&
|
|
shift == ep->v.chr.shift &&
|
|
control == ep->v.chr.control )
|
|
{
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &h_scrolled );
|
|
do_lm_cb((LM)lmp, LM_CB_CELL_BTN, focus_row, focus_column, ep, NULL, 0);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( lmp->single_select )
|
|
{
|
|
switch ( ep->v.chr.ch )
|
|
{
|
|
case K_UP:
|
|
{
|
|
int cur_row = find_selection( lmp );
|
|
if ( cur_row == -1 )
|
|
cur_row = 0;
|
|
else
|
|
{
|
|
if ( cur_row == 0 )
|
|
xi_scroll( lmp->list_obj, -1 );
|
|
else
|
|
cur_row--;
|
|
}
|
|
select_row( lm, cur_row, -1, FALSE );
|
|
break;
|
|
}
|
|
case K_DOWN:
|
|
{
|
|
int cur_row = find_selection( lmp );
|
|
if ( cur_row == -1 )
|
|
cur_row = 0;
|
|
else
|
|
{
|
|
if ( cur_row == lmp->last_fully_vis )
|
|
xi_scroll( lmp->list_obj, 1 );
|
|
else
|
|
cur_row++;
|
|
}
|
|
select_row( lm, cur_row, -1, FALSE );
|
|
break;
|
|
}
|
|
case K_PREV:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_PGUP );
|
|
select_row( lm, lmp->last_fully_vis, -1, FALSE );
|
|
break;
|
|
case K_NEXT:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_PGDOWN );
|
|
select_row( lm, 0, -1, FALSE );
|
|
break;
|
|
case K_HOME:
|
|
case K_LHOME:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_FIRST );
|
|
select_row( lm, 0, -1, FALSE );
|
|
break;
|
|
case K_END:
|
|
case K_LEND:
|
|
xi_scroll( lmp->list_obj, XI_SCROLL_LAST );
|
|
select_row( lm, lmp->last_fully_vis, -1, FALSE );
|
|
break;
|
|
case '\r':
|
|
case ' ':
|
|
row = find_selection( lmp );
|
|
select_row( lm, row, -1, TRUE );
|
|
#if 0
|
|
if ( row != -1 )
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = LM_CB_SELECT;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.row = (unsigned char)row;
|
|
lm_cb_data.column = (unsigned char)get_select_column( lmp );
|
|
lm_cb_data.v.select.selected = TRUE;
|
|
lm_cb_data.v.select.dbl_click = TRUE;
|
|
lm_cb_data.v.select.shift = FALSE;
|
|
lm_cb_data.v.select.control = FALSE;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
if ( !lmp->sizing_row )
|
|
{
|
|
BOOLEAN nav_ret = FALSE;
|
|
|
|
if (! lmp->itf_obj->v.itf->pasting)
|
|
nav_ret = (BOOLEAN)navigate_char_event(lm, ep);
|
|
retval = send_txt_event(lm, lmp->txt, ep, FALSE, (BOOLEAN)(!nav_ret));
|
|
}
|
|
break;
|
|
case E_KILL_WINDOW:
|
|
/* xi_tree_free((char *)lm); */ /* unneeded */
|
|
retval = 0;
|
|
break;
|
|
case E_TIMER:
|
|
case E_COMMAND:
|
|
if (lmp->txt)
|
|
retval = send_txt_event(lm, lmp->txt, ep, FALSE, TRUE);
|
|
break;
|
|
}
|
|
*ep = oevt;
|
|
return(retval);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_font
|
|
lm: current lm
|
|
part: must be LM_COLUMN, or LM_CELL
|
|
idx: column number
|
|
idx2: if LM_CELL, row number
|
|
font: font to set
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_font(LM lm, LM_PART part, int idx, int idx2, FONT_OBJ *font)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
switch (part)
|
|
{
|
|
case LM_COLUMN:
|
|
{
|
|
LM_COLUMN_DATA *lmcd;
|
|
RCT rct;
|
|
|
|
lmcd = lmp->lm_column_data[idx];
|
|
if (font)
|
|
{
|
|
if (! lmcd->font)
|
|
lmcd->font = (FONT_OBJ *)xi_tree_malloc(
|
|
sizeof(FONT_OBJ), lmp);
|
|
*lmcd->font = xi_create_copy_font_id(lmp->itf_obj, *font, 0);
|
|
}
|
|
lm_get_rect(lm, LM_COLUMN, idx, &rct);
|
|
lm_invalidate_rect(lmp, &rct, TRUE);
|
|
break;
|
|
}
|
|
case LM_CELL:
|
|
{
|
|
cell_data = &lmp->cell_data[idx][idx2];
|
|
if (font)
|
|
{
|
|
XVT_FNTID old_font_id;
|
|
if (! cell_data->font)
|
|
cell_data->font = (FONT_OBJ *)xi_tree_malloc(
|
|
sizeof(FONT_OBJ), lmp);
|
|
old_font_id = *cell_data->font;
|
|
*cell_data->font = xi_create_copy_font_id(lmp->itf_obj,
|
|
*font, old_font_id);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* LM drawing functions */
|
|
|
|
#if 0
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_clip
|
|
lmp: current lmp
|
|
rctp: clipping rectangle
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
lm_set_clip(LM_DATA *lmp, RCT *rctp)
|
|
{
|
|
RCT r;
|
|
|
|
r = *rctp;
|
|
r.left += lmp->rct.left;
|
|
r.right += lmp->rct.left;
|
|
|
|
lm_adj_h(lmp, &r.left);
|
|
lm_adj_h(lmp, &r.right);
|
|
|
|
xi_set_clip(lmp->win, &r);
|
|
}
|
|
#endif
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_draw_text
|
|
lmp: current lmp
|
|
h: h position
|
|
v: v position
|
|
s: string
|
|
len: length of string
|
|
-------------------------------------------------------------------------*/
|
|
#if XI_IS_CH
|
|
static void
|
|
lm_draw_text(LM_DATA *lmp, int h, int v, char *s, int len)
|
|
{
|
|
short sh;
|
|
|
|
sh = h;
|
|
sh += lmp->rct.left;
|
|
if (lm_adj_h(lmp, &sh))
|
|
{
|
|
lm_adj_v(lmp, v);
|
|
xi_draw_text(lmp->win, sh, v, s, len);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
static void
|
|
add_seg(void *parent, LM_CELL_DATA *cell_data, int seg_starting_pos)
|
|
{
|
|
++cell_data->nbr_lines;
|
|
if (cell_data->line_breaks)
|
|
cell_data->line_breaks = (int*)xi_tree_realloc(cell_data->line_breaks,
|
|
sizeof(int) * cell_data->nbr_lines);
|
|
else
|
|
cell_data->line_breaks = (int*)xi_tree_malloc(
|
|
sizeof(int) * cell_data->nbr_lines, parent);
|
|
cell_data->line_breaks[cell_data->nbr_lines - 1] = seg_starting_pos;
|
|
}
|
|
|
|
|
|
#define is_word_char(ch) (ch != ' ' && ch != '\n')
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
lmp: current lmp
|
|
row:
|
|
col:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_wrap_text(LM_DATA *lmp, int row, int col, BOOLEAN set_font)
|
|
{
|
|
LM_CELL_DATA *cell_data;
|
|
LM_COLUMN_DATA *column_data;
|
|
int len, pix_width;
|
|
char *cell_text;
|
|
FONT_OBJ *font;
|
|
int leading, ascent, descent, char_width;
|
|
int cur_seg, cur_seg_starting_pos, avg_line_len, seg_len;
|
|
|
|
cell_data = &lmp->cell_data[row][col];
|
|
column_data = lmp->lm_column_data[col];
|
|
cell_text = lmp->buffer[row] + lmp->lm_column_data[col]->text_offset;
|
|
pix_width = column_data->pix_width - lm_get_col_spacing();
|
|
if (cell_data->button)
|
|
{
|
|
pix_width -= lmp->pix_row_spacing;
|
|
}
|
|
if (cell_data->string)
|
|
if (cell_data->pix_width == pix_width &&
|
|
strcmp(cell_data->string, cell_text) == 0)
|
|
return;
|
|
if (cell_data->font)
|
|
font = cell_data->font;
|
|
else
|
|
font = lmp->font;
|
|
if (set_font)
|
|
xi_set_xvt_font(lmp->win, font, FALSE);
|
|
len = strlen(cell_text) + 1;
|
|
if (cell_data->string)
|
|
cell_data->string = (char*)xi_tree_realloc(cell_data->string, len);
|
|
else
|
|
cell_data->string = (char*)xi_tree_malloc(len, lmp);
|
|
cell_data->pix_width = pix_width;
|
|
strcpy(cell_data->string, cell_text);
|
|
if (cell_data->line_breaks)
|
|
{
|
|
xi_tree_free(cell_data->line_breaks);
|
|
cell_data->line_breaks = NULL;
|
|
}
|
|
cell_data->nbr_lines = 0;
|
|
xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
|
|
cell_data->font_height = ascent + descent + leading;
|
|
avg_line_len = pix_width / char_width;
|
|
cur_seg_starting_pos = 0;
|
|
cur_seg = 0;
|
|
|
|
/* find all segments in cell_text */
|
|
while (TRUE)
|
|
{
|
|
int this_seg_len, possible_word_break, cur_seg_len, word_break, cnt;
|
|
BOOLEAN continue_loop;
|
|
|
|
cur_seg_len = strlen(&cell_text[cur_seg_starting_pos]);
|
|
|
|
/* if there is a new line in the text, will the line fit in the wrap space */
|
|
while (TRUE)
|
|
{
|
|
continue_loop = FALSE;
|
|
for (cnt = 0; cnt < cur_seg_len; ++cnt)
|
|
{
|
|
if (cell_text[cur_seg_starting_pos + cnt] == '\n')
|
|
{
|
|
seg_len = xi_xvt_get_text_width(lmp->win,
|
|
&cell_text[cur_seg_starting_pos], cnt);
|
|
if (seg_len <= pix_width)
|
|
{
|
|
add_seg(lmp, cell_data, cur_seg_starting_pos);
|
|
cur_seg_starting_pos += cnt + 1;
|
|
cur_seg_len = strlen(&cell_text[cur_seg_starting_pos]);
|
|
continue_loop = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue_loop = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (! continue_loop)
|
|
break;
|
|
}
|
|
|
|
this_seg_len = min(avg_line_len, cur_seg_len);
|
|
|
|
/* find character that is beyond pix_width */
|
|
while (TRUE)
|
|
{
|
|
seg_len = xi_xvt_get_text_width(lmp->win,
|
|
&cell_text[cur_seg_starting_pos], this_seg_len);
|
|
if (seg_len > pix_width)
|
|
break;
|
|
if (seg_len <= pix_width &&
|
|
cell_text[cur_seg_starting_pos + this_seg_len] == '\0')
|
|
{
|
|
/* this is the last segment of the text */
|
|
add_seg(lmp, cell_data, cur_seg_starting_pos);
|
|
return;
|
|
}
|
|
++this_seg_len;
|
|
}
|
|
|
|
/* add the first segment */
|
|
add_seg(lmp, cell_data, cur_seg_starting_pos);
|
|
|
|
/* find character that is just below pix_width */
|
|
while (TRUE)
|
|
{
|
|
--this_seg_len;
|
|
seg_len = xi_xvt_get_text_width(lmp->win,
|
|
&cell_text[cur_seg_starting_pos], this_seg_len);
|
|
if (seg_len <= pix_width)
|
|
break;
|
|
}
|
|
|
|
/* find possible word break */
|
|
possible_word_break = this_seg_len + 1;
|
|
while (possible_word_break > 0)
|
|
{
|
|
if (! is_word_char(
|
|
cell_text[cur_seg_starting_pos + possible_word_break]))
|
|
break;
|
|
--possible_word_break;
|
|
}
|
|
|
|
/* if there is no possible word break, then break at this_seg_len */
|
|
if (possible_word_break == 0)
|
|
word_break = this_seg_len;
|
|
else
|
|
word_break = possible_word_break;
|
|
|
|
/* move forward so that word break is on a word */
|
|
while (! is_word_char(cell_text[cur_seg_starting_pos + word_break]))
|
|
++word_break;
|
|
|
|
++cur_seg;
|
|
cur_seg_starting_pos += word_break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Make it so a row can have the focus.
|
|
Tab will move focus to a cell in the row, if there is a cell in the row
|
|
that can take focus.
|
|
If XI_ATR_SELECTABLE is set for any columns, space will select the
|
|
row.
|
|
Up arrow and down arrow work. If the focus is on a cell, the focus stays
|
|
on a cell. If the focus is on a row, the focus stays on a row.
|
|
Page up and down should work.
|
|
If the focus is on the last editable cell, and tab_wrap is set, then the
|
|
focus moves to the next row.
|
|
If the focus is on the last editable cell, and tab_wrap is not set, then
|
|
the focus move to the current row.
|
|
Have an option on a list by list basis, enter selects if a row has the
|
|
focus. Enter will act like a double click selection.
|
|
If the row focus option is set, put up the other hand cursor.
|
|
|
|
if spreadsheet is resized, then limit size change to max_lines in lmp
|
|
|
|
have option to have scroll bars on multi-line edit controls in list
|
|
possibly revisit how text is stored in cells - may want indefinite buffer
|
|
size for a column.
|
|
when entering text in a cell, continually evaluate the correct height of
|
|
the cell. The function to recalc number of rows and break points should
|
|
compare line by line, until there is a difference, then do detailed
|
|
comparison after the difference.
|
|
it should be possible to scroll the list backwards to gain more room above
|
|
if the cell is at the bottom of the list
|
|
if the cell is already the maximum possible height, then not necessary to
|
|
do any more comparisons
|
|
limit text edit to buffer size
|
|
make sure that the clipboard works
|
|
|
|
TODO in the future
|
|
------------------
|
|
disabled rows should use colors
|
|
need option for lm to keep n records - caching
|
|
make disabled rows really work
|
|
if height is 0, make the list height be the same as the window height
|
|
expose lm drawing functions
|
|
xi_set_icon for buttons
|
|
make an option so that when the user tabs to an edit control that already contains text, the
|
|
insertion point is set to the right of the text.
|
|
settable background color for text on a 3d radio button or check box, (tab buttons also)
|
|
make function xi_is_nav_char
|
|
make readonly cells
|
|
need colors for static text
|
|
want ability on XVT/CH to have single character fields. Eliminate the [ and ].
|
|
*/
|
|
|