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
4914 lines
144 KiB
C
Executable File
4914 lines
144 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"
|
|
|
|
#define REALIZED_ROWS_GRANULE 4
|
|
#define REC_AT_TOP 1
|
|
#define REC_AT_BOTTOM 0
|
|
#define CELL_VERTICAL_MARGIN (RULE_Y_OFFSET_TOP + RULE_Y_OFFSET_BOTTOM + 2)
|
|
|
|
static void adjust_rows(LM_DATA *lmp, int delta );
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_allocate_rec_info
|
|
lmp: current lmp
|
|
realized_rows_array_len: number of realized rows in the realized rows array
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_allocate_rec_info(LM_DATA *lmp, int realized_rows_array_len)
|
|
{
|
|
int old_len = lmp->realized_rows_array_len;
|
|
int i;
|
|
|
|
lmp->realized_rows_array_len = realized_rows_array_len;
|
|
|
|
/* recs */
|
|
if (lmp->recs)
|
|
{
|
|
lmp->recs = (long *)xi_tree_realloc(lmp->recs, sizeof(long) * realized_rows_array_len);
|
|
for (i = old_len; i < realized_rows_array_len; ++i)
|
|
lmp->recs[i] = 0L;
|
|
}
|
|
else
|
|
lmp->recs = (long *)xi_tree_malloc(sizeof(long) * realized_rows_array_len, lmp);
|
|
|
|
/* pix_offsets */
|
|
if (lmp->pix_offsets)
|
|
lmp->pix_offsets = (int *)xi_tree_realloc(lmp->pix_offsets,
|
|
sizeof(int) * realized_rows_array_len);
|
|
else
|
|
lmp->pix_offsets = (int *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
|
|
|
|
/* pix_heights */
|
|
if (lmp->pix_heights)
|
|
lmp->pix_heights = (int *)xi_tree_realloc(lmp->pix_heights,
|
|
sizeof(int) * realized_rows_array_len);
|
|
else
|
|
lmp->pix_heights = (int *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
|
|
|
|
/* set_heights */
|
|
if (lmp->set_heights)
|
|
lmp->set_heights = (short *)xi_tree_realloc(lmp->set_heights,
|
|
sizeof(int) * realized_rows_array_len);
|
|
else
|
|
lmp->set_heights = (short *)xi_tree_malloc(sizeof(int) * realized_rows_array_len, lmp);
|
|
|
|
/* buffer */
|
|
if (lmp->buffer)
|
|
{
|
|
for (i = realized_rows_array_len; i < old_len; ++i)
|
|
xi_tree_free(lmp->buffer[i]);
|
|
lmp->buffer = (char * *)xi_tree_realloc(lmp->buffer,
|
|
sizeof(char *) * realized_rows_array_len);
|
|
for (i = old_len; i < realized_rows_array_len; ++i)
|
|
lmp->buffer[i] = (char *)xi_tree_malloc(lmp->text_size, lmp);
|
|
}
|
|
else
|
|
lmp->buffer = (char * *)xi_tree_malloc(sizeof(char *) * realized_rows_array_len,
|
|
lmp);
|
|
|
|
/* row_attribs */
|
|
if (lmp->row_attribs)
|
|
{
|
|
lmp->row_attribs = (unsigned long *)xi_tree_realloc(lmp->row_attribs,
|
|
sizeof(unsigned long) * realized_rows_array_len);
|
|
for (i = old_len; i < realized_rows_array_len; ++i)
|
|
lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
|
|
}
|
|
else
|
|
lmp->row_attribs = (unsigned long *)xi_tree_malloc(sizeof(unsigned long) * realized_rows_array_len,
|
|
lmp);
|
|
|
|
/* row_colors */
|
|
if (lmp->row_colors)
|
|
{
|
|
lmp->row_colors = (COLOR *)xi_tree_realloc(lmp->row_colors,
|
|
sizeof(COLOR) * realized_rows_array_len);
|
|
for (i = old_len; i < realized_rows_array_len; ++i)
|
|
lmp->row_colors[i] = 0L;
|
|
}
|
|
else
|
|
lmp->row_colors = (COLOR *)xi_tree_malloc(sizeof(COLOR) * realized_rows_array_len,
|
|
lmp);
|
|
|
|
/* cell_data */
|
|
if (lmp->cell_data)
|
|
{
|
|
for (i = realized_rows_array_len; i < old_len; ++i)
|
|
xi_tree_free(lmp->cell_data[i]);
|
|
lmp->cell_data = (LM_CELL_DATA * *)xi_tree_realloc(lmp->cell_data,
|
|
sizeof(LM_CELL_DATA *) * realized_rows_array_len);
|
|
for (i = old_len; i < realized_rows_array_len; ++i)
|
|
lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_malloc((lmp->nbr_columns + 1) * sizeof(LM_CELL_DATA),
|
|
lmp);
|
|
}
|
|
else
|
|
lmp->cell_data = (LM_CELL_DATA * *)xi_tree_malloc(sizeof(LM_CELL_DATA *) * realized_rows_array_len,
|
|
lmp);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_create
|
|
win: window in which to put list
|
|
lm_def: list definition
|
|
parent: tree memory parent
|
|
-------------------------------------------------------------------------*/
|
|
LM
|
|
lm_create(WINDOW win, LM_DEF *lm_def, void *parent)
|
|
{
|
|
LM_DATA *lmp;
|
|
int i, font_height, leading, ascent, descent, mch, realized_rows_array_len;
|
|
|
|
lmp = LMP(xi_tree_malloc(sizeof(LM_DATA), parent));
|
|
lmp->cid = lm_def->cid;
|
|
lmp->list_obj = lm_def->list_obj;
|
|
lmp->itf_obj = lm_def->itf_obj;
|
|
lmp->win = win;
|
|
lmp->font = lm_def->font;
|
|
lmp->back_color = lm_def->back_color;
|
|
lmp->enabled_color = lm_def->enabled_color;
|
|
lmp->disabled_color = lm_def->disabled_color;
|
|
lmp->disabled_back_color = lm_def->disabled_back_color;
|
|
lmp->active_color = lm_def->active_color;
|
|
lmp->active_back_color = lm_def->active_back_color;
|
|
lmp->white_space_color = lm_def->white_space_color;
|
|
lmp->rule_color = lm_def->rule_color;
|
|
lmp->attrib = lm_def->attrib;
|
|
lmp->lm_cb = lm_def->lm_cb;
|
|
lmp->no_heading = lm_def->no_heading;
|
|
lmp->sizable_columns = lm_def->sizable_columns;
|
|
lmp->movable_columns = lm_def->movable_columns;
|
|
lmp->fixed_columns = lm_def->fixed_columns;
|
|
lmp->resize_with_window = lm_def->resize_with_window;
|
|
lmp->horz_sync_list = lm_def->horz_sync_list;
|
|
lmp->vert_sync_list = lm_def->vert_sync_list;
|
|
lmp->row_focus_border = lm_def->row_focus_border;
|
|
lmp->row_focus_border_color = lm_def->row_focus_border_color;
|
|
lmp->single_select = lm_def->single_select;
|
|
lmp->pixel_width = lm_def->pixel_width;
|
|
lmp->pixel_height = lm_def->pixel_height;
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->min_cell_height = 0;
|
|
lmp->min_heading_height = lm_def->min_heading_height;
|
|
CTOS_END
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->min_cell_height = lm_def->min_cell_height;
|
|
lmp->min_heading_height = lm_def->min_heading_height;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->no_horz_lines = lm_def->no_horz_lines;
|
|
lmp->no_vert_lines = lm_def->no_vert_lines;
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
lmp->drop_and_delete = lm_def->drop_and_delete;
|
|
lmp->select_cells = lm_def->select_cells;
|
|
lmp->get_all_records = lm_def->get_all_records;
|
|
lmp->keep_all_records = lm_def->keep_all_records;
|
|
lmp->retain_back_color_on_select = lm_def->retain_back_color_on_select;
|
|
lmp->max_lines_in_cell = lm_def->max_lines_in_cell;
|
|
if (! lmp->max_lines_in_cell)
|
|
lmp->max_lines_in_cell =
|
|
(int)xi_get_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL);
|
|
xi_set_xvt_font(win, lm_def->font, FALSE);
|
|
xi_get_font_metrics(win, &leading, &ascent, &descent);
|
|
lmp->leading = leading;
|
|
lmp->ascent = ascent;
|
|
lmp->descent = descent;
|
|
font_height = lmp->ascent + lmp->leading + lmp->descent;
|
|
|
|
/* we add two to the following line so that there is room in the cell for the
|
|
row focus border */
|
|
#if XVTWS == WMWS
|
|
lmp->pix_cell_height = font_height;
|
|
#else
|
|
lmp->pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
mch = 8;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
mch = lm_def->min_cell_height;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->pix_cell_height = max(lmp->pix_cell_height, mch);
|
|
lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
|
|
lmp->pix_top = lm_def->pnt.v;
|
|
#if XVTWS == WMWS
|
|
lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH +
|
|
RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
|
|
lmp->pix_hdr_bottom = max(lmp->pix_hdr_bottom, (lm_def->pnt.v
|
|
+ lmp->min_heading_height - BORDER_WIDTH));
|
|
#else
|
|
lmp->pix_hdr_bottom = lm_def->pnt.v + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH + RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
|
|
lmp->pix_hdr_bottom = max( lmp->pix_hdr_bottom, (lm_def->pnt.v + lmp->min_heading_height));
|
|
#endif
|
|
if (lmp->no_heading)
|
|
lmp->pix_row1_top = lm_def->pnt.v + BORDER_WIDTH;
|
|
else
|
|
lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
|
|
lmp->pix_char_width = lm_def->pix_char_width;
|
|
lmp->nbr_columns = 0;
|
|
lmp->lm_column_data = NULL;
|
|
|
|
/* compute number of rows */
|
|
lmp->nbr_rows = lm_def->nbr_rows;
|
|
if (lm_def->nbr_rows)
|
|
lmp->nbr_rows = lm_def->nbr_rows;
|
|
else
|
|
lmp->nbr_rows = (lm_def->pixel_height - (lmp->pix_row1_top - lm_def->pnt.v)
|
|
- BORDER_WIDTH) / lmp->pix_row_spacing;
|
|
if (lm_def->one_row_list)
|
|
lmp->nbr_rows = 1;
|
|
|
|
lmp->rct.left = lm_def->pnt.h;
|
|
lmp->rct.top = lm_def->pnt.v;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->rct.right = lm_def->pnt.h + 2 * BORDER_WIDTH;
|
|
if (lm_def->resize_with_window)
|
|
lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
|
|
else
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
|
|
(BORDER_WIDTH - RULE_WIDTH_H);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->rct.right = lm_def->pnt.h + BORDER_WIDTH;
|
|
if (lm_def->resize_with_window)
|
|
lmp->rct.bottom = lm_def->pnt.v + lm_def->pixel_height;
|
|
else
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
|
|
+ BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->vir_left = lmp->rct.left + BORDER_WIDTH;
|
|
lmp->vir_right = lmp->vir_left + lmp->pixel_width;
|
|
lmp->text_size = 0;
|
|
|
|
realized_rows_array_len = lm_def->realized_rows_array_len;
|
|
if (! realized_rows_array_len)
|
|
realized_rows_array_len = lmp->nbr_rows + 1;
|
|
lm_allocate_rec_info(lmp, realized_rows_array_len);
|
|
|
|
/* calculate mathematical list rectangle */
|
|
lmp->mlr.top = lmp->pix_row1_top;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
lmp->mlr.left = lmp->rct.left + BORDER_WIDTH;
|
|
lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
else
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
lmp->mlr.left = lmp->rct.left;
|
|
lmp->mlr.right = lmp->rct.right;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
|
|
for (i = 0; i < lmp->realized_rows_array_len; ++i)
|
|
{
|
|
lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_malloc(
|
|
lmp->nbr_columns * sizeof(LM_CELL_DATA), lmp);
|
|
lmp->row_attribs[i] = LM_ROW_ATR_ENABLED;
|
|
}
|
|
|
|
return((LM)PTR_LONG(lmp));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_rec_event
|
|
lmp: current lmp
|
|
row: row to do event on
|
|
type: XI_EVENT_TYPE
|
|
notes: In this case, row is not really a row. It is an index into the
|
|
realized rows array.
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
do_rec_event(LM_DATA *lmp, int row, XI_EVENT_TYPE type)
|
|
{
|
|
LM_CELL_DATA *lmcdp;
|
|
int i;
|
|
|
|
if (type == XIE_REC_FREE)
|
|
{
|
|
if (lmp->recs[row] != lmp->focus_rec)
|
|
do_lm_cb((LM)lmp, LM_CB_REC_FREE, row, 0, NULL, NULL, 0);
|
|
lmcdp = lmp->cell_data[row];
|
|
for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
|
|
{
|
|
if (lmcdp->font)
|
|
{
|
|
xi_free_font_id(lmp->itf_obj, *lmcdp->font);
|
|
xi_tree_free(lmcdp->font);
|
|
}
|
|
if (lmcdp->string)
|
|
xi_tree_free(lmcdp->string);
|
|
if (lmcdp->line_breaks)
|
|
xi_tree_free(lmcdp->line_breaks);
|
|
memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
|
|
}
|
|
lmp->recs[row] = 0L;
|
|
/* we technically do not need to do the following lines. it just keeps the data structures clean. */
|
|
lmp->pix_heights[row] = 0;
|
|
lmp->set_heights[row] = FALSE;
|
|
lmp->pix_offsets[row] = 0;
|
|
memset(lmp->buffer[row], '\0', lmp->text_size);
|
|
lmp->row_attribs[row] = 0L;
|
|
lmp->row_colors[row] = 0L;
|
|
}
|
|
if (type == XIE_REC_ALLOCATE)
|
|
{
|
|
do_lm_cb((LM)lmp, LM_CB_REC_ALLOCATE, row, 0, NULL, NULL, 0);
|
|
lmcdp = lmp->cell_data[row];
|
|
for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
|
|
memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: row_copy
|
|
lmp: current lmp
|
|
source_row: row from which to copy
|
|
dest_row: destination row
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
row_copy(LM_DATA *lmp, int source_row, int dest_row)
|
|
{
|
|
int idx;
|
|
LM_CELL_DATA *lmcdpd, *lmcdps;
|
|
|
|
lmp->recs[dest_row] = lmp->recs[source_row];
|
|
lmp->pix_heights[dest_row] = lmp->pix_heights[source_row];
|
|
lmp->set_heights[dest_row] = lmp->set_heights[source_row];
|
|
lmp->pix_offsets[dest_row] = lmp->pix_offsets[source_row];
|
|
memcpy(lmp->buffer[dest_row], lmp->buffer[source_row], lmp->text_size);
|
|
lmp->row_attribs[dest_row] = lmp->row_attribs[source_row];
|
|
lmp->row_colors[dest_row] = lmp->row_colors[source_row];
|
|
for (idx = 0,
|
|
lmcdpd = lmp->cell_data[dest_row],
|
|
lmcdps = lmp->cell_data[source_row];
|
|
idx < lmp->nbr_columns;
|
|
++idx,
|
|
++lmcdpd,
|
|
++lmcdps)
|
|
{
|
|
*lmcdpd = *lmcdps;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: init_row
|
|
lmp: current lmp
|
|
row: row to init
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
init_row(LM_DATA *lmp, int row)
|
|
{
|
|
int idx;
|
|
LM_CELL_DATA *lmcdp;
|
|
|
|
lmp->recs[row] = 0L;
|
|
lmp->pix_heights[row] = 0;
|
|
lmp->set_heights[row] = 0;
|
|
lmp->pix_offsets[row] = 0;
|
|
lmp->row_attribs[row] = LM_ROW_ATR_ENABLED;
|
|
lmp->row_colors[row] = 0;
|
|
for (idx = 0,
|
|
lmcdp = lmp->cell_data[row];
|
|
idx < lmp->nbr_columns;
|
|
++idx,
|
|
++lmcdp)
|
|
{
|
|
memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rec_available
|
|
lmp: current lmp
|
|
top: record to become available is at the top of the realized_row array,
|
|
else the record to become available is at the bottom of the realized
|
|
row array.
|
|
allocate_rec: if TRUE, then send XIE_REC_ALLOCATE event
|
|
notes: if, in order to get a record at the bottom of the realized row array,
|
|
we must discard a record at the beginning of the rrr array, then
|
|
we must change lmp->rrr_offset.
|
|
whenever we make a record be available, make sure that we free
|
|
fonts in cell_data.
|
|
Also, clear cell_data.
|
|
-------------------------------------------------------------------------*/
|
|
static void make_rec_available( LM_DATA *lmp, BOOLEAN top, BOOLEAN allocate_rec,
|
|
BOOLEAN doing_scroll_first)
|
|
{
|
|
int cnt;
|
|
|
|
if (top)
|
|
{
|
|
int idx;
|
|
|
|
if (! lmp->get_all_records)
|
|
{
|
|
int nbr_to_free;
|
|
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
if (nbr_to_free > 0)
|
|
{
|
|
/* free as many records at the end of the list as possible */
|
|
for (idx = lmp->last_fully_vis + 2; idx < lmp->nbr_realized_rows;
|
|
++idx)
|
|
do_rec_event(lmp, idx, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
|
|
if (lmp->nbr_realized_rows >= lmp->realized_rows_array_len)
|
|
lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1);
|
|
|
|
/* copy all the records, making room at the beginning of the realized_row array */
|
|
++lmp->nbr_realized_rows;
|
|
for (idx = lmp->nbr_realized_rows - 1;
|
|
idx > 0; --idx)
|
|
row_copy(lmp, idx - 1, idx);
|
|
adjust_rows(lmp, 1);
|
|
init_row(lmp, 0);
|
|
if (allocate_rec)
|
|
do_rec_event(lmp, 0, XIE_REC_ALLOCATE);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (! lmp->get_all_records || doing_scroll_first)
|
|
{
|
|
/* free as many records at the beginning of the list as possible */
|
|
cnt = lmp->first_fully_vis - 2;
|
|
if (cnt > 0)
|
|
{
|
|
int idx, jidx;
|
|
|
|
for (idx = 0; idx < cnt; ++idx)
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[idx];
|
|
do_rec_event(lmp, idx, XIE_REC_FREE);
|
|
}
|
|
|
|
lmp->nbr_realized_rows -= cnt;
|
|
|
|
/* copy all the records, making room at the end of the realized row array */
|
|
for (idx = cnt, jidx = 0;
|
|
jidx < lmp->nbr_realized_rows;
|
|
++idx, ++jidx)
|
|
row_copy(lmp, idx, idx - cnt);
|
|
adjust_rows(lmp, -cnt);
|
|
}
|
|
if (lmp->nbr_realized_rows >= lmp->realized_rows_array_len)
|
|
lm_allocate_rec_info(lmp, lmp->realized_rows_array_len + 1);
|
|
++lmp->nbr_realized_rows;
|
|
init_row(lmp, lmp->nbr_realized_rows - 1);
|
|
if (allocate_rec)
|
|
do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_ALLOCATE);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_next_rec
|
|
lmp: current lmp
|
|
returns: TRUE if next record was available
|
|
FALSE if not
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
get_next_rec(LM_DATA *lmp, BOOLEAN doing_scroll_first)
|
|
{
|
|
int idx, row_height;
|
|
|
|
make_rec_available(lmp, REC_AT_BOTTOM, TRUE, doing_scroll_first);
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
if (do_lm_cb_get((LM)lmp, LM_CB_GET_NEXT,
|
|
&lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height))
|
|
{
|
|
do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
|
|
if (row_height)
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = 0;
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
|
|
lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_previous_rec
|
|
lmp: current lmp
|
|
returns: TRUE if previous record was available
|
|
FALSE if not
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN get_previous_rec(LM_DATA *lmp)
|
|
{
|
|
int row_height, cnt;
|
|
|
|
make_rec_available(lmp, REC_AT_TOP, TRUE, FALSE);
|
|
if (do_lm_cb_get((LM)lmp, LM_CB_GET_PREV,
|
|
&lmp->recs[1], &lmp->recs[0], 0, &lmp->row_colors[0],
|
|
&lmp->row_attribs[0], &row_height))
|
|
{
|
|
do_rec_event(lmp, 0, XIE_REC_FREE);
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows - 1; ++cnt)
|
|
row_copy(lmp, cnt + 1, cnt);
|
|
adjust_rows(lmp, -1);
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
if (row_height)
|
|
{
|
|
lmp->pix_heights[0] = row_height;
|
|
lmp->set_heights[0] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[0] = 0;
|
|
lmp->set_heights[0] = FALSE;
|
|
}
|
|
lm_invalidate_rows_internal((LM)lmp, 0, 0, FALSE, -1, TRUE );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_cell_height
|
|
lmp: current lmp
|
|
row: row number of cell to calculate
|
|
column: column number of cell to calculate
|
|
returns: height of cell in pixels
|
|
notes: this function does not need to take into consideration the
|
|
variable fixed_row_height. This function is only used by
|
|
lm_calculate_row_height, and will only be called if
|
|
fixed_row_height is false.
|
|
notes: In the future, we may wish to support word wrap. At this
|
|
point, the only way to have multiple lines in a cell is to
|
|
have '\n' characters in the text.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calculate_cell_height(LM_DATA *lmp, int row, int column)
|
|
{
|
|
int pix_height; /* pix_height does include the width of the rules */
|
|
int nbr_lines;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
cell_data = &lmp->cell_data[row][column];
|
|
if (lmp->lm_column_data[column]->wrap_text)
|
|
{
|
|
if (! cell_data->valid_data)
|
|
do_lm_cb_text(lmp, row, column, TRUE );
|
|
lm_wrap_text(lmp, row, column, TRUE);
|
|
nbr_lines = min(cell_data->nbr_lines, lmp->max_lines_in_cell);
|
|
}
|
|
else
|
|
{
|
|
nbr_lines = 1;
|
|
if (! cell_data->font_height)
|
|
{
|
|
FONT_OBJ *font;
|
|
int leading, ascent, descent, char_width;
|
|
|
|
if (cell_data->font)
|
|
font = cell_data->font;
|
|
else
|
|
font = lmp->font;
|
|
xi_get_font_metrics_font(font, &leading, &ascent, &descent, &char_width);
|
|
cell_data->font_height = leading + ascent + descent;
|
|
}
|
|
}
|
|
#if XVTWS != WMWS
|
|
pix_height = nbr_lines * cell_data->font_height + CELL_VERTICAL_MARGIN
|
|
+ RULE_WIDTH_H;
|
|
#else
|
|
pix_height = nbr_lines * cell_data->font_height;
|
|
#endif
|
|
pix_height = max(pix_height, lmp->pix_row_spacing);
|
|
return pix_height;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_calculate_row_height
|
|
lmp: current lmp
|
|
row: row number to calculate
|
|
returns: height of row in pixels
|
|
notes: if fixed_row_height is TRUE, then the calculation is easy.
|
|
if fixed_row_height is FALSE, then the calculation must take
|
|
word wrap into consideration, etc.
|
|
row height includes the height of the horizontal rule below
|
|
the row.
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_calculate_row_height(LM_DATA *lmp, int row)
|
|
{
|
|
int pix_height;
|
|
|
|
if (lmp->fixed_row_height)
|
|
pix_height = lmp->pix_row_spacing;
|
|
else if (lmp->set_heights[row])
|
|
pix_height = lmp->pix_heights[row];
|
|
else
|
|
{
|
|
int cnt;
|
|
int cell_height;
|
|
|
|
pix_height = 0;
|
|
for (cnt = 0; cnt < lmp->nbr_columns; ++cnt)
|
|
{
|
|
cell_height = calculate_cell_height(lmp, row, cnt);
|
|
pix_height = max(pix_height, cell_height);
|
|
}
|
|
}
|
|
if (pix_height > lmp->mlr_height)
|
|
pix_height = lmp->mlr_height;
|
|
return pix_height;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_visibles
|
|
lmp: current lmp
|
|
process: calculates lmp->first_fully_vis
|
|
calculates lmp->last_fully_vis
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calculate_visibles(LM_DATA *lmp)
|
|
{
|
|
int i, idx;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
BOOLEAN have_first;
|
|
|
|
have_first = FALSE;
|
|
lmp->first_fully_vis = 0;
|
|
lmp->last_fully_vis = 0;
|
|
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)
|
|
{
|
|
if (! have_first && *pix_offsetsp >= (-lmp->rrr_offset))
|
|
{
|
|
have_first = TRUE;
|
|
lmp->first_fully_vis = i;
|
|
}
|
|
/*
|
|
should be <, because we are dealing with mathematical rects, but we don't care if
|
|
the rule is not on the list.
|
|
*pix_offsetp + *pix_heightsp is the mathematical rect of the row, in rrr terms.
|
|
lmp->rrr_offset + lmp->mlr_height is the mathematical rect of the list, in rrr terms.
|
|
*/
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (*pix_offsetsp + *pix_heightsp + lmp->rrr_offset <= lmp->mlr_height)
|
|
lmp->last_fully_vis = i;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if (*pix_offsetsp + *pix_heightsp - 1 + lmp->rrr_offset <= lmp->mlr_height)
|
|
lmp->last_fully_vis = i;
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calculate_pix_offsets
|
|
lmp: current lmp
|
|
process: calculates the lmp->pix_offsets array
|
|
calculates lmp->first_fully_vis
|
|
calculates lmp->last_fully_vis
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
calculate_pix_offsets(LM_DATA *lmp, BOOLEAN draw_changes )
|
|
{
|
|
int i, cur_pix, idx;
|
|
int *pix_offsetsp;
|
|
int *pix_heightsp;
|
|
BOOLEAN have_first;
|
|
|
|
cur_pix = 0;
|
|
have_first = FALSE;
|
|
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)
|
|
{
|
|
int new_height;
|
|
|
|
new_height = lm_calculate_row_height(lmp, i);
|
|
if ( draw_changes &&
|
|
(*pix_offsetsp != cur_pix || *pix_heightsp != new_height ))
|
|
{
|
|
RCT rect;
|
|
|
|
lm_get_row_rect( &rect, (LM)lmp, i );
|
|
lm_invalidate_rect( lmp, &rect, FALSE );
|
|
rect.top = cur_pix;
|
|
rect.bottom = cur_pix + new_height;
|
|
lm_invalidate_rect( lmp, &rect, FALSE );
|
|
}
|
|
*pix_offsetsp = cur_pix;
|
|
*pix_heightsp = new_height;
|
|
if (! have_first && cur_pix >= (-lmp->rrr_offset))
|
|
{
|
|
have_first = TRUE;
|
|
lmp->first_fully_vis = i;
|
|
}
|
|
cur_pix += new_height;
|
|
/*
|
|
should be <=, because we are dealing with mathematical rects, but we don't care if
|
|
the rule is not on the list.
|
|
*pix_offsetp + *pix_heightsp is the mathematical rect of the row, in rrr terms.
|
|
lmp->rrr_offset + lmp->mlr_height is the mathematical rect of the list, in rrr terms.
|
|
*/
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (cur_pix + lmp->rrr_offset <= lmp->mlr_height)
|
|
lmp->last_fully_vis = i;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
if ( cur_pix - 1 + lmp->rrr_offset <= lmp->mlr_height)
|
|
lmp->last_fully_vis = i;
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
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;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rrr_room_pix
|
|
lmp: current lmp
|
|
pixels: number of additional pixels desired in realized row rect
|
|
pixels may be negative, in which case, the desired pixels
|
|
are above the realized row rect
|
|
pixels may be positive, in which case, the desired pixels
|
|
are below the realized row rect
|
|
returns: recs read
|
|
-------------------------------------------------------------------------*/
|
|
int
|
|
lm_make_rrr_room_pix(LM_DATA *lmp, int pixels, BOOLEAN do_redraw )
|
|
{
|
|
int recs_read = 0;
|
|
int idx;
|
|
|
|
if (lmp->nbr_realized_rows == 0)
|
|
{
|
|
lmp->rrr_bottom = 0;
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
return 0;
|
|
}
|
|
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->rrr_bottom = lmp->pix_offsets[idx] + lmp->pix_heights[idx];
|
|
|
|
if (pixels < 0)
|
|
{
|
|
while (TRUE)
|
|
{
|
|
if (pixels >= lmp->rrr_offset)
|
|
return recs_read;
|
|
if (get_previous_rec(lmp))
|
|
{
|
|
int row_height;
|
|
|
|
row_height = lm_calculate_row_height(lmp, 0);
|
|
lmp->rrr_offset -= row_height;
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
calculate_visibles(lmp);
|
|
++recs_read;
|
|
}
|
|
else
|
|
return recs_read;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (TRUE)
|
|
{
|
|
if (lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset >= pixels)
|
|
return recs_read;
|
|
if (lmp->get_all_records) return recs_read;
|
|
if (get_next_rec(lmp, FALSE))
|
|
{
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
calculate_visibles(lmp);
|
|
++recs_read;
|
|
}
|
|
else
|
|
return recs_read;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: make_rrr_room_rows
|
|
lmp: current lmp
|
|
nbr_rows: nbr of rows to scroll
|
|
returns: pixels to scroll
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
make_rrr_room_rows(LM_DATA *lmp, int* rows, BOOLEAN do_redraw)
|
|
{
|
|
int nbr_rows = *rows;
|
|
|
|
if (nbr_rows < 0)
|
|
{
|
|
/* convert nbr_rows to positive, for ease of programming */
|
|
nbr_rows = -nbr_rows;
|
|
while (TRUE)
|
|
{
|
|
if (! nbr_rows )
|
|
{
|
|
*rows = 0;
|
|
return 0;
|
|
}
|
|
if (lmp->first_fully_vis - nbr_rows >= 0)
|
|
{
|
|
int pixels;
|
|
|
|
pixels = -(lmp->pix_offsets[lmp->first_fully_vis] -
|
|
lmp->pix_offsets[lmp->first_fully_vis - nbr_rows]);
|
|
lmp->update_rows_at_top = nbr_rows;
|
|
*rows = nbr_rows;
|
|
return pixels;
|
|
}
|
|
else
|
|
{
|
|
if (!lmp->get_all_records && get_previous_rec(lmp))
|
|
{
|
|
lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
|
|
lmp->rrr_offset -= lmp->pix_heights[0];
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
}
|
|
else
|
|
{
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
nbr_rows = lmp->first_fully_vis;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOLEAN get_next_accepted = TRUE;
|
|
int pixels;
|
|
|
|
pixels = lmp->pix_offsets[lmp->first_fully_vis + nbr_rows] -
|
|
lmp->pix_offsets[lmp->first_fully_vis];
|
|
while (TRUE)
|
|
{
|
|
int delta_avail;
|
|
|
|
if (! nbr_rows)
|
|
{
|
|
*rows = 0;
|
|
return 0;
|
|
}
|
|
/*
|
|
if get_all_records is true, then we never need to get more records
|
|
if there is a row beyond the last partially visible row, then we
|
|
don't need to get more records
|
|
if a get next has been refused, then we have all the records that
|
|
we are going to get
|
|
*/
|
|
if (lmp->get_all_records ||
|
|
lmp->last_fully_vis + 1 + nbr_rows < lmp->nbr_realized_rows ||
|
|
! get_next_accepted)
|
|
{
|
|
delta_avail = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] +
|
|
lmp->rrr_offset - lmp->mlr_height;
|
|
if (lmp->get_all_records || pixels <= delta_avail || ! get_next_accepted)
|
|
{
|
|
int nrows, cnt, pcnt;
|
|
|
|
for (nrows = 0, cnt = lmp->last_fully_vis + 1, pcnt = 0;
|
|
pcnt < pixels && cnt < lmp->nbr_realized_rows;
|
|
++nrows, ++cnt, pcnt += lmp->pix_heights[cnt])
|
|
;
|
|
lmp->update_rows_at_bottom = nrows;
|
|
*rows = nbr_rows;
|
|
return pixels;
|
|
}
|
|
}
|
|
if (!lmp->get_all_records
|
|
&& (get_next_accepted = get_next_rec(lmp, FALSE)) != 0)
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
else
|
|
{
|
|
calculate_pix_offsets(lmp, do_redraw);
|
|
nbr_rows = lmp->nbr_realized_rows - 1 - lmp->last_fully_vis;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int make_room_rows( LM_DATA* lm_data, int rows, BOOLEAN do_draw )
|
|
{
|
|
return make_rrr_room_rows( lm_data, &rows, do_draw );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_scroll_bar
|
|
itf: current itf
|
|
listdata: list_data
|
|
list: list
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
do_scroll_bar(XI_LIST_DATA *listdata)
|
|
{
|
|
LM_DATA *lmp;
|
|
|
|
if (listdata->scroll_bar)
|
|
{
|
|
lmp = (LM_DATA *)listdata->lm;
|
|
if (lmp->get_all_records)
|
|
{
|
|
int top, prop;
|
|
|
|
if (lmp->rrr_offset == 0 && lmp->rrr_bottom < lmp->mlr_height)
|
|
{
|
|
top = 0;
|
|
prop = 100;
|
|
} else
|
|
{
|
|
top = (int)(-lmp->rrr_offset * 100L / lmp->rrr_bottom);
|
|
if (lmp->mlr_height - lmp->rrr_offset >= lmp->rrr_bottom - 1)
|
|
prop = 100 - top;
|
|
else
|
|
prop = (int)(lmp->mlr_height * 100L / lmp->rrr_bottom);
|
|
}
|
|
xvt_sbar_set_proportion(listdata->sb_win, HVSCROLL, prop);
|
|
xvt_sbar_set_pos(listdata->sb_win, HVSCROLL, top);
|
|
} else
|
|
{
|
|
int percent1 = 0;
|
|
int percent2 = 100;
|
|
|
|
if (lmp->nbr_realized_rows > 1)
|
|
{
|
|
do_lm_cb(listdata->lm, LM_CB_GET_PERCENT, lmp->first_fully_vis,
|
|
0, NULL, &percent1, 0);
|
|
do_lm_cb(listdata->lm, LM_CB_GET_PERCENT, lmp->last_fully_vis,
|
|
0, NULL, &percent2, 0);
|
|
}
|
|
xvt_sbar_set_proportion(listdata->sb_win, HVSCROLL, percent2 - percent1);
|
|
xvt_sbar_set_pos(listdata->sb_win, HVSCROLL, percent1);
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
xvt_sbar_set_range(listdata->sb_win, HVSCROLL, 0, 100 - (percent2 - percent1));
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_remove_all_rows
|
|
lm: current lm
|
|
-------------------------------------------------------------------------*/
|
|
|
|
void lm_remove_all_rows( LM_DATA* lmp, BOOLEAN delete_focus )
|
|
{
|
|
int i;
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
if (lmp->focus_rec && delete_focus )
|
|
{
|
|
int idx;
|
|
BOOLEAN found = FALSE;
|
|
|
|
for (idx = 0; idx < lmp->nbr_realized_rows; ++idx)
|
|
{
|
|
if (lmp->focus_rec == lmp->recs[idx])
|
|
{
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (! found)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < lmp->nbr_realized_rows; ++i)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
|
|
lmp->nbr_realized_rows = 0;
|
|
lmp->rrr_bottom = 0;
|
|
lmp->rrr_offset = 0;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
lm_list_has_focus(LM_DATA *lmp)
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
BOOLEAN retval;
|
|
|
|
itf = lmp->itf_obj->v.itf;
|
|
retval = (itf->focus_obj != NULL && itf->focus_obj->parent == lmp->list_obj);
|
|
return retval;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
lm_cell_has_focus( LM_DATA *lmp, int row, int column,
|
|
BOOLEAN is_vert_scrolled)
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
XI_OBJ *focus_obj;
|
|
XI_CELL_DATA *cd;
|
|
|
|
if (lmp->txt_is_invisible)
|
|
return FALSE;
|
|
itf = lmp->itf_obj->v.itf;
|
|
focus_obj = itf->focus_obj;
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
cd = &focus_obj->v.cell;
|
|
return (cd->row == row && cd->column == column
|
|
&& cd->is_vert_scrolled == is_vert_scrolled);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
lm_row_has_focus( LM_DATA *lmp, int row, BOOLEAN is_vert_scrolled)
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
XI_OBJ *focus_obj;
|
|
XI_CELL_DATA *cd;
|
|
|
|
#if 0
|
|
if (lmp->txt_is_invisible && ! lmp->horizontally_scrolling_list)
|
|
return FALSE;
|
|
#endif
|
|
itf = lmp->itf_obj->v.itf;
|
|
focus_obj = itf->focus_obj;
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
cd = &focus_obj->v.cell;
|
|
return (cd->row == row && cd->is_vert_scrolled == is_vert_scrolled);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void
|
|
lm_get_focus_cell(LM_DATA *lmp, int *rowp, int *columnp, BOOLEAN* is_vert_scrolled)
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
XI_OBJ *focus_obj;
|
|
XI_CELL_DATA *cd;
|
|
|
|
itf = lmp->itf_obj->v.itf;
|
|
focus_obj = itf->focus_obj;
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
cd = &focus_obj->v.cell;
|
|
*rowp = cd->row;
|
|
*columnp = cd->column;
|
|
*is_vert_scrolled = cd->is_vert_scrolled;
|
|
return;
|
|
}
|
|
*rowp = 0;
|
|
*columnp = 0;
|
|
*is_vert_scrolled = FALSE;
|
|
return;
|
|
}
|
|
|
|
|
|
void lm_set_focus_cell(LM_DATA *lmp, int row, int column, BOOLEAN is_vert_scrolled)
|
|
{
|
|
XI_ITF_DATA *itf;
|
|
XI_OBJ *focus_obj;
|
|
XI_CELL_DATA *cd;
|
|
|
|
itf = lmp->itf_obj->v.itf;
|
|
focus_obj = itf->focus_obj;
|
|
if (focus_obj != NULL && focus_obj->parent == lmp->list_obj &&
|
|
focus_obj->type == XIT_CELL)
|
|
{
|
|
cd = &focus_obj->v.cell;
|
|
cd->row = row;
|
|
cd->column = column;
|
|
cd->is_vert_scrolled = (unsigned char)is_vert_scrolled;
|
|
return;
|
|
}
|
|
xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20921", 20921,
|
|
"lm_set_focus_cell called when list does not have focus");
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* lm_set_focus_text */
|
|
/* -------------------------------------------------------------------------- */
|
|
void lm_set_focus_text( LM_DATA* lmp, const char* new_text )
|
|
{
|
|
int len = strlen(new_text) + 1;
|
|
if (lmp->focus_cell_text)
|
|
lmp->focus_cell_text = (char *)xi_tree_realloc(lmp->focus_cell_text, len);
|
|
else
|
|
lmp->focus_cell_text = (char *)xi_tree_malloc(len, lmp);
|
|
strcpy(lmp->focus_cell_text, new_text);
|
|
}
|
|
|
|
void
|
|
lm_make_invis(LM_DATA *lmp)
|
|
{
|
|
TXT_DATA *txt;
|
|
|
|
if (! lm_list_has_focus(lmp))
|
|
return;
|
|
if (lmp->txt_is_invisible)
|
|
return;
|
|
if (lmp->txt)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
lmp->txt_is_invisible = TRUE;
|
|
lmp->focus_rec = lmp->recs[focus_row];
|
|
lmp->focus_rec_color = lmp->row_colors[focus_row];
|
|
lmp->focus_rec_attrib = lmp->row_attribs[focus_row];
|
|
lmp->focus_rec_height = lmp->pix_heights[focus_row];
|
|
txt = lmp->txt;
|
|
lm_set_focus_text( lmp, txt->text );
|
|
lmp->focus_cell_ip1 = txt->selstart;
|
|
lmp->focus_cell_ip2 = txt->selstop;
|
|
txt_hide_caret(lmp->txt);
|
|
txt_caret(lmp->txt, FALSE);
|
|
if (lmp->focus_cell_ip1 != lmp->focus_cell_ip2)
|
|
redraw_cell((LM)lmp, focus_row, focus_column, FALSE );
|
|
xi_tree_free((char *)lmp->txt);
|
|
lmp->txt = NULL;
|
|
}
|
|
else
|
|
{
|
|
lmp->txt_is_invisible = FALSE;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: fill_previous
|
|
returns: # of records read
|
|
-------------------------------------------------------------------------*/
|
|
static int fill_previous( LM_DATA* lmp )
|
|
{
|
|
int *pix_heights, *pix_offsets;
|
|
int offset, height;
|
|
int i;
|
|
int result = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
|
|
if (! get_previous_rec(lmp))
|
|
break;
|
|
result++;
|
|
/* recalculate the heights and offsets of every row */
|
|
lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
|
|
offset = 0;
|
|
for (i = 0, pix_heights = &lmp->pix_heights[0],
|
|
pix_offsets = &lmp->pix_offsets[0];
|
|
i < lmp->nbr_realized_rows;
|
|
++i, ++pix_heights, ++pix_offsets)
|
|
{
|
|
*pix_offsets = offset;
|
|
offset += *pix_heights;
|
|
}
|
|
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
if we finally have enough rows to display the entire list
|
|
|
|
note: we subtract 1 from the space necessary because it is not
|
|
necessary to create space for the pixel at the bottom of the
|
|
last row.
|
|
*/
|
|
height = lmp->pix_heights[lmp->nbr_realized_rows - 1];
|
|
if (! height)
|
|
height = lmp->pix_row_spacing;
|
|
if (! lmp->get_all_records &&
|
|
(lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
height - 1
|
|
>= lmp->mlr_height))
|
|
break;
|
|
}
|
|
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
|
|
lmp->rrr_bottom = lmp->pix_offsets[lmp->nbr_realized_rows - 1]
|
|
+ lmp->pix_heights[lmp->nbr_realized_rows - 1];
|
|
/*
|
|
subtract 1 from rrr_bottom because of the pixel at the bottom of the
|
|
last row.
|
|
*/
|
|
lmp->rrr_offset = lmp->mlr_height - (lmp->rrr_bottom - 1);
|
|
lmp->rrr_offset = min(0, lmp->rrr_offset);
|
|
|
|
/*
|
|
although we have adjusted pix_offsets, and pix_heights, it is still necessary to calculate
|
|
the first and last fully visible rows
|
|
*/
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
if the page down does not make the first row editable, then
|
|
scroll the exact amount to make it editable
|
|
*/
|
|
if (-lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis])
|
|
{
|
|
lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
|
|
calculate_visibles(lmp);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* data structure for passing around lm_scroll functions */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
typedef struct {
|
|
int nbr_lines;
|
|
int percent;
|
|
long rec;
|
|
BOOLEAN have_rec;
|
|
COLOR color;
|
|
unsigned long attrib;
|
|
int row_height_arg;
|
|
int scroll_type;
|
|
int pix_overlap;
|
|
int nbr_pixels;
|
|
RCT focus_cell_rct;
|
|
BOOLEAN have_pixels;
|
|
BOOLEAN list_had_focus;
|
|
BOOLEAN is_first_or_last;
|
|
int focus_row;
|
|
int focus_column;
|
|
BOOLEAN v_scrolled;
|
|
int pixels_scrolled;
|
|
} lm_scroll_data;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_scroll_data_construct */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static void lm_scroll_data_construct( LM_DATA* lmp, lm_scroll_data* data,
|
|
LM_SCROLL_ARG* arg )
|
|
{
|
|
int pref_overlap;
|
|
|
|
data->nbr_lines = arg->nbr_lines;
|
|
data->percent = arg->percent;
|
|
data->rec = arg->rec;
|
|
data->have_rec = arg->have_rec;
|
|
data->color = arg->color;
|
|
data->attrib = arg->attrib;
|
|
data->row_height_arg = arg->row_height;
|
|
data->have_pixels = FALSE;
|
|
data->list_had_focus = FALSE;
|
|
data->is_first_or_last = FALSE;
|
|
if (arg->nbr_lines == XI_SCROLL_FIRST && arg->percent == 100)
|
|
data->nbr_lines = XI_SCROLL_LAST;
|
|
if (! lmp->nbr_realized_rows)
|
|
data->nbr_lines = XI_SCROLL_FIRST;
|
|
if (arg->have_rec)
|
|
{
|
|
if (arg->rec_at_top)
|
|
data->nbr_lines = XI_SCROLL_FIRST;
|
|
else
|
|
data->nbr_lines = XI_SCROLL_LAST;
|
|
}
|
|
data->scroll_type = data->nbr_lines;
|
|
pref_overlap = (int)xi_get_pref(XI_PREF_OVERLAP);
|
|
data->pix_overlap = pref_overlap * lmp->pix_row_spacing;
|
|
data->pixels_scrolled = 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* lm_scroll_remove focus */
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static BOOLEAN lm_scroll_remove_focus( LM_DATA* lmp, lm_scroll_data* data,
|
|
XI_OBJ* old_focus_obj )
|
|
{
|
|
/* remove the focus from the list being scrolled */
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
data->list_had_focus = TRUE;
|
|
lm_get_focus_cell( lmp, &data->focus_row, &data->focus_column,
|
|
&data->v_scrolled );
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
if (lmp->focus_rec == 0)
|
|
{
|
|
lm_make_invis(lmp);
|
|
switch (data->nbr_lines)
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
{
|
|
int current_percent;
|
|
|
|
do_lm_cb( (LM)lmp, LM_CB_GET_PERCENT,
|
|
lmp->first_fully_vis, 0, NULL,¤t_percent, 0);
|
|
lmp->focus_rec_is_above = (data->percent > current_percent);
|
|
break;
|
|
}
|
|
case XI_SCROLL_LAST:
|
|
lmp->focus_rec_is_above = TRUE;
|
|
break;
|
|
case XI_SCROLL_PGUP:
|
|
lmp->focus_rec_is_above = FALSE;
|
|
break;
|
|
case XI_SCROLL_PGDOWN:
|
|
lmp->focus_rec_is_above = TRUE;
|
|
break;
|
|
default:
|
|
lmp->focus_rec_is_above = (data->nbr_lines > 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xi_get_rect(old_focus_obj, &data->focus_cell_rct);
|
|
if (! xi_move_focus(lmp->itf_obj))
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_calc_lines */
|
|
/* if nbr_lines is not an integral, and instead is one of XI_SCROLL_FIRST, */
|
|
/* XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDOWN, then calculate */
|
|
/* the number of lines. */
|
|
/*------------------------------------------------------------------------- */
|
|
static void lm_scroll_calc_lines( LM_DATA* lmp, lm_scroll_data* data )
|
|
{
|
|
switch (data->nbr_lines)
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
case XI_SCROLL_LAST:
|
|
data->is_first_or_last = TRUE;
|
|
break;
|
|
case XI_SCROLL_PGUP:
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
data->nbr_pixels = -(lmp->mlr_height - data->pix_overlap);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
data->nbr_pixels = -(lmp->mlr_height - data->pix_overlap + 1);
|
|
CTOS_END;
|
|
#endif
|
|
data->have_pixels = TRUE;
|
|
break;
|
|
case XI_SCROLL_PGDOWN:
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
data->nbr_pixels = lmp->mlr_height - data->pix_overlap;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
data->nbr_pixels = lmp->mlr_height - data->pix_overlap + 1;
|
|
CTOS_END;
|
|
#endif
|
|
data->have_pixels = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_get_initial_rec */
|
|
/*------------------------------------------------------------------------- */
|
|
static BOOLEAN lm_scroll_get_initial_rec( LM_DATA* lmp, lm_scroll_data* data,
|
|
int record_location, int event_type )
|
|
{
|
|
int row_height;
|
|
BOOLEAN refused;
|
|
|
|
/* first, get rid of all rows */
|
|
lm_remove_all_rows( lmp, FALSE );
|
|
make_rec_available(lmp, (BOOLEAN)record_location, (BOOLEAN)!data->have_rec, TRUE);
|
|
if (data->have_rec)
|
|
{
|
|
lmp->recs[0] = data->rec;
|
|
lmp->row_colors[0] = data->color;
|
|
lmp->row_attribs[0] = data->attrib;
|
|
row_height = data->row_height_arg;
|
|
refused = FALSE;
|
|
}
|
|
else
|
|
{
|
|
refused = do_lm_cb_get( (LM)lmp, event_type, &lmp->recs[0], &lmp->recs[0],
|
|
data->percent, &lmp->row_colors[0],
|
|
&lmp->row_attribs[0], &row_height);
|
|
if (refused)
|
|
{
|
|
do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
|
|
--lmp->nbr_realized_rows;
|
|
calculate_visibles(lmp);
|
|
}
|
|
}
|
|
if (! refused)
|
|
{
|
|
if (row_height)
|
|
{
|
|
lmp->pix_heights[0] = row_height;
|
|
lmp->set_heights[0] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[0] = 0;
|
|
lmp->set_heights[0] = FALSE;
|
|
}
|
|
lmp->pix_offsets[0] = 0;
|
|
lmp->pix_heights[0] = lm_calculate_row_height(lmp, 0);
|
|
lm_invalidate_rows_internal((LM)lmp, 0, 0, FALSE, -1, TRUE );
|
|
}
|
|
return !refused;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_fill_forward */
|
|
/* returns # of records read if fill previous called, otherwise 0 */
|
|
/*------------------------------------------------------------------------- */
|
|
|
|
static int lm_scroll_fill_forward( LM_DATA* lmp, BOOLEAN have_rec )
|
|
{
|
|
BOOLEAN refused;
|
|
|
|
while (TRUE)
|
|
{
|
|
int idx;
|
|
|
|
refused = !get_next_rec(lmp, TRUE);
|
|
if ( refused )
|
|
break;
|
|
idx = lmp->nbr_realized_rows - 1;
|
|
lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
|
|
if (idx > 0)
|
|
lmp->pix_offsets[idx] = lmp->pix_offsets[idx - 1]
|
|
+ lmp->pix_heights[idx - 1];
|
|
else
|
|
lmp->pix_offsets[idx] = 0;
|
|
|
|
/* if we finally have enough rows to display the entire list */
|
|
if (!lmp->get_all_records && ( lmp->pix_offsets[idx] + lmp->pix_heights[idx]
|
|
>= lmp->mlr_height))
|
|
break;
|
|
}
|
|
|
|
/*
|
|
although we have adjusted pix_offsets, and pix_heights, it is still
|
|
necessary to calculate the first and last fully visible rows
|
|
*/
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
If we have the first record and the list is not full, try getting
|
|
previous records.
|
|
*/
|
|
if ( have_rec && refused )
|
|
return fill_previous( lmp );
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_first */
|
|
/* returns row # of first record requested - i.e. for xi_scroll_rec, the */
|
|
/* row # of the new record. for scroll first with a percentage, the */
|
|
/* row # of that percentage. Normally 0, but with back-fill, can be */
|
|
/* a positive number. */
|
|
/*------------------------------------------------------------------------- */
|
|
static int lm_scroll_first( LM_DATA* lmp, lm_scroll_data* data )
|
|
{
|
|
int result = 0;
|
|
|
|
if ( (lmp->get_all_records || lmp->keep_all_records)
|
|
&& lmp->nbr_realized_rows > 0)
|
|
{
|
|
/* have_rec */
|
|
lmp->rrr_offset = -(int)((long)lmp->rrr_bottom * data->percent / 100);
|
|
calculate_visibles(lmp);
|
|
lmp->rrr_offset = -lmp->pix_offsets[lmp->first_fully_vis];
|
|
} else
|
|
{
|
|
if (lm_scroll_get_initial_rec( lmp, data, REC_AT_BOTTOM, LM_CB_GET_FIRST ))
|
|
result = lm_scroll_fill_forward( lmp, data->have_rec );
|
|
if (! lmp->get_all_records && ! lmp->keep_all_records)
|
|
{
|
|
int nbr_to_free, cnt, idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis - 1;
|
|
if ( nbr_to_free > 0 )
|
|
{
|
|
for (cnt = 0; cnt < nbr_to_free; cnt++)
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
do_rec_event(lmp, cnt, XIE_REC_FREE);
|
|
}
|
|
|
|
for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
|
|
row_copy(lmp, idx, idx - nbr_to_free);
|
|
result -= nbr_to_free;
|
|
adjust_rows(lmp, -nbr_to_free);
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
for (idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free; idx++, cnt++)
|
|
do_rec_event(lmp, idx, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_last */
|
|
/* returns row # of requested row */
|
|
/*------------------------------------------------------------------------- */
|
|
static int lm_scroll_last( LM_DATA* lmp, lm_scroll_data* data )
|
|
{ /* scroll last */
|
|
int result = 0;
|
|
|
|
if (lmp->get_all_records)
|
|
{
|
|
if (lmp->rrr_bottom < lmp->mlr_height)
|
|
lmp->rrr_offset = 0;
|
|
else
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->rrr_offset = lmp->mlr_height - lmp->rrr_bottom + 1;
|
|
CTOS_END;
|
|
#endif
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
if the page up does not make the first row editable, then
|
|
scroll the exact amount to make it editable
|
|
*/
|
|
if (-lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis])
|
|
{
|
|
int p;
|
|
|
|
p = lmp->pix_offsets[lmp->first_fully_vis] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles(lmp);
|
|
}
|
|
} else
|
|
{
|
|
data->percent = 0;
|
|
if (lm_scroll_get_initial_rec( lmp, data, REC_AT_TOP, LM_CB_GET_LAST ))
|
|
{
|
|
result = fill_previous( lmp );
|
|
/*
|
|
get one record after the last record, so that there will not be a
|
|
gray space below the last record, unless there are no more records.
|
|
*/
|
|
get_next_rec(lmp, FALSE);
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_calc_pixels */
|
|
/*------------------------------------------------------------------------- */
|
|
static void lm_scroll_calc_pixels( LM_DATA* lmp, lm_scroll_data* data )
|
|
{
|
|
/* calculate the max number of pixels that we should scroll */
|
|
if (data->nbr_pixels < 0)
|
|
{
|
|
int p;
|
|
|
|
data->nbr_pixels = max(data->nbr_pixels, lmp->rrr_offset);
|
|
lmp->rrr_offset -= data->nbr_pixels;
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
if the page up does not make the first row editable, then
|
|
scroll the exact amount to make it editable
|
|
*/
|
|
if (-lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis])
|
|
{
|
|
p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles(lmp);
|
|
}
|
|
} else
|
|
{
|
|
int p;
|
|
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
|
|
/*
|
|
following line puts row coming onto the list at the bottom of the list
|
|
completly on the list. new behavior is to have the row at the top of
|
|
the list to always be completely on the list.
|
|
nbr_pixels = min(nbr_pixels, lmp->rrr_bottom - lmp->mlr_height + lmp->rrr_offset);
|
|
*/
|
|
data->nbr_pixels = max(data->nbr_pixels, 0);
|
|
lmp->rrr_offset -= data->nbr_pixels;
|
|
calculate_visibles(lmp);
|
|
|
|
/*
|
|
if the page down does not make the first row editable, then
|
|
scroll the exact amount to make it editable
|
|
*/
|
|
if (-lmp->rrr_offset !=
|
|
lmp->pix_offsets[lmp->first_fully_vis])
|
|
{
|
|
p = lmp->pix_offsets[lmp->first_fully_vis - 1] +
|
|
lmp->rrr_offset;
|
|
data->nbr_pixels += p;
|
|
lmp->rrr_offset -= p;
|
|
calculate_visibles(lmp);
|
|
}
|
|
|
|
/*
|
|
if the page down leaves too much room at the bottom, then make more
|
|
rows visible.
|
|
*/
|
|
while (TRUE)
|
|
{
|
|
int h, pix_left;
|
|
|
|
if (lmp->first_fully_vis == 0)
|
|
break;
|
|
h = lmp->pix_heights[lmp->first_fully_vis - 1];
|
|
/*
|
|
Add 1 to pix_left (pixels left in mlr), because it is ok for the pixel
|
|
required for the rule at the bottom of the row to fall below the
|
|
visible portion of the list.
|
|
*/
|
|
pix_left = -(lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] +
|
|
lmp->rrr_offset - lmp->mlr_height) + 1;
|
|
if (pix_left < h)
|
|
break;
|
|
data->nbr_pixels -= h;
|
|
lmp->rrr_offset += h;
|
|
calculate_visibles(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_scroll_rct
|
|
lmp: current lmp
|
|
r: pointer to rectangle to be filled in
|
|
returns: r
|
|
-------------------------------------------------------------------------*/
|
|
static RCT* lm_get_scroll_rct(LM_DATA *lmp, RCT *r)
|
|
{
|
|
*r = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
r->right = r->left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
return r;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_middle */
|
|
/*------------------------------------------------------------------------- */
|
|
static int lm_scroll_middle( LM_DATA* lmp, lm_scroll_data* data,
|
|
BOOLEAN invalidate )
|
|
{
|
|
int recs_read;
|
|
|
|
recs_read = 0;
|
|
if (data->have_pixels)
|
|
recs_read = lm_make_rrr_room_pix(lmp, data->nbr_pixels, FALSE);
|
|
else if (data->nbr_lines)
|
|
{
|
|
recs_read = data->nbr_lines;
|
|
data->nbr_pixels = make_rrr_room_rows(lmp, &recs_read, FALSE);
|
|
}
|
|
lm_scroll_calc_pixels( lmp, data );
|
|
if (! lmp->get_all_records && ! lmp->keep_all_records)
|
|
{
|
|
int nbr_to_free, cnt, idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis;
|
|
if (nbr_to_free)
|
|
{
|
|
for (cnt = 0; cnt < nbr_to_free; cnt++)
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
do_rec_event(lmp, cnt, XIE_REC_FREE);
|
|
}
|
|
|
|
for (cnt = nbr_to_free; cnt < lmp->nbr_realized_rows; ++cnt)
|
|
row_copy(lmp, cnt, cnt - nbr_to_free);
|
|
adjust_rows(lmp, -nbr_to_free);
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
for (idx = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free;
|
|
idx++, cnt++)
|
|
do_rec_event(lmp, idx, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
|
|
for (idx = lmp->nbr_realized_rows;
|
|
idx < lmp->realized_rows_array_len;
|
|
++idx)
|
|
init_row(lmp, idx);
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
}
|
|
|
|
if (invalidate)
|
|
{
|
|
RCT r;
|
|
|
|
lm_get_scroll_rct(lmp, &r);
|
|
xi_set_clip(lmp->win, NULL);
|
|
if (data->nbr_pixels)
|
|
{
|
|
xvt_dwin_update(lmp->win);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lmp->update_cells_only = TRUE;
|
|
xi_scroll_rect(lmp->win, &r, 0, -data->nbr_pixels);
|
|
data->pixels_scrolled = data->nbr_pixels;
|
|
}
|
|
}
|
|
return recs_read;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------- */
|
|
/* lm_scroll_replace_focus */
|
|
/*------------------------------------------------------------------------- */
|
|
static void lm_scroll_replace_focus( LM_DATA* lmp, lm_scroll_data* data,
|
|
XI_OBJ* old_focus_obj, BOOLEAN same_cell )
|
|
{
|
|
/* put the focus back */
|
|
if (data->list_had_focus)
|
|
{
|
|
if (old_focus_obj->type == XIT_CELL)
|
|
{
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
lm_make_vis(lmp);
|
|
else
|
|
{
|
|
if (same_cell)
|
|
{
|
|
int col = old_focus_obj->v.cell.column;
|
|
int row, t, b;
|
|
int max_intersect, intersect_row;
|
|
XI_OBJ cell;
|
|
RCT cell_rct;
|
|
int tr;
|
|
|
|
max_intersect = 0;
|
|
intersect_row = -1;
|
|
tr = min(lmp->nbr_realized_rows, lmp->last_fully_vis + 1);
|
|
for (row = lmp->first_fully_vis; row < tr; ++row)
|
|
{
|
|
XI_MAKE_CELL(&cell, lmp->list_obj, (unsigned char)row,
|
|
(unsigned char)col);
|
|
xi_get_rect(&cell, &cell_rct);
|
|
t = max(cell_rct.top, data->focus_cell_rct.top);
|
|
b = min(cell_rct.bottom, data->focus_cell_rct.bottom);
|
|
if ((b - t) > max_intersect)
|
|
{
|
|
max_intersect = b - t;
|
|
intersect_row = row;
|
|
}
|
|
}
|
|
if (intersect_row != -1)
|
|
{
|
|
XI_MAKE_CELL(&cell, lmp->list_obj, (unsigned char)intersect_row,
|
|
(unsigned char)col);
|
|
xi_move_focus(&cell);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (data->scroll_type)
|
|
{
|
|
case XI_SCROLL_FIRST:
|
|
case XI_SCROLL_PGUP:
|
|
data->focus_row = lmp->first_fully_vis;
|
|
break;
|
|
case XI_SCROLL_LAST:
|
|
case XI_SCROLL_PGDOWN:
|
|
data->focus_row = lmp->last_fully_vis;
|
|
break;
|
|
default:
|
|
data->focus_row = clip( data->focus_row, lmp->first_fully_vis,
|
|
lmp->last_fully_vis);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
xi_move_focus(old_focus_obj);
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_scroll
|
|
lm: current lm
|
|
nbr_lines: nbr of lines to scroll, may be positive or negative, may be set
|
|
to XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, or XI_SCROLL_PGDN
|
|
percent: passed with XI_SCROLL_FIRST event
|
|
same_cell: sometimes the focus goes back onto the same cell. In other cases,
|
|
for instance, XI_SCROLL_FIRST, XI_SCROLL_LAST, XI_SCROLL_PGUP, and
|
|
XI_SCROLL_PGDN, we don't want to put the focus back on the same cell,
|
|
but instead, want to put the focus on the first or last fully visible
|
|
row.
|
|
invalidate: indicates whether to invalidate the list. This is only set to FALSE when
|
|
xi_scroll_internal is called when the interface is created.
|
|
rec: if have_rec is TRUE, then use rec for the first record, and don't do get first
|
|
-------------------------------------------------------------------------*/
|
|
int lm_scroll(LM_SCROLL_ARG *arg)
|
|
{
|
|
lm_scroll_data data;
|
|
int result = 0;
|
|
XI_OBJ* old_focus_obj;
|
|
LM_DATA* lmp = (LM_DATA*)arg->lm;
|
|
XI_OBJ* itf = lmp->itf_obj;
|
|
BOOLEAN invalidate = !itf->v.itf->half_baked;
|
|
|
|
if ((xi_get_attrib(lmp->list_obj) & XI_ATR_VISIBLE) == 0)
|
|
invalidate = FALSE;
|
|
lm_scroll_data_construct( lmp, &data, arg );
|
|
/*
|
|
If the focus is on the first row, and scrolling up, or the focus is on the
|
|
last row and scrolling down, return 0.
|
|
*/
|
|
if (lmp->get_all_records)
|
|
{
|
|
if (lmp->first_fully_vis == 0 && data.nbr_lines < 0)
|
|
return 0;
|
|
if (lmp->last_fully_vis == lmp->nbr_realized_rows &&
|
|
data.nbr_lines > 0 && data.nbr_lines < XI_SCROLL_PGUP)
|
|
return 0;
|
|
}
|
|
if (! lmp->itf_obj->v.itf->half_baked && invalidate)
|
|
xvt_dwin_update(lmp->win);
|
|
old_focus_obj = itf->v.itf->focus_obj;
|
|
if (!lm_scroll_remove_focus( lmp, &data, old_focus_obj ))
|
|
return 0;
|
|
lm_scroll_calc_lines( lmp, &data );
|
|
if (data.is_first_or_last)
|
|
{
|
|
if (data.nbr_lines == XI_SCROLL_FIRST)
|
|
result = lm_scroll_first( lmp, &data );
|
|
else
|
|
result = lm_scroll_last( lmp, &data );
|
|
if (invalidate)
|
|
{
|
|
RCT r;
|
|
|
|
xi_invalidate_rect(lmp->win, lm_get_scroll_rct(lmp, &r));
|
|
}
|
|
} else
|
|
{
|
|
result = lm_scroll_middle( lmp, &data, invalidate );
|
|
arg->pixels_scrolled = data.pixels_scrolled;
|
|
}
|
|
|
|
lm_scroll_replace_focus( lmp, &data, old_focus_obj, arg->same_cell );
|
|
if (lmp->row_focus_border && lmp->nbr_realized_rows > 0)
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_vert_scrolled;
|
|
BOOLEAN is_hscrolled;
|
|
BOOLEAN is_vis;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_vert_scrolled);
|
|
is_vis = lm_is_cell_visible( lmp, focus_row, focus_column, TRUE,
|
|
&is_hscrolled);
|
|
if ((is_vis || is_hscrolled) && !is_vert_scrolled )
|
|
{
|
|
lm_redraw_row(lmp, focus_row, FALSE);
|
|
if ( lmp->txt != NULL )
|
|
txt_redraw(lmp->txt, FALSE);
|
|
}
|
|
}
|
|
do_scroll_bar( lmp->list_obj->v.list );
|
|
if (invalidate)
|
|
xvt_dwin_update( lmp->win );
|
|
return result;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_text
|
|
lm: current lm
|
|
s: string to set
|
|
row:
|
|
column:
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_text(LM lm, char *s, int row, int column, BOOLEAN v_scrolled )
|
|
{
|
|
BOOLEAN was_suspended = FALSE;
|
|
LM_COLUMN_DATA *lmcd;
|
|
RCT rct;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
lmcd = lmp->lm_column_data[column];
|
|
if (row == LM_HEADING_TEXT)
|
|
{
|
|
lmcd->heading_text = (char *)xi_tree_realloc(lmcd->heading_text,
|
|
strlen(s) + 1);
|
|
strcpy(lmcd->heading_text, s);
|
|
lm_get_cell_rect(&rct, lm, 1, column, FALSE, TRUE);
|
|
rct.top = lmp->pix_hdr_bottom -
|
|
max(lmp->pix_cell_height, lmp->min_heading_height +
|
|
2 * BORDER_WIDTH);
|
|
rct.bottom = lmp->pix_hdr_bottom;
|
|
if ( (lmp->attrib & LM_ATR_VISIBLE) != 0)
|
|
xi_invalidate_rect(lmp->win, &rct);
|
|
} else
|
|
{
|
|
int new_row_height;
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scroll;
|
|
|
|
if (lm_cell_has_focus(lmp, row, column, v_scrolled))
|
|
{
|
|
was_suspended = TRUE;
|
|
lm_make_invis(lmp);
|
|
}
|
|
if (!v_scrolled)
|
|
tgstrncpy( lmp->buffer[row] + lmcd->text_offset, s, lmcd->text_size);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scroll);
|
|
if (lmp->txt_is_invisible && row == focus_row && column == focus_column)
|
|
{
|
|
int len;
|
|
|
|
len = strlen(s) + 1;
|
|
if (lmp->focus_cell_text)
|
|
lmp->focus_cell_text = (char *)xi_tree_realloc(lmp->focus_cell_text, len);
|
|
else
|
|
lmp->focus_cell_text = (char *)xi_tree_malloc(len, lmp);
|
|
strcpy(lmp->focus_cell_text, s);
|
|
if (lmp->lm_column_data[column]->attrib | XI_ATR_AUTOSELECT)
|
|
{
|
|
lmp->focus_cell_ip1 = 0;
|
|
lmp->focus_cell_ip2 = strlen(s);
|
|
}
|
|
else
|
|
{
|
|
lmp->focus_cell_ip1 = 0;
|
|
lmp->focus_cell_ip2 = 0;
|
|
}
|
|
}
|
|
if (!v_scrolled)
|
|
{
|
|
new_row_height = lm_calculate_row_height(lmp, row);
|
|
if (new_row_height != lmp->pix_heights[row])
|
|
lm_set_row_height(lm, row, new_row_height, FALSE, 0, FALSE);
|
|
if (LMP(lm)->attrib & XI_ATR_VISIBLE)
|
|
redraw_cell(lm, row, column, FALSE );
|
|
}
|
|
if (was_suspended)
|
|
lm_make_vis(lmp);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: next cell
|
|
lm: current lm
|
|
c: character causing the focus to change
|
|
next_row: int pointer to be filled in with next row
|
|
next_col: int pointer to be filled in with next column
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
next_cell(LM lm, int c, int *next_row, int *next_col)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
switch (c)
|
|
{
|
|
case K_BTAB:
|
|
--*next_col;
|
|
if (*next_col < 0)
|
|
{
|
|
*next_col = lmp->nbr_columns - 1;
|
|
if ((lmp->attrib & LM_ATR_TABWRAP))
|
|
--*next_row;
|
|
}
|
|
break;
|
|
case '\t':
|
|
++*next_col;
|
|
if (*next_col >= lmp->nbr_columns)
|
|
{
|
|
*next_col = 0;
|
|
if ((lmp->attrib & LM_ATR_TABWRAP))
|
|
++*next_row;
|
|
}
|
|
break;
|
|
case K_UP:
|
|
--*next_row;
|
|
break;
|
|
case K_DOWN:
|
|
++*next_row;
|
|
break;
|
|
case K_WLEFT:
|
|
case K_LEFT:
|
|
--*next_col;
|
|
if (*next_col < 0)
|
|
*next_col = lmp->nbr_columns - 1;
|
|
break;
|
|
case K_WRIGHT:
|
|
case K_RIGHT:
|
|
++*next_col;
|
|
if (*next_col >= lmp->nbr_columns)
|
|
*next_col = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_CHAR, LM_CB_CHANGE, LM_CB_FOCUS, LM_CB_REC_ALLOCATE,
|
|
LM_CB_REC_FREE
|
|
row: relevent row
|
|
column: relevent column
|
|
ep: xvt event that caused the LM event, used to pass on shift and control
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
do_lm_cb(LM lm, LM_CB_TYPE cb_reason, int row, int column, EVENT *ep, int *percent, int pixels)
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
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;
|
|
switch (cb_reason)
|
|
{
|
|
case LM_CB_REC_ALLOCATE:
|
|
lm_cb_data.v.rec_allocate.record = lmp->recs[row];
|
|
if (lm_cb_data.v.rec_allocate.record)
|
|
return FALSE;
|
|
break;
|
|
case LM_CB_REC_FREE:
|
|
lm_cb_data.v.rec_free.record = lmp->recs[row];
|
|
if (! lm_cb_data.v.rec_allocate.record)
|
|
return FALSE;
|
|
break;
|
|
case LM_CB_CHAR:
|
|
lm_cb_data.v.chr.ch = ep->v.chr.ch;
|
|
lm_cb_data.v.chr.shift = ep->v.chr.shift;
|
|
lm_cb_data.v.chr.control = ep->v.chr.control;
|
|
lm_cb_data.v.chr.is_paste = FALSE;
|
|
lm_cb_data.v.chr.refused = FALSE;
|
|
break;
|
|
case LM_CB_CELL_BTN:
|
|
lm_cb_data.v.cell_btn.shift = ep->v.chr.shift;
|
|
lm_cb_data.v.cell_btn.control = ep->v.chr.control;
|
|
break;
|
|
case LM_CB_GET_PERCENT:
|
|
lm_cb_data.v.get_percent.record = lmp->recs[row];
|
|
break;
|
|
case LM_CB_ROW_SIZE:
|
|
lm_cb_data.v.row_size.new_row_height = pixels;
|
|
break;
|
|
default:
|
|
lm_cb_data.v.refused = FALSE;
|
|
break;
|
|
}
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
/* retval = FALSE if event refused */
|
|
switch (cb_reason)
|
|
{
|
|
case LM_CB_REC_ALLOCATE:
|
|
lmp->recs[row] = lm_cb_data.v.rec_allocate.record;
|
|
return FALSE;
|
|
case LM_CB_REC_FREE:
|
|
lmp->recs[row] = 0L;
|
|
return FALSE;
|
|
case LM_CB_CHAR:
|
|
if (! lm_cb_data.v.chr.refused)
|
|
ep->v.chr.ch = lm_cb_data.v.chr.ch;
|
|
return (! lm_cb_data.v.chr.refused);
|
|
case LM_CB_GET_PERCENT:
|
|
*percent = lm_cb_data.v.get_percent.percent;
|
|
return FALSE;
|
|
case LM_CB_ROW_SIZE:
|
|
return (! lm_cb_data.v.row_size.refused);
|
|
default:
|
|
return (! lm_cb_data.v.refused);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_get
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_GET_FIRST, LM_CB_GET_LAST, LM_CB_GET_NEXT,
|
|
LM_CB_GET_PREV
|
|
spec_rec:
|
|
data_rec:
|
|
percent:
|
|
returns: TRUE if event refused
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
do_lm_cb_get(LM lm, LM_CB_TYPE cb_reason, long *spec_rec,
|
|
long *data_rec, int percent, COLOR *color, unsigned long *attrib, int *row_height)
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
lm_cb_data.cid = lmp->cid;
|
|
lm_cb_data.win = lmp->win;
|
|
lm_cb_data.v.rec_request.spec_rec = *spec_rec;
|
|
lm_cb_data.v.rec_request.data_rec = *data_rec;
|
|
lm_cb_data.v.rec_request.percent = percent;
|
|
lm_cb_data.v.rec_request.color = *color;
|
|
lm_cb_data.v.rec_request.attrib = *attrib;
|
|
lm_cb_data.v.rec_request.refused = FALSE;
|
|
(*lmp->lm_cb)(&lm_cb_data);
|
|
/* retval = FALSE if event refused */
|
|
if (! lm_cb_data.v.rec_request.refused)
|
|
{
|
|
*data_rec = lm_cb_data.v.rec_request.data_rec;
|
|
*color = lm_cb_data.v.rec_request.color;
|
|
*attrib = lm_cb_data.v.rec_request.attrib;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
*row_height = lm_cb_data.v.rec_request.row_height;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
*row_height = 0;
|
|
CTOS_END;
|
|
#endif
|
|
if ( lm_cb_data.v.rec_request.has_focus
|
|
&& xi_get_pref(XI_PREF_UNUSED_PREFERENCE) )
|
|
{
|
|
if ( lmp->focus_rec )
|
|
{
|
|
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);
|
|
}
|
|
lmp->focus_rec = *data_rec;
|
|
}
|
|
}
|
|
return lm_cb_data.v.rec_request.refused;
|
|
}
|
|
|
|
|
|
static void calculate_next_cell( LM_DATA *lmp, int *next_row, int *next_col,
|
|
BOOLEAN *use_key, EVENT *ep, BOOLEAN *off_top,
|
|
BOOLEAN *off_bottom)
|
|
{
|
|
BOOLEAN keep_looking;
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
keep_looking = *use_key;
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
*next_row = focus_row;
|
|
*next_col = focus_column;
|
|
while (keep_looking)
|
|
{
|
|
next_cell((LM)lmp, ep->v.chr.ch, next_row, next_col);
|
|
if (*next_row < 0)
|
|
{
|
|
/* off top logic */
|
|
if (lmp->get_all_records)
|
|
{
|
|
*use_key = FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
keep_looking = FALSE;
|
|
*off_top = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (*next_row >= lmp->nbr_realized_rows)
|
|
{
|
|
/* off bottom logic */
|
|
if (lmp->get_all_records)
|
|
{
|
|
*use_key = FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
keep_looking = FALSE;
|
|
*off_bottom = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if ( CELL_IS_ENABLED(lmp, *next_row, *next_col)
|
|
&& !CELL_IS_SELECTABLE(lmp, *next_row, *next_col)
|
|
&& lmp->cell_data[*next_row][*next_col].icon_rid
|
|
== 0 )
|
|
{
|
|
/* found a valid cell */
|
|
keep_looking = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void adjust_rows(LM_DATA *lmp, int delta)
|
|
{
|
|
XI_OBJ *focus_obj;
|
|
|
|
focus_obj = lmp->itf_obj->v.itf->focus_obj;
|
|
if (focus_obj && focus_obj->cid == lmp->cid)
|
|
{
|
|
if (focus_obj && focus_obj->type == XIT_CELL)
|
|
{
|
|
focus_obj->v.cell.row += delta;
|
|
if ( !focus_obj->v.cell.is_vert_scrolled
|
|
&& (long)focus_obj->v.cell.row >= (long)lmp->nbr_realized_rows )
|
|
focus_obj->v.cell.is_vert_scrolled = TRUE;
|
|
}
|
|
if (focus_obj && focus_obj->type == XIT_ROW)
|
|
focus_obj->v.row += delta;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: navigate_char_event
|
|
lm: current lm
|
|
ep: xvt event
|
|
returns: TRUE if key was used.
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
navigate_char_event(LM lm, EVENT *ep)
|
|
{
|
|
BOOLEAN use_key = FALSE;
|
|
BOOLEAN off_top = FALSE;
|
|
BOOLEAN off_bottom = FALSE;
|
|
BOOLEAN should_redraw = TRUE;
|
|
int next_row, next_col, row_inc, col_inc;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
if (!lm_list_has_focus(lmp))
|
|
return FALSE;
|
|
switch (ep->v.chr.ch) {
|
|
case '\t':
|
|
case K_BTAB:
|
|
case K_UP:
|
|
case K_DOWN:
|
|
use_key = TRUE;
|
|
break;
|
|
case K_WRIGHT:
|
|
case K_WLEFT:
|
|
case K_LEFT:
|
|
case K_RIGHT:
|
|
if ((lmp->attrib & LM_ATR_NAVIGATE) || ep->v.chr.control)
|
|
use_key = TRUE;
|
|
break;
|
|
}
|
|
calculate_next_cell(lmp, &next_row, &next_col,
|
|
&use_key, ep, &off_top, &off_bottom);
|
|
if (use_key)
|
|
{
|
|
XI_LIST_DATA *list_data;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
if (off_top || off_bottom)
|
|
{
|
|
int old_row_height, focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
BOOLEAN do_redraw;
|
|
|
|
lm_make_invis(lmp);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
old_row_height = lmp->pix_heights[focus_row];
|
|
do_redraw = (lm_calculate_row_height(lmp, focus_row) != old_row_height);
|
|
if (off_top)
|
|
make_room_rows(lmp, -1, do_redraw);
|
|
else
|
|
make_room_rows(lmp, 1, do_redraw);
|
|
/*
|
|
calculate next cell again, because the desired next cell
|
|
may have changed.
|
|
*/
|
|
calculate_next_cell( lmp, &next_row, &next_col, &use_key, ep, &off_top,
|
|
&off_bottom);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
row_inc = next_row - focus_row;
|
|
col_inc = next_col - focus_column;
|
|
next_row = focus_row + row_inc;
|
|
if (next_row >= lmp->nbr_realized_rows)
|
|
next_row = lmp->nbr_realized_rows - 1;
|
|
if (next_row < 0)
|
|
next_row = 0;
|
|
next_col = focus_column + col_inc;
|
|
|
|
while (TRUE)
|
|
{
|
|
if (CELL_IS_ENABLED(lm, next_row, next_col) &&
|
|
! CELL_IS_SELECTABLE(lm, next_row, next_col))
|
|
break;
|
|
next_cell(lm, off_bottom ? '\t' :
|
|
K_BTAB, &next_row, &next_col);
|
|
}
|
|
if (list_data->vert_sync_list &&
|
|
! list_data->scrolling_in_progress)
|
|
{
|
|
XI_OBJ *other_list;
|
|
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj(lmp->itf_obj,
|
|
list_data->vert_sync_list);
|
|
if (other_list)
|
|
xi_scroll(other_list, off_top ? -1 : 1);
|
|
xvt_dwin_update(lmp->win);
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
xvt_dwin_update(lmp->win);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
if (focus_row > lmp->last_fully_vis)
|
|
{
|
|
lm_force_vis(lmp);
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
next_row = focus_row;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
}
|
|
lm_make_vis(lmp);
|
|
}
|
|
|
|
else if (next_row < lmp->first_fully_vis || next_row > lmp->last_fully_vis)
|
|
{
|
|
if (list_data->vert_sync_list &&
|
|
! list_data->scrolling_in_progress)
|
|
{
|
|
XI_OBJ *other_list;
|
|
|
|
list_data->scrolling_in_progress = TRUE;
|
|
other_list = xi_get_obj(lmp->itf_obj,
|
|
list_data->vert_sync_list);
|
|
if (other_list)
|
|
xi_scroll(other_list,
|
|
next_row < lmp->first_fully_vis ? -1 : 1);
|
|
xvt_dwin_update(lmp->win);
|
|
list_data->scrolling_in_progress = FALSE;
|
|
}
|
|
}
|
|
|
|
if (next_row < lmp->first_fully_vis)
|
|
{
|
|
int delta, idx2, pix2, old_pix, cnt, height;
|
|
RCT tmp_rct;
|
|
|
|
if (lmp->first_fully_vis == 0)
|
|
return use_key;
|
|
lm_make_invis(lmp);
|
|
idx2 = lmp->first_fully_vis - 1;
|
|
pix2 = lmp->pix_offsets[idx2];
|
|
old_pix = -lmp->rrr_offset;
|
|
delta = old_pix - pix2;
|
|
lmp->rrr_offset += delta;
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lm_get_scroll_rct(lmp, &tmp_rct);
|
|
|
|
/*
|
|
calculate lmp->update_rows_at_top to speed up scrolling the list
|
|
*/
|
|
height = delta;
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt)
|
|
height -= lmp->pix_heights[cnt];
|
|
lmp->update_rows_at_top = cnt;
|
|
|
|
xi_scroll_rect(lmp->win, &tmp_rct, 0, delta);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
lm_make_vis(lmp);
|
|
should_redraw = FALSE;
|
|
}
|
|
|
|
if (next_row > lmp->last_fully_vis)
|
|
{
|
|
int delta, delta2, diff, cnt, height, first, old_row_height, focus_row;
|
|
int focus_column, new_row_height;
|
|
BOOLEAN v_scrolled;
|
|
RCT tmp_rct;
|
|
|
|
if (lmp->last_fully_vis >= lmp->nbr_realized_rows)
|
|
return use_key;
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
old_row_height = lmp->pix_heights[focus_row];
|
|
lm_make_invis(lmp);
|
|
delta = lmp->pix_heights[lmp->first_fully_vis];
|
|
lm_make_rrr_room_pix(lmp, delta, TRUE);
|
|
if (lmp->last_fully_vis + 1 < lmp->nbr_realized_rows)
|
|
delta = max(delta, lmp->pix_heights[lmp->last_fully_vis + 1]);
|
|
lmp->rrr_offset -= delta;
|
|
calculate_pix_offsets(lmp, TRUE);
|
|
calculate_visibles(lmp);
|
|
if (-lmp->rrr_offset != lmp->pix_offsets[lmp->first_fully_vis])
|
|
{
|
|
delta2 = lmp->pix_offsets[lmp->first_fully_vis] +
|
|
lmp->rrr_offset;
|
|
lmp->rrr_offset -= delta2;
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
calculate_visibles(lmp);
|
|
delta += delta2;
|
|
}
|
|
diff = lmp->pix_offsets[lmp->nbr_realized_rows - 1] +
|
|
lmp->pix_heights[lmp->nbr_realized_rows - 1] -
|
|
lmp->mlr_height + lmp->rrr_offset;
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
if (diff < 0)
|
|
lm_make_rrr_room_pix(lmp, -diff, FALSE);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lm_get_scroll_rct(lmp, &tmp_rct);
|
|
|
|
/*
|
|
calculate lmp->update_rows_at_bottom to speed up scrolling the list
|
|
*/
|
|
height = lmp->mlr.bottom - lmp->mlr.top - delta;
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows && height > 0; ++cnt)
|
|
height -= lmp->pix_heights[cnt];
|
|
first = cnt - 1;
|
|
height += delta;
|
|
for (;height > 0; ++cnt)
|
|
height -= lmp->pix_heights[cnt];
|
|
lmp->update_rows_at_bottom = cnt - first;
|
|
|
|
/*
|
|
scroll the list
|
|
*/
|
|
xi_scroll_rect(lmp->win, &tmp_rct, 0, -delta);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
|
|
/*
|
|
if the row height changed, then we need to redraw the row
|
|
*/
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
new_row_height = lmp->pix_heights[focus_row];
|
|
if (new_row_height != old_row_height)
|
|
{
|
|
lm_redraw_row(lmp, focus_row, FALSE );
|
|
calculate_pix_offsets(lmp, TRUE );
|
|
}
|
|
should_redraw = FALSE;
|
|
}
|
|
|
|
if (! lmp->get_all_records && ! lmp->keep_all_records)
|
|
{
|
|
int nbr_to_free, cnt, i, idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis;
|
|
if (nbr_to_free > 0)
|
|
{
|
|
for (cnt = 0; cnt < nbr_to_free; cnt++)
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
do_rec_event(lmp, cnt, XIE_REC_FREE);
|
|
}
|
|
|
|
for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
|
|
row_copy(lmp, idx, idx - nbr_to_free);
|
|
adjust_rows(lmp, -nbr_to_free);
|
|
|
|
/*
|
|
calculate next cell again, because the desired next cell
|
|
may have changed.
|
|
*/
|
|
calculate_next_cell(lmp, &next_row, &next_col,
|
|
&use_key, ep, &off_top, &off_bottom);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_pix_offsets(lmp, should_redraw );
|
|
calculate_visibles(lmp);
|
|
}
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
if (nbr_to_free > 0)
|
|
{
|
|
for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
|
|
i++, cnt++)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
}
|
|
|
|
calculate_pix_offsets(lmp, should_redraw );
|
|
|
|
lm_make_rrr_room_pix(lmp, 0, FALSE );
|
|
}
|
|
do_lm_cb(lm, LM_CB_FOCUS, next_row, next_col, NULL, NULL, 0);
|
|
}
|
|
return use_key;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_insert_row
|
|
lm: current lm
|
|
row: row to insert
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_insert_row(LM lm, int row)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
xvt_errmsg_sig_if(!(! lmp->get_all_records), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20919", 20919,
|
|
"xi_insert_row called with get_all_records set to TRUE");
|
|
if (xi_move_focus(lmp->itf_obj))
|
|
{
|
|
if (row > 0 && lmp->nbr_realized_rows)
|
|
{
|
|
int idx, row_height, pix;
|
|
RCT r, row_rect;
|
|
BOOLEAN is_visible;
|
|
|
|
row = min(row, lmp->nbr_realized_rows);
|
|
|
|
pix = lmp->pix_offsets[row - 1] + lmp->pix_heights[row - 1]
|
|
+ 1;
|
|
is_visible = (pix <= lmp->mlr_height - lmp->rrr_offset);
|
|
|
|
if (is_visible || lmp->get_all_records)
|
|
{
|
|
LM_CELL_DATA *lmcdp;
|
|
int i;
|
|
|
|
make_rec_available(lmp, REC_AT_BOTTOM, FALSE, FALSE);
|
|
for (i = lmp->nbr_realized_rows - 2; i >= row; i--)
|
|
row_copy(lmp, i, i + 1);
|
|
idx = row;
|
|
lmcdp = lmp->cell_data[idx];
|
|
for (i = 0; i < lmp->nbr_columns; ++i, ++lmcdp)
|
|
memset((char *)lmcdp, '\0', sizeof(LM_CELL_DATA));
|
|
lmp->recs[idx] = 0L;
|
|
do_rec_event(lmp, idx, XIE_REC_ALLOCATE);
|
|
if (do_lm_cb_get((LM)lmp, LM_CB_GET_NEXT,
|
|
&lmp->recs[idx - 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height))
|
|
{
|
|
do_rec_event(lmp, lmp->nbr_realized_rows - 1, XIE_REC_FREE);
|
|
for (i = row; i < lmp->nbr_realized_rows - 2; ++i)
|
|
row_copy(lmp, i + 1, i);
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
if (row_height)
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
|
|
lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE);
|
|
}
|
|
|
|
if (is_visible)
|
|
{
|
|
lm_get_scroll_rct(lmp, &r);
|
|
row_height = lm_calculate_row_height(lmp, idx);
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
lm_get_rect(lm, LM_ROW, idx, &row_rect);
|
|
r.top = row_rect.top;
|
|
xi_scroll_rect(lmp->win, &r, 0, row_height);
|
|
}
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
int idx, row_height, cnt;
|
|
RCT r;
|
|
BOOLEAN need_first = ! lmp->nbr_realized_rows;
|
|
|
|
make_rec_available(lmp, REC_AT_TOP, TRUE, FALSE);
|
|
idx = 0;
|
|
if (do_lm_cb_get((LM)lmp, need_first ? LM_CB_GET_FIRST : LM_CB_GET_PREV,
|
|
&lmp->recs[idx + 1], &lmp->recs[idx], 0, &lmp->row_colors[idx],
|
|
&lmp->row_attribs[idx], &row_height))
|
|
{
|
|
do_rec_event(lmp, 0, XIE_REC_FREE);
|
|
for (cnt = 1; cnt < lmp->nbr_realized_rows; ++cnt)
|
|
row_copy(lmp, cnt, cnt - 1);
|
|
--lmp->nbr_realized_rows;
|
|
return FALSE;
|
|
}
|
|
|
|
if (row_height)
|
|
{
|
|
lmp->pix_heights[idx] = row_height;
|
|
lmp->set_heights[idx] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lmp->pix_heights[idx] = lm_calculate_row_height(lmp, idx);
|
|
lmp->set_heights[idx] = FALSE;
|
|
}
|
|
lm_invalidate_rows_internal((LM)lmp, idx, idx, FALSE, -1, TRUE );
|
|
lm_get_scroll_rct(lmp, &r);
|
|
row_height = lm_calculate_row_height(lmp, idx);
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
xi_scroll_rect(lmp->win, &r, 0, row_height);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete_row
|
|
lm: current lm
|
|
row: row to delete
|
|
-------------------------------------------------------------------------*/
|
|
BOOLEAN
|
|
lm_delete_row(LM lm, int row)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
xvt_errmsg_sig_if(!(! lmp->get_all_records), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20920", 20920,
|
|
"xi_delete_row called with get_all_records set to TRUE");
|
|
if (xi_move_focus(lmp->itf_obj))
|
|
{
|
|
int pix_height, i;
|
|
int recs_read;
|
|
RCT r, row_rct;
|
|
|
|
pix_height = lmp->pix_heights[row];
|
|
lm_get_rect(lm, LM_ROW, row, &row_rct);
|
|
do_rec_event(lmp, row, XIE_REC_FREE);
|
|
for (i = row + 1; i < lmp->nbr_realized_rows; i++)
|
|
row_copy(lmp, i, i - 1);
|
|
lmp->recs[--lmp->nbr_realized_rows] = 0;
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
recs_read = lm_make_rrr_room_pix(lmp, pix_height, FALSE);
|
|
pix_height = max(pix_height, 0);
|
|
lm_get_scroll_rct(lmp, &r);
|
|
r.top = max(r.top, row_rct.top);
|
|
if (recs_read)
|
|
xi_invalidate_rect( lmp->win, &r );
|
|
else
|
|
xi_scroll_rect(lmp->win, &r, 0, -pix_height);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_row_height
|
|
lm: current lm
|
|
row: row to set
|
|
height: height
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_row_height(LM lm, int row, int height, BOOLEAN set_height,
|
|
int old_height, BOOLEAN only_update)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
int idx = row;
|
|
int old_row_height, delta;
|
|
RCT r, r2;
|
|
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
if (only_update)
|
|
old_row_height = old_height;
|
|
else
|
|
{
|
|
old_row_height = lmp->pix_heights[idx];
|
|
lmp->pix_heights[idx] = height;
|
|
lmp->set_heights[idx] = set_height;
|
|
}
|
|
calculate_pix_offsets(lmp, FALSE );
|
|
|
|
/* Adjust row information */
|
|
if (! lmp->get_all_records && ! lmp->keep_all_records)
|
|
{
|
|
if (height < old_row_height)
|
|
lm_make_rrr_room_pix(lmp, 0, FALSE);
|
|
else
|
|
{ /* Free rows at bottom */
|
|
int i, cnt;
|
|
int nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
for (i = lmp->nbr_realized_rows - nbr_to_free,
|
|
cnt = 0; cnt < nbr_to_free; i++, cnt++)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
if (nbr_to_free > 0)
|
|
lmp->nbr_realized_rows -= nbr_to_free;
|
|
}
|
|
}
|
|
lm_get_scroll_rct(lmp, &r);
|
|
if (row < lmp->nbr_realized_rows - 1)
|
|
{
|
|
r.top = lmp->pix_offsets[idx + 1] + lmp->rrr_offset + lmp->mlr.top;
|
|
delta = height - old_row_height;
|
|
xi_scroll_rect(lmp->win, &r, 0, delta);
|
|
}
|
|
lm_get_rect(lm, LM_ROW, row, &r);
|
|
if (row == lmp->nbr_realized_rows - 1)
|
|
{
|
|
r2 = r;
|
|
r2.top = r2.bottom;
|
|
r2.bottom = lmp->mlr.bottom;
|
|
if (r2.top < r2.bottom)
|
|
xi_invalidate_rect(lmp->win, &r2);
|
|
}
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_list_size
|
|
lm: current lm
|
|
height: new height
|
|
width: new width
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_list_size(LM lm, int height, int width)
|
|
{
|
|
LM_DATA* lmp = (LM_DATA *)lm;
|
|
RCT vert_scrollbar_rect;
|
|
RCT horz_scrollbar_rect;
|
|
RCT ir, old_rct;
|
|
int old_height;
|
|
int col_offset;
|
|
int max_row_height;
|
|
int row_height;
|
|
int heading_height;
|
|
int i;
|
|
XI_LIST_DATA* list_data;
|
|
int nbr_to_free, cnt;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
xi_get_rect(lmp->list_obj, &old_rct);
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
xi_get_hsb_rect(lmp->list_obj, &horz_scrollbar_rect);
|
|
xi_get_sb_rect(lmp->list_obj, &vert_scrollbar_rect);
|
|
|
|
/* calculate minumum height */
|
|
{
|
|
int leading;
|
|
int ascent;
|
|
int descent;
|
|
int char_width;
|
|
int font_height;
|
|
|
|
xi_get_font_metrics_font(lmp->font, &leading, &ascent, &descent,
|
|
&char_width);
|
|
font_height = leading + ascent + descent;
|
|
max_row_height = lmp->max_lines_in_cell * font_height + RULE_Y_OFFSET_TOP
|
|
+ RULE_Y_OFFSET_BOTTOM + RULE_WIDTH_H;
|
|
}
|
|
for (i = 0; i < lmp->nbr_realized_rows; ++i)
|
|
{
|
|
row_height = lmp->pix_heights[i];
|
|
max_row_height = max(row_height, max_row_height);
|
|
}
|
|
heading_height = (lmp->pix_row1_top - lmp->rct.top) + BORDER_WIDTH;
|
|
i = max_row_height + heading_height + (horz_scrollbar_rect.bottom
|
|
- horz_scrollbar_rect.top);
|
|
height = max(height, i);
|
|
|
|
/* calculate new list metrics */
|
|
lmp->rct.bottom = lmp->rct.top + height
|
|
- ((list_data->hsb_win) ? (horz_scrollbar_rect.bottom
|
|
- horz_scrollbar_rect.top - 1)
|
|
: 0);
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
CTOS_END;
|
|
#else
|
|
CTOS_IS_PM;
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
old_height = lmp->mlr_height;
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
calculate_pix_offsets( lmp, FALSE );
|
|
if (! lmp->get_all_records)
|
|
{
|
|
/* fill in with more records */
|
|
if (old_height < lmp->mlr_height)
|
|
lm_make_rrr_room_pix(lmp, lmp->mlr_height - old_height, FALSE);
|
|
}
|
|
|
|
calculate_visibles(lmp);
|
|
|
|
if (width && lmp->pixel_width)
|
|
{
|
|
int i, min_width, max_col_width;
|
|
|
|
max_col_width = 0;
|
|
for (i = lmp->fixed_columns; i < lmp->nbr_columns; ++i)
|
|
max_col_width = max(lmp->lm_column_data[i]->pix_width, max_col_width);
|
|
max_col_width += BORDER_WIDTH;
|
|
min_width = (lmp->vir_left - lmp->rct.left) + max_col_width
|
|
+ (vert_scrollbar_rect.right - vert_scrollbar_rect.left)
|
|
+ BORDER_WIDTH + 2 * col_offset;
|
|
if ( list_data->sb_win )
|
|
min_width += ( vert_scrollbar_rect.right
|
|
- vert_scrollbar_rect.left );
|
|
width = max(min_width, width);
|
|
|
|
lmp->pixel_width = width - (2 * BORDER_WIDTH);
|
|
if ( list_data->sb_win )
|
|
lmp->pixel_width -= ( vert_scrollbar_rect.right
|
|
- vert_scrollbar_rect.left - 1 );
|
|
lmp->vir_right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
}
|
|
|
|
/* move scroll bars */
|
|
list_data->have_sb_rct = FALSE;
|
|
list_data->have_hsb_rct = FALSE;
|
|
xi_move_list_scroll_bar(lmp->list_obj);
|
|
xi_move_list_hscroll_bar(lmp->list_obj);
|
|
lm_set_hscroll_range(lm);
|
|
|
|
ir = lmp->rct;
|
|
xi_get_hsb_rect(lmp->list_obj, &horz_scrollbar_rect);
|
|
ir.bottom = horz_scrollbar_rect.bottom + BORDER_WIDTH;
|
|
xi_get_sb_rect(lmp->list_obj, &vert_scrollbar_rect);
|
|
ir.right = vert_scrollbar_rect.right + BORDER_WIDTH;
|
|
ir.right = max(ir.right, old_rct.right);
|
|
ir.bottom = max(ir.bottom, old_rct.bottom);
|
|
xi_invalidate_rect(lmp->win, &ir);
|
|
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
|
|
if (width && lmp->pixel_width)
|
|
{
|
|
/* calculate visible columns */
|
|
i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
|
|
if (i < lmp->first_vis)
|
|
{
|
|
xvt_dwin_update(lmp->win);
|
|
lm_hscroll(lm, lmp->first_vis - i, 0);
|
|
} else
|
|
{
|
|
lm_calc_last_vis(lmp);
|
|
lm_set_hscroll_bar((LM)lmp);
|
|
}
|
|
}
|
|
|
|
if (! lmp->get_all_records)
|
|
{
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
|
|
i++, cnt++)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_visibles(lmp);
|
|
}
|
|
}
|
|
|
|
void
|
|
lm_recalc_metrics(LM lm)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
int leading, ascent, descent, font_height, mch, i;
|
|
WINDOW win;
|
|
LM_COLUMN_DATA * * lmcdp;
|
|
int old_char_width;
|
|
XI_LIST_DATA *list_data;
|
|
PNT pnt;
|
|
RCT rct;
|
|
|
|
list_data = lmp->list_obj->v.list;
|
|
pnt = list_data->xi_pnt;
|
|
xi_fu_to_pu(lmp->itf_obj, &pnt, 1);
|
|
lmp->rct.top = pnt.v;
|
|
lmp->rct.left = pnt.h;
|
|
|
|
if (! lmp->resize_with_window)
|
|
{
|
|
lmp->pixel_width = list_data->width *
|
|
xi_get_fu_width(lmp->itf_obj) / XI_FU_MULTIPLE;
|
|
}
|
|
|
|
*lmp->font = *lmp->itf_obj->v.itf->font;
|
|
win = lmp->win;
|
|
xi_set_xvt_font(win, lmp->font, FALSE);
|
|
xi_get_font_metrics(win, &leading, &ascent, &descent);
|
|
lmp->leading = leading;
|
|
lmp->ascent = ascent;
|
|
lmp->descent = descent;
|
|
font_height = lmp->ascent + lmp->leading + lmp->descent;
|
|
lmp->pix_cell_height = font_height + (RULE_Y_OFFSET_TOP +
|
|
RULE_Y_OFFSET_BOTTOM);
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
mch = 8;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
mch = lmp->min_cell_height;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->pix_cell_height = max(lmp->pix_cell_height, mch);
|
|
lmp->pix_row_spacing = lmp->pix_cell_height + RULE_WIDTH_H;
|
|
lmp->pix_top = lmp->rct.top;
|
|
lmp->pix_hdr_bottom = lmp->rct.top + lmp->leading + lmp->ascent +
|
|
lmp->descent + BORDER_WIDTH +
|
|
RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
|
|
lmp->pix_hdr_bottom = max(lmp->pix_hdr_bottom,
|
|
(lmp->rct.top + lmp->min_heading_height + 2 * BORDER_WIDTH));
|
|
if (lmp->no_heading)
|
|
lmp->pix_row1_top = lmp->rct.top + BORDER_WIDTH;
|
|
else
|
|
lmp->pix_row1_top = lmp->pix_hdr_bottom + BORDER_WIDTH;
|
|
|
|
old_char_width = lmp->pix_char_width;
|
|
lmp->pix_char_width = xi_get_fu_width(lmp->itf_obj);
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
|
|
for (i = 0, lmcdp = lmp->lm_column_data; i < lmp->nbr_columns; ++i, ++lmcdp)
|
|
(*lmcdp)->pix_width = (*lmcdp)->pix_width * lmp->pix_char_width /
|
|
old_char_width;
|
|
|
|
for (i = 0; i < lmp->nbr_columns; ++i)
|
|
calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
|
|
|
|
lmp->rct.right = lmp->rct.left +
|
|
lmp->lm_column_data[lmp->nbr_columns - 1]->x_pix_pos +
|
|
lmp->lm_column_data[lmp->nbr_columns - 1]->pix_width +
|
|
2 * BORDER_WIDTH;
|
|
|
|
if (! lmp->resize_with_window)
|
|
{
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing +
|
|
(BORDER_WIDTH - RULE_WIDTH_H);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->rct.bottom = lmp->pix_row1_top + lmp->nbr_rows * lmp->pix_row_spacing
|
|
+ BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
}
|
|
|
|
if (lmp->fixed_columns >= lmp->nbr_columns)
|
|
lmp->delta_x = 0;
|
|
else
|
|
lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
|
|
lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
|
|
|
|
lmp->mlr.top = lmp->pix_row1_top;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
if (lmp->pixel_width)
|
|
lmp->mlr.bottom = lmp->rct.bottom;
|
|
else
|
|
lmp->mlr.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
lmp->mlr_height = lmp->mlr.bottom - lmp->mlr.top;
|
|
|
|
if (lmp->rrr_bottom < lmp->mlr_height)
|
|
lm_make_rrr_room_pix(lmp, lmp->mlr_height - lmp->rrr_bottom, FALSE);
|
|
|
|
list_data->have_sb_rct = FALSE;
|
|
list_data->have_hsb_rct = FALSE;
|
|
|
|
xi_get_sb_rect(lmp->list_obj, &rct);
|
|
xvt_vobj_move(list_data->sb_win, &rct);
|
|
|
|
xi_get_hsb_rect(lmp->list_obj, &rct);
|
|
xvt_vobj_move(list_data->hsb_win, &rct);
|
|
|
|
lm_calc_last_vis(lmp);
|
|
}
|
|
|
|
void
|
|
lm_text_scrolling(XI_OBJ *xi_obj)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)xi_obj->v.list->lm;
|
|
|
|
lmp->text_scrolling = TRUE;
|
|
}
|
|
|
|
void
|
|
lm_set_hscroll_range(LM lm)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
int hscroll_width, fixed_width, cnt;
|
|
RCT mlr;
|
|
XI_LIST_DATA *listdata;
|
|
|
|
if (lmp->list_obj->nbr_children <= 0) return;
|
|
|
|
listdata = lmp->list_obj->v.list;
|
|
lm_get_scroll_rct(lmp, &mlr);
|
|
if (lmp->pixel_width)
|
|
{
|
|
int prop;
|
|
|
|
hscroll_width = 0;
|
|
fixed_width = 0;
|
|
for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt)
|
|
hscroll_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing();
|
|
for (cnt = 0; cnt < lmp->fixed_columns; ++cnt)
|
|
fixed_width += lmp->lm_column_data[cnt]->pix_width + lm_get_col_spacing();
|
|
#if XIWS == MTFWS
|
|
if ( hscroll_width != 0 )
|
|
{
|
|
#endif
|
|
xvt_sbar_set_range(listdata->hsb_win, HVSCROLL, 0, hscroll_width);
|
|
prop = mlr.right - mlr.left - fixed_width - BORDER_WIDTH;
|
|
prop = min(prop, hscroll_width);
|
|
prop = max(prop, 0);
|
|
xvt_sbar_set_proportion(listdata->hsb_win, HVSCROLL, prop);
|
|
#if XIWS == MTFWS
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_column_set_pixel_width
|
|
lm: current lm
|
|
idx: column number
|
|
width: in pixels
|
|
-------------------------------------------------------------------------*/
|
|
void lm_column_set_pixel_width(LM lm, int idx, int width)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *) lm;
|
|
LM_COLUMN_DATA * column;
|
|
RCT invalid_rct, old_rct;
|
|
int i, old_width, new_row_height, cnt;
|
|
|
|
old_rct = lmp->rct;
|
|
column = lmp->lm_column_data[idx];
|
|
old_width = column->pix_width;
|
|
column->width = width / lmp->pix_char_width;
|
|
column->pix_width = width;
|
|
for (i = idx + 1; i < lmp->nbr_columns; ++i)
|
|
calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
|
|
|
|
/* adjust bounding rectangle */
|
|
lmp->rct.right += column->pix_width - old_width;
|
|
lmp->mlr.right += column->pix_width - old_width;
|
|
if (idx < lmp->fixed_columns)
|
|
lmp->vir_left += column->pix_width - old_width;
|
|
/* The x_pix_pos of the first visible column may have changed so
|
|
recalculate delta_x */
|
|
if (lmp->fixed_columns >= lmp->nbr_columns)
|
|
lmp->delta_x = 0;
|
|
else
|
|
lmp->delta_x = lmp->lm_column_data[lmp->first_vis]->x_pix_pos -
|
|
lmp->lm_column_data[lmp->fixed_columns]->x_pix_pos;
|
|
|
|
invalid_rct = lmp->rct;
|
|
invalid_rct.left = column->x_pix_pos;
|
|
invalid_rct.right = max(invalid_rct.right, old_rct.right);
|
|
if (lmp->pixel_width)
|
|
invalid_rct.right = lmp->rct.left + lmp->pixel_width + 2 * BORDER_WIDTH;
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
lm_set_hscroll_range((LM)lmp);
|
|
lm_calc_last_vis(lmp);
|
|
|
|
if (column->wrap_text)
|
|
{
|
|
int first_fully_vis = lmp->first_fully_vis;
|
|
int last_row = lmp->nbr_realized_rows - 1;
|
|
int height;
|
|
|
|
for (cnt = 0; cnt < lmp->nbr_realized_rows; ++cnt)
|
|
{
|
|
int old_row_height;
|
|
|
|
old_row_height = lmp->pix_heights[cnt];
|
|
new_row_height = lm_calculate_row_height(lmp, cnt);
|
|
lmp->pix_heights[cnt] = new_row_height;
|
|
if (old_row_height != new_row_height)
|
|
invalid_rct.left = lmp->rct.left;
|
|
}
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
height = lmp->pix_offsets[last_row] + lmp->pix_heights[last_row] -
|
|
lmp->pix_offsets[first_fully_vis];
|
|
if (height < lmp->mlr_height)
|
|
lm_make_rrr_room_pix(lmp, lmp->mlr_height - height, FALSE);
|
|
if (! lmp->get_all_records)
|
|
{
|
|
int nbr_to_free;
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0;
|
|
cnt < nbr_to_free;
|
|
i++, cnt++)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
calculate_visibles(lmp);
|
|
}
|
|
}
|
|
lm_invalidate_rect2(lmp, &invalid_rct, TRUE);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_column_width
|
|
lm: current lm
|
|
idx: column number
|
|
width: in characters
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_column_width(LM lm, int idx, int width)
|
|
{
|
|
lm_column_set_pixel_width( lm, idx,
|
|
width * ((LM_DATA *)lm)->pix_char_width );
|
|
}
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
/* lm_cell_is_visible */
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
BOOLEAN
|
|
lm_is_cell_visible( LM_DATA *lmp, int row, int column,
|
|
BOOLEAN use_txt_is_visible,
|
|
BOOLEAN *is_hscrolled)
|
|
{
|
|
if (is_hscrolled)
|
|
*is_hscrolled = FALSE;
|
|
if (use_txt_is_visible && lmp->txt_is_invisible)
|
|
{
|
|
int r;
|
|
|
|
if (lmp->focus_rec == 0L)
|
|
{
|
|
if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
|
|
return TRUE;
|
|
*is_hscrolled = TRUE;
|
|
return FALSE;
|
|
}
|
|
for (r = 0; r < lmp->nbr_realized_rows; ++r)
|
|
{
|
|
if (lmp->recs[r] == lmp->focus_rec)
|
|
{
|
|
if (r >= lmp->first_fully_vis && r <= lmp->last_fully_vis)
|
|
{
|
|
if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (is_hscrolled)
|
|
*is_hscrolled = TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (row >= lmp->first_fully_vis && row <= lmp->last_fully_vis + 1)
|
|
{
|
|
if (column < lmp->fixed_columns || (column >= lmp->first_vis && column <= lmp->last_vis))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (is_hscrolled)
|
|
*is_hscrolled = TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void lm_force_vis(LM_DATA *lmp)
|
|
{
|
|
LM_COLUMN_DATA* lmcdp;
|
|
unsigned long attrib, cell_attrib;
|
|
int c;
|
|
RCT mr;
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
mr = lmp->mlr;
|
|
if (lmp->pixel_width)
|
|
mr.right = mr.left + lmp->pixel_width + BORDER_WIDTH;
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled);
|
|
lmcdp = lmp->lm_column_data[focus_column];
|
|
attrib = lmcdp->attrib;
|
|
|
|
cell_attrib = lm_get_attrib( (LM) lmp, LM_CELL, focus_row, focus_column,
|
|
v_scrolled ) & (XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
if (cell_attrib)
|
|
{
|
|
attrib &= ~(XI_ATR_HCENTER | XI_ATR_RJUST);
|
|
attrib |= cell_attrib;
|
|
}
|
|
|
|
/* force cell to be visible */
|
|
c = min(focus_column, lmp->nbr_columns - 1);
|
|
if (c >= lmp->fixed_columns && c < lmp->first_vis)
|
|
lm_local_hscroll((LM)lmp, c - lmp->first_vis);
|
|
else
|
|
{
|
|
if (c > lmp->last_vis)
|
|
{
|
|
int first_col;
|
|
|
|
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);
|
|
}
|
|
}
|
|
if (focus_row < lmp->first_fully_vis)
|
|
{
|
|
int delta, idx2, pix2, old_pix;
|
|
RCT tmp_rct;
|
|
|
|
make_room_rows(lmp, focus_row - lmp->first_fully_vis, FALSE);
|
|
idx2 = focus_row;
|
|
pix2 = lmp->pix_offsets[idx2];
|
|
old_pix = -lmp->rrr_offset;
|
|
delta = old_pix - pix2;
|
|
lmp->rrr_offset += delta;
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lm_get_scroll_rct(lmp, &tmp_rct);
|
|
xi_scroll_rect(lmp->win, &tmp_rct, 0, delta);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
}
|
|
if (focus_row > lmp->last_fully_vis)
|
|
{
|
|
int pix, delta;
|
|
RCT tmp_rct;
|
|
|
|
delta = 0;
|
|
while (TRUE)
|
|
{
|
|
if (focus_row <= lmp->last_fully_vis)
|
|
break;
|
|
pix = lmp->pix_heights[0];
|
|
delta += pix;
|
|
lm_make_rrr_room_pix(lmp, pix, FALSE);
|
|
lmp->rrr_offset -= pix;
|
|
calculate_pix_offsets(lmp, FALSE);
|
|
calculate_visibles(lmp);
|
|
}
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lm_get_scroll_rct(lmp, &tmp_rct);
|
|
xi_scroll_rect(lmp->win, &tmp_rct, 0, -delta);
|
|
do_scroll_bar(lmp->list_obj->v.list);
|
|
|
|
if (! lmp->get_all_records && ! lmp->keep_all_records)
|
|
{
|
|
int nbr_to_free, cnt, i, idx;
|
|
|
|
nbr_to_free = lmp->first_fully_vis;
|
|
if (nbr_to_free > 0)
|
|
{
|
|
for (cnt = 0; cnt < nbr_to_free; cnt++)
|
|
{
|
|
lmp->rrr_offset += lmp->pix_heights[cnt];
|
|
do_rec_event(lmp, cnt, XIE_REC_FREE);
|
|
}
|
|
|
|
for (idx = nbr_to_free; idx < lmp->nbr_realized_rows; ++idx)
|
|
row_copy(lmp, idx, idx - nbr_to_free);
|
|
adjust_rows(lmp, -nbr_to_free);
|
|
|
|
lmp->nbr_realized_rows -= cnt;
|
|
}
|
|
|
|
/* free any unnecessary records at the end of the list */
|
|
nbr_to_free = lmp->nbr_realized_rows - (lmp->last_fully_vis + 2);
|
|
if (nbr_to_free > 0)
|
|
{
|
|
for (i = lmp->nbr_realized_rows - nbr_to_free, cnt = 0; cnt < nbr_to_free;
|
|
i++, cnt++)
|
|
do_rec_event(lmp, i, XIE_REC_FREE);
|
|
lmp->nbr_realized_rows -= cnt;
|
|
}
|
|
|
|
calculate_pix_offsets(lmp, TRUE );
|
|
}
|
|
}
|
|
lm_make_vis(lmp);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_visible_columns
|
|
lm: current lm
|
|
first_vis:
|
|
last_vis:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_get_visible_columns(LM lm, int *first_vis, int *last_vis)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
|
|
*first_vis = lmp->first_vis;
|
|
*last_vis = lmp->last_vis;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_info
|
|
lm: current lm
|
|
nbr_recs: number of records
|
|
returns: array of record handles
|
|
-------------------------------------------------------------------------*/
|
|
long *
|
|
lm_get_list_info(LM lm, int *nbr_recs)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
|
|
*nbr_recs = lmp->nbr_realized_rows;
|
|
return &lmp->recs[0];
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_cell_request
|
|
lm: current lm
|
|
lm_part: may be LM_LIST, LM_ROW, LM_COLUMN, or LM_CELL ??
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_cell_request( LM lm, LM_PART lm_part, int idx1, int idx2 )
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
BOOLEAN redraw;
|
|
|
|
redraw = (BOOLEAN)(lmp->attrib & (LM_ATR_VISIBLE));
|
|
lm_make_invis(lmp);
|
|
switch (lm_part)
|
|
{
|
|
case LM_LIST:
|
|
lm_invalidate_rows_internal( lm, 0, lmp->nbr_realized_rows - 1, redraw, -1,
|
|
FALSE );
|
|
lm_make_vis(lmp);
|
|
return;
|
|
case LM_ROW:
|
|
lm_invalidate_rows_internal(lm, idx1, idx1, redraw, -1, FALSE);
|
|
lm_make_vis(lmp);
|
|
return;
|
|
case LM_COLUMN:
|
|
lm_invalidate_rows_internal(lm, 0, lmp->nbr_realized_rows - 1, redraw, idx1,
|
|
FALSE );
|
|
lm_make_vis(lmp);
|
|
return;
|
|
case LM_CELL:
|
|
lm_invalidate_rows_internal(lm, idx1, idx1, redraw, idx2, FALSE);
|
|
lm_make_vis(lmp);
|
|
return;
|
|
}
|
|
xvt_errmsg_sig_if(!(xi_false), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20918", 20918, "lm_cell_request: Invalid LM part");
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_visible_rows
|
|
------------------------------------------------------------------------- */
|
|
int
|
|
lm_get_visible_rows(LM lm, int *first_vis, int *last_vis)
|
|
{
|
|
LM_DATA *lmp = (LM_DATA *)lm;
|
|
|
|
if (first_vis)
|
|
*first_vis = lmp->first_fully_vis;
|
|
if (last_vis)
|
|
*last_vis = lmp->last_fully_vis;
|
|
if (! lmp->nbr_realized_rows)
|
|
return 0;
|
|
else
|
|
return lmp->last_fully_vis - lmp->first_fully_vis + 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_list_obj
|
|
lm: current lm
|
|
returns: XI_OBJ * for list
|
|
-------------------------------------------------------------------------*/
|
|
XI_OBJ *
|
|
lm_get_list_obj(LM lm)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
return(lmp->list_obj);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_buf_size_internal
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
size: the new buffer size
|
|
redraw: if TRUE, then redraw the cell
|
|
-------------------------------------------------------------------------*/
|
|
static void near
|
|
lm_set_buf_size_internal(LM lm, LM_PART part, int idx, int size, BOOLEAN redraw)
|
|
{
|
|
int i, toff;
|
|
int oldlen, diff;
|
|
int oldbufsize;
|
|
char *p;
|
|
LM_COLUMN_DATA *lmcd, *lmcdm1;
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
xvt_errmsg_sig_if(!(part == LM_COLUMN), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4,"20917",
|
|
20917, "lm_set_buf_size: Invalid LM part");
|
|
lmcd = lmp->lm_column_data[idx];
|
|
oldlen = lmcd->text_size;
|
|
oldbufsize = lmp->text_size;
|
|
lmcd->text_size = size;
|
|
diff = size - oldlen;
|
|
lmp->text_size += diff;
|
|
toff = lmcd->text_offset;
|
|
|
|
for (i = 0; i < lmp->realized_rows_array_len; i++)
|
|
{
|
|
p = lmp->buffer[i];
|
|
if (diff < 0) {
|
|
p[toff + size - 1] = '\0';
|
|
gmemmove(p + toff + size, p + toff + oldlen,
|
|
(long)(oldbufsize - toff - oldlen));
|
|
lmp->buffer[i] = (char *)xi_tree_realloc(p, oldbufsize + diff);
|
|
/* redraw cause might obliterate some text */
|
|
if (redraw)
|
|
redraw_cell(lm, i, idx, FALSE );
|
|
}
|
|
else
|
|
{
|
|
p = lmp->buffer[i] = (char *)xi_tree_realloc(p, oldbufsize + diff);
|
|
gmemmove(p + toff + size, p + toff + oldlen,
|
|
(long)(oldbufsize - toff - oldlen));
|
|
}
|
|
}
|
|
for (i = 0; i < lmp->nbr_columns; ++i)
|
|
{
|
|
lmcd = lmp->lm_column_data[i];
|
|
if (i)
|
|
lmcdm1 = lmp->lm_column_data[i - 1];
|
|
lmcd->text_offset = (i == 0) ? 0 :
|
|
lmcdm1->text_offset + lmcdm1->text_size;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_buf_size
|
|
lm: current lm
|
|
part: must be LM_COLUMN
|
|
idx: column number
|
|
size: the new buffer size
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_buf_size(LM lm, LM_PART part, int idx, int size)
|
|
{
|
|
lm_set_buf_size_internal(lm, part, idx, size, TRUE);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* adjust_focus_for_column_delete */
|
|
/* if the focus is on a column after the deleted column, adjust the focus */
|
|
/* objects. */
|
|
/* if the focus is on the deleted column, move the focus to the interface */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static void adjust_focus_for_column_delete( LM_DATA* lmp, int column_nbr )
|
|
{
|
|
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)
|
|
return;
|
|
if ( focus_obj->v.cell.column == column_nbr )
|
|
{
|
|
xi_set_focus( lmp->itf_obj );
|
|
return;
|
|
}
|
|
if ( (int)focus_obj->v.cell.column > (int)column_nbr )
|
|
focus_obj->v.cell.column--;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_delete_column
|
|
lm: current lm
|
|
column_nbr: column to delete
|
|
adjust_hscrolling: if TRUE, then make more horizontal columns visible
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_delete_column(LM lm, int column_nbr, BOOLEAN adjust_hscrolling)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
LM_COLUMN_DATA *lmcd;
|
|
RCT invalid_rct, old_rct;
|
|
int i, old_width, old_left, col_spacing;
|
|
int old_x_pix_pos;
|
|
LM_CELL_DATA *cell_data;
|
|
|
|
adjust_focus_for_column_delete( lmp, column_nbr );
|
|
col_spacing = lm_get_col_spacing();
|
|
xvt_errmsg_sig_if(!(column_nbr < lmp->nbr_columns), NULL_WIN, SEV_FATAL,
|
|
ERR_ASSERT_4, "20915", 20915,
|
|
"Invalid column number passed to lm_delete_column");
|
|
old_rct = lmp->rct;
|
|
lmcd = lmp->lm_column_data[column_nbr];
|
|
old_left = lmcd->x_pix_pos - lmp->delta_x;
|
|
old_x_pix_pos = lmcd->x_pix_pos;
|
|
old_width = lmcd->pix_width;
|
|
lm_set_buf_size_internal(lm, LM_COLUMN, column_nbr, 0, FALSE);
|
|
xi_tree_free(lmp->lm_column_data[column_nbr]);
|
|
|
|
for (i = 0; i < lmp->nbr_realized_rows; ++i)
|
|
{
|
|
cell_data = &(lmp->cell_data[i][column_nbr]);
|
|
if (cell_data->font)
|
|
{
|
|
xi_free_font_id(lmp->itf_obj, *cell_data->font);
|
|
xi_tree_free(cell_data->font);
|
|
}
|
|
if (cell_data->string)
|
|
xi_tree_free(cell_data->string);
|
|
if (cell_data->line_breaks)
|
|
xi_tree_free(cell_data->line_breaks);
|
|
}
|
|
|
|
for (i = 0; i < lmp->realized_rows_array_len; ++i)
|
|
{
|
|
int j;
|
|
|
|
for (j = column_nbr; j < lmp->nbr_columns - 1; ++j)
|
|
lmp->cell_data[i][j] = lmp->cell_data[i][j + 1];
|
|
lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_realloc(lmp->cell_data[i],
|
|
(lmp->nbr_columns - 1) * sizeof(LM_CELL_DATA));
|
|
}
|
|
|
|
for (i = column_nbr; i < lmp->nbr_columns - 1; ++i)
|
|
lmp->lm_column_data[i] = lmp->lm_column_data[i + 1];
|
|
--lmp->nbr_columns;
|
|
|
|
for (i = column_nbr; i < lmp->nbr_columns; ++i)
|
|
calc_x_pix_pos(lm, lmp->lm_column_data[i], i);
|
|
|
|
/*
|
|
adjust bounding rectangle
|
|
*/
|
|
lmp->rct.right = lmp->rct.right - old_width - lm_get_col_spacing();
|
|
/* single-column lists do not have a vertical rule seperating columns */
|
|
if (lmp->nbr_columns == 0)
|
|
lmp->rct.right += RULE_WIDTH_V;
|
|
|
|
/* adjust left border of horizontal virtual space */
|
|
if (column_nbr < lmp->fixed_columns)
|
|
lmp->vir_left -= (old_width + col_spacing);
|
|
|
|
|
|
/*
|
|
if the column is invisible
|
|
*/
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
if (column_nbr >= lmp->fixed_columns && old_x_pix_pos < lmp->delta_x)
|
|
{
|
|
lmp->delta_x -= (old_width + lm_get_col_spacing());
|
|
--lmp->first_vis;
|
|
lm_set_hscroll_range((LM)lmp);
|
|
}
|
|
else
|
|
{
|
|
if (column_nbr < lmp->fixed_columns)
|
|
{
|
|
--lmp->first_vis;
|
|
--lmp->fixed_columns;
|
|
lm_set_hscroll_range((LM)lmp);
|
|
}
|
|
|
|
invalid_rct = lmp->rct;
|
|
invalid_rct.left = old_left;
|
|
invalid_rct.right = max(invalid_rct.right, old_rct.right);
|
|
if (lmp->pixel_width)
|
|
invalid_rct.right = lmp->rct.left + lmp->pixel_width + BORDER_WIDTH;
|
|
|
|
/*
|
|
if we add the following two lines in, it prevents flashing of the top and bottom borders when
|
|
moving columns, however, the top and bottom borders need to get invalidated
|
|
invalid_rct.top += BORDER_WIDTH;
|
|
invalid_rct.bottom -= BORDER_WIDTH;
|
|
*/
|
|
|
|
lm_invalidate_rect2(lmp, &invalid_rct, FALSE);
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
|
|
i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
|
|
if (lmp->first_vis >= lmp->nbr_columns)
|
|
{
|
|
RCT r;
|
|
|
|
xvt_dwin_update(lmp->win);
|
|
lmp->delta_x = lmp->lm_column_data[i]->x_pix_pos - lmp->vir_left;
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lmp->last_vis = lmp->first_vis = i;
|
|
lm_calc_last_vis(lmp);
|
|
r.left = lmp->vir_left;
|
|
r.right = lmp->vir_right;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
r.top = lmp->rct.top + BORDER_WIDTH;
|
|
r.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
r.top = lmp->rct.top;
|
|
r.bottom = lmp->rct.bottom;
|
|
CTOS_END;
|
|
#endif
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
xvt_dwin_update(lmp->win);
|
|
lm_set_hscroll_bar((LM)lmp);
|
|
}
|
|
else
|
|
{
|
|
if (i < lmp->first_vis && adjust_hscrolling)
|
|
{
|
|
xvt_dwin_update(lmp->win);
|
|
lm_hscroll(lm, i - lmp->first_vis, 0);
|
|
}
|
|
else
|
|
{
|
|
lm_calc_last_vis(lmp);
|
|
lm_set_hscroll_range((LM)lmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
TODO this function will change. pix_row_spacing will no longer be used.
|
|
instead, min_row_height, and absolute_height will be used.
|
|
*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
lm_get_vertical_metrics
|
|
-------------------------------------------------------------------------*/
|
|
void lm_get_vertical_metrics( XI_OBJ_DEF* obj_def, int* first_row_y,
|
|
int* row_spacing, int *client_height,
|
|
int* title_height )
|
|
{
|
|
XI_LIST_DEF* list_def;
|
|
XI_OBJ_DEF* itf_def;
|
|
int leading, ascent, descent, char_width, font_height, pix_cell_height,
|
|
pix_hdr_bottom, min_cell_height;
|
|
PNT p;
|
|
FONT_OBJ *fontp = NULL;
|
|
|
|
list_def = obj_def->v.list;
|
|
|
|
#if XI_IS_CH
|
|
NOREF(char_width);
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
|
|
itf_def = obj_def->parent;
|
|
if (itf_def && itf_def->v.itf->font_id)
|
|
fontp = &itf_def->v.itf->font_id;
|
|
if (list_def->font_id)
|
|
xi_get_font_metrics_font( &list_def->font_id, &leading, &ascent, &descent,
|
|
&char_width);
|
|
else if (fontp)
|
|
xi_get_font_metrics_font(fontp, &leading, &ascent, &descent, &char_width);
|
|
else
|
|
xi_get_font_metrics_font( &xi_sysfont, &leading, &ascent, &descent,
|
|
&char_width);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
leading = 0;
|
|
ascent = 8;
|
|
descent = 0;
|
|
CTOS_END;
|
|
#endif
|
|
font_height = ascent + leading + descent;
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
min_cell_height = 8;
|
|
pix_cell_height = font_height;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
min_cell_height = list_def->min_cell_height;
|
|
pix_cell_height = font_height + CELL_VERTICAL_MARGIN;
|
|
CTOS_END;
|
|
#endif
|
|
pix_cell_height = max(pix_cell_height, min_cell_height);
|
|
#if XVTWS == WMWS
|
|
*row_spacing = pix_cell_height;
|
|
#else
|
|
*row_spacing = pix_cell_height + RULE_WIDTH_H;
|
|
#endif
|
|
itf_def = obj_def->parent;
|
|
if (itf_def && itf_def->v.itf->font_id)
|
|
fontp = &itf_def->v.itf->font_id;
|
|
if (xi_get_xil_pref((XI_OBJ *)itf_def))
|
|
{
|
|
p = list_def->xi_pnt;
|
|
}
|
|
else
|
|
{
|
|
p = list_def->pixel_origin;
|
|
if (!p.v && !p.h)
|
|
{
|
|
p = list_def->xi_pnt;
|
|
if (list_def->font_id)
|
|
xi_fu_to_pu_font(&list_def->font_id, &p, 1);
|
|
else if (fontp)
|
|
xi_fu_to_pu_font(fontp, &p, 1);
|
|
else
|
|
xi_fu_to_pu_font(&xi_sysfont, &p, 1);
|
|
}
|
|
}
|
|
#if XVTWS != WMWS
|
|
pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH
|
|
+ RULE_Y_OFFSET_BOTTOM + RULE_Y_OFFSET_TOP;
|
|
pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height
|
|
+ BORDER_WIDTH);
|
|
#else
|
|
pix_hdr_bottom = p.v + leading + ascent + descent + BORDER_WIDTH;
|
|
pix_hdr_bottom = max( pix_hdr_bottom, p.v + list_def->min_heading_height);
|
|
#endif
|
|
if (list_def->no_heading)
|
|
{
|
|
int first_row_y_pos = p.v + BORDER_WIDTH;
|
|
|
|
*first_row_y = first_row_y_pos;
|
|
}
|
|
else
|
|
{
|
|
*first_row_y = pix_hdr_bottom + BORDER_WIDTH;
|
|
}
|
|
if (xi_get_xil_pref((XI_OBJ *)itf_def))
|
|
{
|
|
*client_height = list_def->height;
|
|
}
|
|
else
|
|
{
|
|
if (list_def->pixel_height)
|
|
*client_height = list_def->pixel_height;
|
|
else
|
|
{
|
|
int height;
|
|
|
|
if (list_def->font_id)
|
|
height = xi_get_fu_height_font(&list_def->font_id);
|
|
else if (fontp)
|
|
height = xi_get_fu_height_font(fontp);
|
|
else
|
|
height = xi_get_fu_height_font(&xi_sysfont);
|
|
*client_height = list_def->height * height / XI_FU_MULTIPLE;
|
|
}
|
|
}
|
|
*title_height = *first_row_y - p.v;
|
|
*client_height -= *title_height + BORDER_WIDTH;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_get_metrics
|
|
lm_def: definition of a list
|
|
hborder: to be filled in with the horizontal border width
|
|
column_div: to be filled in with the column spacing in pixels
|
|
list_button: bottom of the list, in pixels
|
|
-------------------------------------------------------------------------*/
|
|
void lm_get_metrics(XI_OBJ_DEF *obj_def, int *hborder, int *column_div,
|
|
int *list_bottom)
|
|
{
|
|
if (hborder != NULL)
|
|
*hborder = BORDER_WIDTH;
|
|
if (column_div != NULL)
|
|
*column_div = lm_get_col_spacing();
|
|
if (obj_def->v.list)
|
|
{
|
|
int pix_row_spacing, nbr_rows, height, pix_row1_top, title_height;
|
|
|
|
lm_get_vertical_metrics( obj_def, &pix_row1_top, &pix_row_spacing,
|
|
&height, &title_height );
|
|
if (obj_def->v.list->one_row_list)
|
|
nbr_rows = 1;
|
|
else
|
|
nbr_rows = height / pix_row_spacing;
|
|
#if XVTWS == WMWS
|
|
*list_bottom = pix_row1_top + nbr_rows * pix_row_spacing + BORDER_WIDTH;
|
|
#else
|
|
*list_bottom = pix_row1_top + nbr_rows * pix_row_spacing
|
|
+ (BORDER_WIDTH - RULE_WIDTH_H);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_start_edit
|
|
lm: current lm
|
|
row: relevant row
|
|
column: relevant column
|
|
notes: create a text core edit field in the position of the
|
|
cell of interest, and copy in the necessary attributes
|
|
and text from the list
|
|
-------------------------------------------------------------------------*/
|
|
static void lm_start_edit(LM lm, int row, int column)
|
|
{
|
|
LM_DATA* lmp = LMP(lm);
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
|
|
xvt_errmsg_sig_if(!( focus_row == row && focus_column == column), NULL_WIN,
|
|
SEV_FATAL, ERR_ASSERT_4, "20919", 20919,
|
|
"lm_start_edit: Internal error, called with focus not poperly set");
|
|
lm_force_vis(lmp);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_focus
|
|
lm: current lm
|
|
row: row
|
|
column: column
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_focus(LM lm, int row, int column)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &v_scrolled );
|
|
if (row != focus_row || column != focus_column)
|
|
{
|
|
lm_make_invis(lmp);
|
|
lm_make_vis(lmp);
|
|
}
|
|
}
|
|
else
|
|
lm_start_edit(lm, row, column);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_hscroll_bar
|
|
lm: current lm
|
|
notes: Calculate the percentage for the horizontal scroll bar, and set the
|
|
thumb position on the horizontal scroll bar.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_hscroll_bar(LM lm)
|
|
{
|
|
XI_OBJ *list_obj;
|
|
int i, first_vis, p;
|
|
LM_DATA *lmp;
|
|
int rng1, rng2;
|
|
int prop;
|
|
|
|
lmp = (LM_DATA *)lm;
|
|
list_obj = lmp->list_obj;
|
|
if (list_obj->v.list->hsb_win)
|
|
{
|
|
xvt_sbar_get_range(list_obj->v.list->hsb_win, HVSCROLL,
|
|
&rng1, &rng2);
|
|
prop = xvt_sbar_get_proportion(list_obj->v.list->hsb_win, HVSCROLL);
|
|
rng2 -= prop;
|
|
i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
|
|
if (i == 0)
|
|
p = 0;
|
|
else
|
|
{
|
|
i = i - lmp->fixed_columns;
|
|
first_vis = lmp->first_vis - lmp->fixed_columns;
|
|
if (i)
|
|
p = (int)(((long)rng2 * (long)first_vis) / i);
|
|
else
|
|
p = 0;
|
|
}
|
|
if (p < 0)
|
|
p = 0;
|
|
if (p > rng2)
|
|
p = rng2;
|
|
xvt_sbar_set_pos(list_obj->v.list->hsb_win, HVSCROLL,
|
|
p);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_create_column
|
|
lcdef: column definition
|
|
not_creating_list: if TRUE, do all of the cell requests for the column
|
|
in_hscrolling: if TRUE, and if on border between fixed and scrolling columns
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_create_column(LM lm, LM_COLUMN_DEF *lcdef, BOOLEAN not_creating_list,
|
|
BOOLEAN in_hscrolling)
|
|
{
|
|
LM_COLUMN_DATA *lcdata, *lcdatam1;
|
|
LM_COLUMN_DATA * *column_data;
|
|
LM_DATA *lmp = LMP(lm);
|
|
RCT rct_to_invalidate;
|
|
int new_textlen;
|
|
int text_copyidx;
|
|
int i;
|
|
char *src;
|
|
char *dst;
|
|
char *target;
|
|
char *buf;
|
|
int position, col_spacing;
|
|
int focus_row, focus_column;
|
|
BOOLEAN made_invis = FALSE;
|
|
|
|
col_spacing = lm_get_col_spacing();
|
|
position = min(lcdef->position, lmp->nbr_columns);
|
|
if (lm_list_has_focus(lmp))
|
|
{
|
|
BOOLEAN vert_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &vert_scrolled);
|
|
if (focus_column >= position)
|
|
++focus_column;
|
|
lm_set_focus_cell(lmp, focus_row, focus_column, vert_scrolled );
|
|
if (! lmp->txt_is_invisible)
|
|
{
|
|
lm_make_invis(lmp);
|
|
made_invis = TRUE;
|
|
}
|
|
}
|
|
lcdata = (LM_COLUMN_DATA *)xi_tree_malloc(sizeof(LM_COLUMN_DATA),
|
|
(char *)lm);
|
|
lcdata->attrib = lcdef->attrib;
|
|
/*
|
|
lcdata->pix_width = lcdef->width * lmp->pix_char_width;
|
|
lcdata->width = lcdef->width;
|
|
*/
|
|
lcdata->pix_width = lcdef->pix_width;
|
|
lcdata->width = lcdef->pix_width / lmp->pix_char_width;
|
|
calc_x_pix_pos(lm, lcdata, position);
|
|
if (position)
|
|
lcdatam1 = lmp->lm_column_data[position - 1];
|
|
text_copyidx = (position == 0) ? 0 : lcdatam1->text_offset +
|
|
lcdatam1->text_size;
|
|
lcdata->text_offset = text_copyidx;
|
|
lcdata->text_size = lcdef->text_size;
|
|
lcdata->center_heading = lcdef->center_heading;
|
|
lcdata->heading_well = lcdef->heading_well;
|
|
lcdata->heading_platform = lcdef->heading_platform;
|
|
lcdata->column_well = lcdef->column_well;
|
|
lcdata->column_platform = lcdef->column_platform;
|
|
lcdata->heading_text = (char *)xi_tree_malloc(
|
|
strlen(lcdef->heading_text) + 1, (char *)lm);
|
|
strcpy(lcdata->heading_text, lcdef->heading_text);
|
|
if (lcdef->font)
|
|
{
|
|
#if 0
|
|
/* reparenting font object, not reallocating */
|
|
lcdata->font = (FONT_OBJ *)xi_tree_malloc(sizeof(FONT_OBJ),
|
|
(void *)lm);
|
|
#endif
|
|
lcdata->font = lcdef->font;
|
|
xi_tree_reparent(lcdata->font, lcdata);
|
|
}
|
|
lcdata->icon_rid = lcdef->icon_rid;
|
|
lcdata->icon_x = lcdef->icon_x;
|
|
lcdata->icon_y = lcdef->icon_y;
|
|
lcdata->size_rows = lcdef->size_rows;
|
|
lcdata->suppress_update_heading = lcdef->suppress_update_heading;
|
|
lcdata->suppress_update_cells = lcdef->suppress_update_cells;
|
|
lcdata->vertical_align_center = lcdef->vertical_align_center;
|
|
lcdata->vertical_align_bottom = lcdef->vertical_align_bottom;
|
|
lcdata->wrap_text = lcdef->wrap_text;
|
|
lcdata->auto_tab = lcdef->auto_tab;
|
|
|
|
new_textlen = lmp->text_size + lcdata->text_size;
|
|
|
|
/* allocate new text for each row and move text if necessary */
|
|
for (i = 0; i < lmp->realized_rows_array_len; i++)
|
|
{
|
|
buf = lmp->buffer[i] = (char *)xi_tree_realloc2(lmp->buffer[i],
|
|
new_textlen, (char *)lm);
|
|
/* zero out new text */
|
|
memset(buf + lmp->text_size, '\0', (size_t)lcdata->text_size);
|
|
|
|
/* copy text for old columns that were moved */
|
|
/* degenerate zero-column case is handled correctly */
|
|
dst = buf + new_textlen;
|
|
src = buf + lmp->text_size;
|
|
target = buf + text_copyidx;
|
|
while (src > target)
|
|
*--dst = *--src;
|
|
}
|
|
|
|
/* allocate new columns */
|
|
column_data = lmp->lm_column_data =
|
|
(LM_COLUMN_DATA * *)xi_tree_realloc2(
|
|
(char *)lmp->lm_column_data,
|
|
sizeof(LM_COLUMN_DATA *) * (lmp->nbr_columns + 1),
|
|
(char *)lm);
|
|
|
|
/* create space for cell data */
|
|
for (i = 0; i < lmp->realized_rows_array_len; i++)
|
|
{
|
|
int j;
|
|
|
|
lmp->cell_data[i] = (LM_CELL_DATA *)xi_tree_realloc(lmp->cell_data[i],
|
|
(lmp->nbr_columns + 1) * sizeof(LM_CELL_DATA));
|
|
for (j = lmp->nbr_columns; j > position; j--)
|
|
lmp->cell_data[i][j] = lmp->cell_data[i][j - 1];
|
|
memset((char *)&lmp->cell_data[i][position], '\0',
|
|
sizeof(LM_CELL_DATA));
|
|
}
|
|
|
|
/* move column pointers around in the column list */
|
|
for (i = lmp->nbr_columns; i > position; i--)
|
|
{
|
|
column_data[i] = column_data[i - 1];
|
|
column_data[i]->x_pix_pos += lcdata->pix_width + col_spacing;
|
|
column_data[i]->text_offset += lcdata->text_size;
|
|
}
|
|
column_data[position] = lcdata;
|
|
|
|
lmp->nbr_columns++;
|
|
|
|
if ((not_creating_list) && (position < lmp->fixed_columns))
|
|
{
|
|
lmp->first_vis++;
|
|
lmp->fixed_columns++;
|
|
}
|
|
|
|
if (not_creating_list && (! in_hscrolling) && position == lmp->fixed_columns)
|
|
{
|
|
lmp->first_vis++;
|
|
lmp->fixed_columns++;
|
|
}
|
|
|
|
if (lmp->first_vis < lmp->fixed_columns &&
|
|
lmp->nbr_columns > lmp->fixed_columns)
|
|
lmp->first_vis = lmp->fixed_columns;
|
|
|
|
lmp->text_size = new_textlen;
|
|
|
|
/* adjust bounding rectangle */
|
|
lmp->rct.right += lcdata->pix_width + col_spacing;
|
|
if (lmp->nbr_columns == 1)
|
|
lmp->rct.right -= RULE_WIDTH_V; /* did not add divider rule */
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
lmp->mlr.right = lmp->rct.right;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
lmp->mlr.right = lmp->rct.right - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
|
|
/* 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;
|
|
}
|
|
if (not_creating_list)
|
|
{
|
|
lm_invalidate_rows_internal(lm, 0, INT_MAX, FALSE, position, TRUE);
|
|
calculate_pix_offsets( lmp, TRUE );
|
|
}
|
|
if (position >= lmp->fixed_columns && column_data[position]->x_pix_pos < lmp->delta_x)
|
|
{
|
|
lmp->delta_x += (column_data[position]->pix_width + lm_get_col_spacing());
|
|
++lmp->first_vis;
|
|
lm_set_hscroll_range((LM)lmp);
|
|
}
|
|
else
|
|
{
|
|
/* invalidate changed rectangle */
|
|
lm_get_list_rct(lmp, &rct_to_invalidate);
|
|
|
|
/*
|
|
if we add the following two lines in, it prevents flashing of the top and bottom borders when
|
|
moving columns, however, the top and bottom borders need to get invalidated
|
|
rct_to_invalidate.top += BORDER_WIDTH;
|
|
rct_to_invalidate.bottom -= BORDER_WIDTH;
|
|
*/
|
|
|
|
rct_to_invalidate.left = lcdata->x_pix_pos;
|
|
lm_adj_h(lmp, &rct_to_invalidate.left);
|
|
if (rct_to_invalidate.bottom > rct_to_invalidate.top &&
|
|
rct_to_invalidate.right > rct_to_invalidate.left)
|
|
lm_invalidate_rect2(lmp, &rct_to_invalidate, FALSE);
|
|
}
|
|
lm_calc_last_vis(lmp);
|
|
lmp->list_obj->v.list->have_sb_rct = FALSE;
|
|
if (not_creating_list && lmp->list_obj->v.list->hsb_win)
|
|
{
|
|
RCT rct;
|
|
|
|
lmp->list_obj->v.list->have_hsb_rct = FALSE;
|
|
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);
|
|
}
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
{
|
|
if (not_creating_list && made_invis)
|
|
lm_make_vis(lmp);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: do_lm_cb_column
|
|
lm: current lm
|
|
cb_reason: one of LM_CB_COL_DELETE, LM_CB_COL_MOVE, LM_CB_COL_SIZE
|
|
col_nbr: column being deleted, moved, or re-sized
|
|
new_col_nbr: new column number on LM_CB_COL_MOVE
|
|
new_col_width: new column width on LM_CB_COL_SIZE
|
|
new_col_pixel_width: new column pixel width on LM_CB_COL_SIZE
|
|
in_fixed: if TRUE, then column is being moved to fixed portion of list
|
|
returns: TRUE if event refused
|
|
-------------------------------------------------------------------------*/
|
|
static BOOLEAN
|
|
near do_lm_cb_column(LM lm, LM_CB_TYPE cb_reason, int col_nbr,
|
|
int new_col_nbr, int new_col_width, int new_col_pixel_width,
|
|
BOOLEAN in_fixed)
|
|
{
|
|
LM_CB_DATA lm_cb_data;
|
|
|
|
lm_cb_data.lm = lm;
|
|
lm_cb_data.cb_type = cb_reason;
|
|
lm_cb_data.cid = LMP(lm)->cid;
|
|
lm_cb_data.win = LMP(lm)->win;
|
|
lm_cb_data.column = (unsigned char)col_nbr;
|
|
lm_cb_data.v.column.new_col_nbr = new_col_nbr;
|
|
lm_cb_data.v.column.in_fixed = in_fixed;
|
|
lm_cb_data.v.column.new_col_width = new_col_width;
|
|
lm_cb_data.v.column.new_col_pixel_width = new_col_pixel_width;
|
|
lm_cb_data.v.column.refused = FALSE;
|
|
(*LMP(lm)->lm_cb)(&lm_cb_data);
|
|
return (lm_cb_data.v.column.refused);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: get_rubber_rect
|
|
lmp: current lmp
|
|
rctp: rectangle to be filled in
|
|
x: current mouse x position
|
|
y: current mouse y position
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
get_rubber_rect(LM_DATA *lmp, RCT *rctp, int x, int y,
|
|
BOOLEAN last_in_hscrolling)
|
|
{
|
|
RCT rct;
|
|
int col, delta_x, delta_y;
|
|
|
|
col = lmp->column_being_moved;
|
|
/*
|
|
lm_get_cell_rect returns the exact physical rectangle of the cell - not
|
|
shifted to the right or to the left.
|
|
*/
|
|
lm_get_cell_rect(&rct, (LM)lmp, 1, col, FALSE, TRUE);
|
|
rct.top = lmp->pix_top + BORDER_WIDTH;
|
|
rct.bottom = lmp->pix_hdr_bottom;
|
|
delta_x = x - lmp->org_x;
|
|
if (lmp->down_in_hscrolling && ! last_in_hscrolling)
|
|
delta_x += lmp->delta_x;
|
|
if (! lmp->down_in_hscrolling && last_in_hscrolling)
|
|
delta_x -= lmp->delta_x;
|
|
delta_y = y - lmp->org_y;
|
|
rct.left += delta_x;
|
|
rct.right += delta_x;
|
|
rct.top += delta_y;
|
|
rct.bottom += delta_y;
|
|
*rctp = rct;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_rect
|
|
lmp: current lmp
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_rect(LM_DATA *lmp)
|
|
{
|
|
#if XI_IS_NOT_CH
|
|
RCT rct;
|
|
DRAW_CTOOLS new_ctools;
|
|
WINDOW win = lmp->win;
|
|
|
|
CTOS_IS_PM;
|
|
xvt_app_get_default_ctools(&new_ctools);
|
|
xi_set_draw_ctools(win, &new_ctools);
|
|
xi_set_cpen(win, &rubber_cpen);
|
|
xi_set_cbrush(win, &hollow_cbrush);
|
|
xi_set_draw_mode(win, M_XOR);
|
|
xi_set_clip(win, NULL);
|
|
get_rubber_rect(lmp, &rct, lmp->last_x, lmp->last_y, lmp->last_in_hscrolling);
|
|
xi_draw_rect(win, &rct);
|
|
CTOS_END;
|
|
#endif
|
|
NOREF(lmp);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_move_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_move_event(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
PNT where;
|
|
int col_offset;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
where = ep->v.mouse.where;
|
|
switch (ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
lmp->last_x = where.h;
|
|
lmp->org_x = lmp->last_x;
|
|
lmp->last_y = where.v;
|
|
lmp->org_y = lmp->last_y;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
rubber_rect(lmp);
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
if (where.h != lmp->last_x || where.v != lmp->last_y)
|
|
{
|
|
rubber_rect(lmp);
|
|
lmp->last_x = where.h;
|
|
lmp->last_y = where.v;
|
|
lmp->last_in_hscrolling = lmp->in_hscrolling;
|
|
rubber_rect(lmp);
|
|
}
|
|
break;
|
|
case E_MOUSE_UP:
|
|
{
|
|
int column;
|
|
XI_OBJ *list_obj, * *members;
|
|
int nbr_members, col_cnt, temp1, temp2, dist1, dist2, min_dist,
|
|
position;
|
|
RCT rct;
|
|
PNT where;
|
|
|
|
where = ep->v.mouse.where;
|
|
rubber_rect(lmp);
|
|
column = lmp->column_being_moved;
|
|
list_obj = lmp->list_obj;
|
|
if (list_obj)
|
|
get_rubber_rect(lmp, &rct, where.h, where.v, lmp->in_hscrolling);
|
|
if (lmp->drop_and_delete &&
|
|
(rct.bottom < (lmp->pix_top - 8) ||
|
|
rct.top > (lmp->pix_row1_top + 8)))
|
|
{
|
|
if (do_lm_cb_column((long)lmp, LM_CB_COL_DELETE, column,
|
|
0, 0, 0, FALSE) == FALSE)
|
|
{
|
|
members = xi_get_member_list(list_obj, &nbr_members);
|
|
xi_delete(members[column]);
|
|
lm_set_hscroll_range((LM)lmp);
|
|
}
|
|
}
|
|
if (where.v > lmp->pix_top && where.v < lmp->pix_row1_top &&
|
|
where.h >= lmp->rct.left)
|
|
{
|
|
BOOLEAN in_hscrolling, old_in_hscrolling;
|
|
|
|
/*
|
|
determine where to move the column, if anywhere
|
|
*/
|
|
in_hscrolling = FALSE;
|
|
old_in_hscrolling = (column >= lmp->fixed_columns);
|
|
min_dist = INT_MAX;
|
|
position = 0;
|
|
for (col_cnt = 0; col_cnt < lmp->nbr_columns; col_cnt++)
|
|
{
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
if (col_cnt >= lmp->fixed_columns &&
|
|
col_cnt < lmp->first_vis)
|
|
continue;
|
|
column_data = lmp->lm_column_data[col_cnt];
|
|
temp1 = column_data->x_pix_pos;
|
|
temp2 = temp1 + 2 * col_offset + column_data->pix_width;
|
|
dist1 = abs(temp1 - where.h);
|
|
dist2 = abs(temp2 - where.h);
|
|
if (dist1 < min_dist)
|
|
{
|
|
position = col_cnt;
|
|
min_dist = dist1;
|
|
}
|
|
if (dist2 < min_dist)
|
|
{
|
|
position = col_cnt + 1;
|
|
min_dist = dist2;
|
|
}
|
|
if (col_cnt == lmp->fixed_columns)
|
|
{
|
|
if (where.h < column_data->x_pix_pos)
|
|
in_hscrolling = FALSE;
|
|
else
|
|
in_hscrolling = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
if we need to move the column, then move it
|
|
*/
|
|
if (position < column || position > column + 1 ||
|
|
position == lmp->fixed_columns)
|
|
{
|
|
if (column == position && position == lmp->fixed_columns &&
|
|
in_hscrolling && (! old_in_hscrolling))
|
|
position -= 1;
|
|
else if (position > column)
|
|
position -= 1;
|
|
|
|
/*
|
|
if there is only one fixed column left, then don't move it
|
|
*/
|
|
if (column != 0 || lmp->fixed_columns != 1)
|
|
{
|
|
int widest_remaining, col_width, width_remaining,
|
|
new_fixed_width, cnt;
|
|
BOOLEAN do_move = TRUE;
|
|
LM_COLUMN_DATA *column_data, *lmcdp2;
|
|
RCT r;
|
|
|
|
if (lmp->fixed_columns < lmp->nbr_columns)
|
|
{
|
|
/*
|
|
if there is not room in the horizontal scrolling portion of the
|
|
list for the widest column remaining in the horizontal scrolling
|
|
portion of the list, then don't move the column
|
|
*/
|
|
widest_remaining = 0;
|
|
for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns;
|
|
++cnt)
|
|
{
|
|
if (cnt == column)
|
|
continue;
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
if (col_width > widest_remaining)
|
|
widest_remaining = col_width;
|
|
}
|
|
column_data = lmp->lm_column_data[lmp->fixed_columns];
|
|
lmcdp2 = lmp->lm_column_data[column];
|
|
new_fixed_width = column_data->x_pix_pos;
|
|
if (position < lmp->fixed_columns || ! in_hscrolling)
|
|
new_fixed_width += lmcdp2->pix_width + 2 * col_offset;
|
|
if (column < lmp->fixed_columns)
|
|
new_fixed_width -= lmcdp2->pix_width + 2 * col_offset;
|
|
lm_get_list_rct(lmp, &r);
|
|
width_remaining = r.right - r.left - new_fixed_width;
|
|
if (widest_remaining > width_remaining)
|
|
do_move = FALSE;
|
|
}
|
|
|
|
if (do_move)
|
|
{
|
|
BOOLEAN in_fixed = ! in_hscrolling;
|
|
|
|
if (position > lmp->fixed_columns)
|
|
in_fixed = FALSE;
|
|
if (do_lm_cb_column((long)lmp, LM_CB_COL_MOVE, column,
|
|
position, 0, 0, in_fixed) == FALSE)
|
|
{
|
|
members = xi_get_member_list(list_obj, &nbr_members);
|
|
xi_move_column_internal(members[column], position,
|
|
in_hscrolling);
|
|
lm_calc_last_vis(lmp);
|
|
lm_set_hscroll_bar((LM)lmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
lm_make_vis(lmp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: calc_x
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
returns: Calculates and returns the X pixel position of the rubber band line.
|
|
Used only when sizing columns.
|
|
-------------------------------------------------------------------------*/
|
|
static int
|
|
calc_x(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
int column = lmp->column_being_sized;
|
|
int temp, temp2, widest_remaining;
|
|
int min_width_in_pix = 16;
|
|
int col_offset;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
|
|
/*
|
|
temp is the min width position of the column, relative to the
|
|
left edge of the list.
|
|
*/
|
|
temp = lmp->lm_column_data[column]->x_pix_pos + col_offset +
|
|
min_width_in_pix;
|
|
temp = max(ep->v.mouse.where.h, temp);
|
|
widest_remaining = 0;
|
|
if (lmp->pixel_width)
|
|
{
|
|
int col_offset, col_width, cnt;
|
|
LM_COLUMN_DATA *column_data;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
if (column < lmp->fixed_columns)
|
|
{
|
|
/*
|
|
figure out the widest column in the horizontal scrolling
|
|
portion of the list
|
|
*/
|
|
for (cnt = lmp->fixed_columns; cnt < lmp->nbr_columns; ++cnt)
|
|
{
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
if (col_width > widest_remaining)
|
|
widest_remaining = col_width;
|
|
}
|
|
/*
|
|
add the widths of all of the columns to the right of this column
|
|
in the fixed portion of the list
|
|
*/
|
|
temp2 = 0;
|
|
for (cnt = column + 1; cnt < lmp->fixed_columns; ++cnt)
|
|
{
|
|
column_data = lmp->lm_column_data[cnt];
|
|
col_width = column_data->pix_width + 2 * col_offset;
|
|
temp2 += col_width;
|
|
}
|
|
temp = min((lmp->pixel_width - widest_remaining - temp2) - BORDER_WIDTH,
|
|
temp);
|
|
}
|
|
else
|
|
temp = min((lmp->pixel_width + lmp->delta_x) - BORDER_WIDTH, temp);
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: rubber_x
|
|
lmp: current lmp
|
|
x: draw a rubber line at position x
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
rubber_x(LM_DATA *lmp, int x)
|
|
{
|
|
#if XI_IS_NOT_CH
|
|
int top, bottom;
|
|
DRAW_CTOOLS new_ctools;
|
|
PNT pnt;
|
|
WINDOW win = lmp->win;
|
|
|
|
CTOS_IS_PM;
|
|
top = lmp->pix_top;
|
|
bottom = lmp->mlr.bottom;
|
|
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 = x;
|
|
pnt.v = top;
|
|
if (! lmp->down_in_hscrolling)
|
|
pnt.h += lmp->rct.left;
|
|
lm_move_to(lmp, pnt, FALSE, lmp->down_in_hscrolling);
|
|
pnt.v = bottom;
|
|
lm_draw_line(lmp, pnt, FALSE, lmp->down_in_hscrolling);
|
|
CTOS_END;
|
|
#endif
|
|
NOREF(lmp);
|
|
NOREF(x);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_size_event
|
|
lmp: current lmp
|
|
ep: xvt event
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_size_event(LM_DATA *lmp, EVENT *ep)
|
|
{
|
|
int x;
|
|
|
|
switch (ep->type)
|
|
{
|
|
case E_MOUSE_DOWN:
|
|
case E_MOUSE_DBL:
|
|
x = calc_x(lmp, ep);
|
|
lmp->last_x = x;
|
|
rubber_x(lmp, x);
|
|
break;
|
|
case E_MOUSE_MOVE:
|
|
x = calc_x(lmp, ep);
|
|
rubber_x(lmp, lmp->last_x);
|
|
lmp->last_x = x;
|
|
rubber_x(lmp, x);
|
|
break;
|
|
case E_MOUSE_UP:
|
|
{
|
|
int col_offset;
|
|
int column;
|
|
int temp;
|
|
int width_in_chars;
|
|
int pixel_width;
|
|
XI_OBJ * list_obj, * *members;
|
|
int nbr_members;
|
|
int char_width;
|
|
|
|
col_offset = (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
x = calc_x(lmp, ep);
|
|
rubber_x(lmp, lmp->last_x);
|
|
column = lmp->column_being_sized;
|
|
temp = lmp->lm_column_data[column]->x_pix_pos + col_offset;
|
|
pixel_width = (x - temp) - col_offset;
|
|
width_in_chars = (int)(pixel_width / (long)xi_get_fu_width(lmp->itf_obj));
|
|
list_obj = lmp->list_obj;
|
|
|
|
char_width = width_in_chars * XI_FU_MULTIPLE;
|
|
if (xi_get_xil_pref(list_obj->itf))
|
|
char_width = width_in_chars;
|
|
|
|
if (do_lm_cb_column((long)lmp, LM_CB_COL_SIZE, column,
|
|
0, char_width, pixel_width, FALSE) == FALSE)
|
|
{
|
|
int i;
|
|
|
|
members = xi_get_member_list(list_obj, &nbr_members);
|
|
xi_column_set_pixel_width( members[column], pixel_width );
|
|
i = lm_get_left_most_far_right_col(lmp, lmp->nbr_columns);
|
|
if (i < lmp->first_vis)
|
|
{
|
|
xvt_dwin_update(lmp->win);
|
|
lm_hscroll((LM)lmp, lmp->first_vis - i, 0);
|
|
}
|
|
else
|
|
{
|
|
lm_calc_last_vis(lmp);
|
|
lm_set_hscroll_bar((LM)lmp);
|
|
}
|
|
}
|
|
lm_make_vis(lmp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_icon
|
|
lm: current lm
|
|
icon_rid: icon resource id
|
|
row:
|
|
column:
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_set_icon(LM lm, int icon_rid, int row, int column)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
lmp->cell_data[row][column].icon_rid = icon_rid;
|
|
if (LMP(lm)->attrib & XI_ATR_VISIBLE)
|
|
redraw_cell(lm, row, column, FALSE );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_set_sel
|
|
lm: current lm
|
|
row: row
|
|
column: column
|
|
c1: starting position in selection
|
|
c2: ending position
|
|
-------------------------------------------------------------------------*/
|
|
void lm_set_sel(LM lm, int row, int column, BOOLEAN v_scrolled, int c1, int c2)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
|
|
if (!lm_list_has_focus(lmp))
|
|
{
|
|
lm_set_focus(lm, row, column);
|
|
} else
|
|
{
|
|
int focus_row, focus_column;
|
|
BOOLEAN is_v_scrolled;
|
|
|
|
lm_get_focus_cell(lmp, &focus_row, &focus_column, &is_v_scrolled);
|
|
if (focus_row != row || focus_column != column || v_scrolled != is_v_scrolled)
|
|
lm_set_focus(lm, row, column);
|
|
}
|
|
if (v_scrolled)
|
|
{
|
|
lmp->focus_cell_ip1 = c1;
|
|
lmp->focus_cell_ip2 = c2;
|
|
} else
|
|
txt_set_sel(lmp->txt, c1, c2);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: scroll_list
|
|
lmp: current lmp
|
|
left_col:
|
|
right_col:
|
|
-------------------------------------------------------------------------*/
|
|
static void
|
|
scroll_list(LM_DATA *lmp, int left_col, int right_col)
|
|
{
|
|
RCT r;
|
|
int l1, l2, dist;
|
|
|
|
if (left_col == right_col)
|
|
{
|
|
if (lmp->nbr_columns == lmp->fixed_columns)
|
|
lmp->delta_x = 0;
|
|
return;
|
|
}
|
|
l1 = lmp->rct.left + lmp->lm_column_data[left_col]->x_pix_pos;
|
|
l2 = lmp->rct.left + lmp->lm_column_data[right_col]->x_pix_pos;
|
|
dist = l2 - l1;
|
|
lmp->delta_x += dist;
|
|
r.left = lmp->vir_left;
|
|
r.right = lmp->vir_right;
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
r.top = lmp->rct.top + BORDER_WIDTH;
|
|
r.bottom = lmp->rct.bottom - BORDER_WIDTH;
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
r.top = lmp->rct.top;
|
|
r.bottom = lmp->rct.bottom;
|
|
CTOS_END;
|
|
#endif
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
xi_set_update_obj(lmp->list_obj);
|
|
lmp->last_vis = lmp->first_vis;
|
|
lm_calc_last_vis(lmp);
|
|
|
|
#if XI_IS_CH
|
|
CTOS_IS_CH;
|
|
xi_invalidate_rect(lmp->win, &r);
|
|
CTOS_END;
|
|
#endif
|
|
#if XI_IS_NOT_CH
|
|
CTOS_IS_PM;
|
|
xi_scroll_rect(lmp->win, &r, -dist, 0);
|
|
CTOS_END;
|
|
#endif
|
|
|
|
if (! lmp->itf_obj->v.itf->half_baked)
|
|
xvt_dwin_update(lmp->win);
|
|
lm_set_hscroll_bar((LM)lmp);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
function: lm_hscroll
|
|
lm: current lm
|
|
nbr_columns: number of columns to scroll
|
|
pos: if set, pos is a percentage based on where the thumb was dropped.
|
|
-------------------------------------------------------------------------*/
|
|
void
|
|
lm_hscroll(LM lm, int nbr_columns, int pos)
|
|
{
|
|
LM_DATA *lmp = LMP(lm);
|
|
int first_vis, last_vis, lmfrc, starting_column;
|
|
|
|
xvt_dwin_update(lmp->win);
|
|
lmfrc = lm_get_left_most_far_right_col(LMP(lm), lmp->nbr_columns);
|
|
first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
last_vis = min(lmp->last_vis, lmp->nbr_columns - 1);
|
|
if (xi_get_pref(XI_PREF_UNUSED_PREFERENCE))
|
|
lm_make_invis(lmp);
|
|
else
|
|
{
|
|
if (! lmp->itf_obj->v.itf->moving_focus)
|
|
if (! xi_move_focus(lmp->itf_obj))
|
|
return;
|
|
}
|
|
if (nbr_columns == XI_SCROLL_FIRST)
|
|
{
|
|
starting_column = lmfrc;
|
|
if (starting_column)
|
|
{
|
|
starting_column = starting_column - lmp->fixed_columns;
|
|
starting_column = (int)(((long)pos * (long)starting_column) /
|
|
(long)100);
|
|
}
|
|
starting_column += lmp->fixed_columns;
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
scroll_list(lmp, first_vis, lmp->first_vis);
|
|
lm_make_vis(lmp);
|
|
return;
|
|
}
|
|
if (nbr_columns == XI_SCROLL_PGDOWN)
|
|
{
|
|
starting_column = min(last_vis + 1, lmfrc);
|
|
starting_column = min(starting_column, lmp->nbr_columns - 1);
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
scroll_list(lmp, first_vis, lmp->first_vis);
|
|
lm_make_vis(lmp);
|
|
return;
|
|
}
|
|
if (nbr_columns == XI_SCROLL_PGUP)
|
|
{
|
|
starting_column = lm_get_left_most_far_right_col(lmp, first_vis);
|
|
starting_column = min(starting_column, lmp->nbr_columns - 1);
|
|
lmp->first_vis = starting_column;
|
|
lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
scroll_list(lmp, first_vis, lmp->first_vis);
|
|
lm_make_vis(lmp);
|
|
return;
|
|
}
|
|
lmp->first_vis += nbr_columns;
|
|
if (nbr_columns > 0)
|
|
{
|
|
lmp->first_vis = min(lmp->first_vis, lm_get_left_most_far_right_col(lmp, lmp->nbr_columns));
|
|
lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
}
|
|
else
|
|
{
|
|
lmp->first_vis = max(lmp->first_vis, lmp->fixed_columns);
|
|
lmp->first_vis = min(lmp->first_vis, lmp->nbr_columns - 1);
|
|
}
|
|
scroll_list(lmp, first_vis, lmp->first_vis);
|
|
lm_make_vis(lmp);
|
|
}
|
|
|
|
|
|
|