/*
* Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
* Copyright(c) 1995-99 Andrew Lister
* All rights reserved
* Permission to use, copy, modify and distribute this material for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of Bellcore not be used in advertising
* or publicity pertaining to this material without the specific,
* prior written permission of an authorized representative of
* Bellcore.
*
* BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
* PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
* FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE
* SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
* ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
* LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
* ING TO THE SOFTWARE.
*
* $Id: ScrollMgr.c,v 1.1 1999-09-11 01:25:38 fnevgeny Exp $
*/
/*
* ScrollMgr.c created by Andrew Lister (7 August, 1995)
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Xm/Xm.h>
#include <Xbae/MatrixP.h>
#include <Xbae/Draw.h>
#include <Xbae/Shadow.h>
#include <Xbae/ScrollMgr.h>
#include <Xbae/Utils.h>
#include <Xm/ScrollBar.h>
/*
* ScrollMgr implementation.
* When we scroll using XCopyArea, occluding windows will cause GraphicsExpose
* events to be generated, if there are no occluding windows then NoExpose
* events will be generated. The removal of occluding windows will cause Expose
* events. If a number of scrolls (XCopyAreas) occur in quick succession,
* the events will contain obsolete x/y information since our internal
* coordinates have been scrolled to a new location. The ScrollMgr
* keeps track of scrolls and offsets required to relocate the events to the
* current coordinate system.
*
* The Matrix widget has two ScrollMgrs, one for the Matrix's window
* and one for the Clip widget's window.
*
* Each widgets compress_exposures field should be XtExposeCompressSeries
* or XtExposeNoCompress.
*
* The idea behind this code is based on the PanHandler posted by Chuck Ocheret
* (chuck@fid.morgan.com)
*/
/*
* Create and initialize a ScrollMgr
*/
SmScrollMgr
xbaeSmCreateScrollMgr()
{
SmScrollMgr scrollMgr = XtNew(SmScrollMgrRec);
scrollMgr->offset_x = 0;
scrollMgr->offset_y = 0;
scrollMgr->scroll_count = 0;
scrollMgr->scroll_queue = NULL;
scrollMgr->scrolling = False;
return scrollMgr;
}
/*
* Destroy a ScrollMgr, including any queued scrolls
*/
void
xbaeSmDestroyScrollMgr(scrollMgr)
SmScrollMgr scrollMgr;
{
if (scrollMgr->scroll_queue)
{
SmScrollNode node = scrollMgr->scroll_queue->next;
while (node != scrollMgr->scroll_queue)
{
SmScrollNode d = node;
node = node->next;
XtFree((XtPointer) d);
}
XtFree((XtPointer) node);
}
XtFree((XtPointer) scrollMgr);
}
/*
* Record a new scroll request in the ScrollMgr
*/
void
xbaeSmAddScroll(scrollMgr, delta_x, delta_y)
SmScrollMgr scrollMgr;
int delta_x;
int delta_y;
{
SmScrollNode node = XtNew(SmScrollNodeRec);
node->x = delta_x;
node->y = delta_y;
scrollMgr->offset_x += delta_x;
scrollMgr->offset_y += delta_y;
scrollMgr->scroll_count++;
/*
* Insert the node at the end of the queue
*/
if (!scrollMgr->scroll_queue)
{
scrollMgr->scroll_queue = node;
node->next = node;
node->prev = node;
}
else
{
SmScrollNode last = scrollMgr->scroll_queue->prev;
last->next = node;
node->next = scrollMgr->scroll_queue;
node->prev = last;
scrollMgr->scroll_queue->prev = node;
}
}
/*
* Remove a scroll from the ScrollMgr queue
*/
void
xbaeSmRemoveScroll(scrollMgr)
SmScrollMgr scrollMgr;
{
if (scrollMgr->scroll_count)
{
SmScrollNode node = scrollMgr->scroll_queue;
scrollMgr->offset_x -= node->x;
scrollMgr->offset_y -= node->y;
/*
* Remove node from head of queue
*/
if (node->next == node)
scrollMgr->scroll_queue = NULL;
else
{
scrollMgr->scroll_queue = node->next;
node->next->prev = node->prev;
node->prev->next = node->next;
}
XtFree((XtPointer) node);
scrollMgr->scroll_count--;
}
}
/*
* Handle an expose event
*/
void
xbaeSmScrollEvent(scrollMgr, event)
SmScrollMgr scrollMgr;
XEvent *event;
{
switch (event->type)
{
case Expose:
/*
* Normal Expose event, translate it into our scrolled
* coordinate system.
*/
event->xexpose.x += scrollMgr->offset_x;
event->xexpose.y += scrollMgr->offset_y;
break;
case GraphicsExpose:
/*
* If we are not scrolling, then this must be the first
* GraphicsExpose event. Remove the corresponding scroll from the
* queue, and if we have more GraphicsExposes to come, set scrolling
* to True.
*/
if (scrollMgr->scrolling == False)
{
xbaeSmRemoveScroll(scrollMgr);
if (event->xgraphicsexpose.count != 0)
scrollMgr->scrolling = True;
}
/*
* This is the last GraphicsExpose so set scrolling to False.
*/
else if (event->xgraphicsexpose.count == 0)
scrollMgr->scrolling = False;
/*
* Translate the event into our scrolled coordinate system.
*/
event->xgraphicsexpose.x += scrollMgr->offset_x;
event->xgraphicsexpose.y += scrollMgr->offset_y;
break;
case NoExpose:
/*
* A NoExpose event means we won't be getting any GraphicsExpose
* events, so remove the scroll from the queue and set scrolling
* to False.
*/
xbaeSmRemoveScroll(scrollMgr);
scrollMgr->scrolling = False;
break;
default:
break;
}
}
/*
* Callback for vertical scrollbar
*/
/* ARGSUSED */
void
xbaeScrollVertCB(w, client_data, call_data)
Widget w;
XtPointer client_data;
XmScrollBarCallbackStruct *call_data;
{
XbaeMatrixWidget mw = (XbaeMatrixWidget) XtParent(w);
Rectangle fixed, nonfixed;
int src_y, dest_y, height;
int vert_sb_offset = VERT_SB_OFFSET(mw);
int row_height = ROW_HEIGHT(mw);
int trailing_fixed_row_label_offset = TRAILING_FIXED_ROW_LABEL_OFFSET(mw);
int trailing_fixed_column_label_offset =
TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw);
int trailing_fixed_column_width = TRAILING_FIXED_COLUMN_WIDTH(mw);
int row_label_width = ROW_LABEL_WIDTH(mw);
int fixed_row_label_offset = FIXED_ROW_LABEL_OFFSET(mw);
/*
* Not managed yet
*/
if (!XtIsRealized((Widget)mw))
return;
/*
* Didn't scroll
*/
if (call_data->value == VERT_ORIGIN(mw))
return;
/*
* Scrolled forward. We want to copy a chunk starting at src_y up
* to the top (dest_y=0)
*/
else if (call_data->value > VERT_ORIGIN(mw))
{
dest_y = 0;
src_y = (call_data->value - VERT_ORIGIN(mw)) * row_height;
height = ClipChild(mw)->core.height - src_y;
}
/*
* Scrolled backward. We want to copy a chunk starting at the top
* (src_y=0) down to dest_y.
*/
else
{
dest_y = (VERT_ORIGIN(mw) - call_data->value) * row_height;
src_y = 0;
height = ClipChild(mw)->core.height - dest_y;
}
/*
* The textField needs to scroll along with the cells.
*/
if (XtIsManaged(TextChild(mw)) &&
mw->matrix.current_row >= (int)mw->matrix.fixed_rows &&
mw->matrix.current_row < TRAILING_VERT_ORIGIN(mw))
XtMoveWidget(TextChild(mw),
TextChild(mw)->core.x, TextChild(mw)->core.y +
(VERT_ORIGIN(mw) - call_data->value) * row_height);
/*
* Now we can adjust our vertical origin
*/
VERT_ORIGIN(mw) = call_data->value;
/*
* If we scrolled more than a screenful, just clear and
* redraw the whole thing
*/
if (height <= 0)
{
/*
* Clear the whole clip window.
*/
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
0, 0,
0 /*Full Width*/, 0 /*Full Height*/,
False);
/*
* Clear the whole Left and Right Clips
*/
if (XtIsManaged(LeftClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(LeftClip(mw)),
0, 0,
0 /*Full Width*/, 0 /*Full Height*/,
False);
if (XtIsManaged(RightClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(RightClip(mw)),
0, 0,
0 /*Full Width*/, 0 /*Full Height*/,
False);
/*
* Redraw all the non-fixed cells in the clip window
*/
SETRECT(nonfixed,
0, 0,
ClipChild(mw)->core.width - 1,
ClipChild(mw)->core.height - 1);
/*
* Clear non-fixed row labels, if necessary.
* If we don't have a row label width, then
* it would clear the entire width.
*/
if (row_label_width)
XClearArea(XtDisplay(mw), XtWindow(mw),
vert_sb_offset, fixed_row_label_offset,
row_label_width - 1,
VISIBLE_HEIGHT(mw),
False);
/*
* Clear the trailing filled rows, if necessary
*/
if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw))
XClearArea(XtDisplay(mw), XtWindow(mw),
trailing_fixed_column_label_offset +
trailing_fixed_column_width,
fixed_row_label_offset,
FILL_HORIZ_WIDTH(mw),
ClipChild(mw)->core.height,
False);
/*
* Redraw non-fixed row labels and cells in fixed columns
*/
SETRECT(fixed,
vert_sb_offset, fixed_row_label_offset,
trailing_fixed_column_label_offset +
trailing_fixed_column_width - 1,
trailing_fixed_row_label_offset - 1);
}
/*
* If we scrolled less than a screenful, we want to copy as many
* pixels as we can and then clear and redraw the newly scrolled data.
*/
else
{
int y_clear = src_y > dest_y ? height : 0;
/*
* Queue this scroll with the ScrollMgr
*/
xbaeSmAddScroll(mw->matrix.clip_scroll_mgr, 0, dest_y - src_y);
/*
* Copy the non-fixed cells in the clip widget
*/
XCopyArea(XtDisplay(mw),
XtWindow(ClipChild(mw)), XtWindow(ClipChild(mw)),
mw->matrix.draw_gc,
0, src_y,
ClipChild(mw)->core.width, height,
0, dest_y);
/*
* Clear the newly scrolled chunk of the clip widget
*/
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
0, y_clear,
0 /*Full Width*/, ClipChild(mw)->core.height - height,
False);
/*
* Redraw the non-fixed cells into the new chunk
*/
SETRECT(nonfixed,
0, y_clear,
ClipChild(mw)->core.width - 1,
(y_clear + (ClipChild(mw)->core.height - height)) - 1);
/*
* Queue this scroll with the ScrollMgr
*/
xbaeSmAddScroll(mw->matrix.matrix_scroll_mgr, 0, dest_y - src_y);
/*
* Copy cells in the fixed columns on LeftClip
*/
if (XtIsManaged(LeftClip(mw)))
XCopyArea(XtDisplay(mw),
XtWindow(LeftClip(mw)), XtWindow(LeftClip(mw)),
mw->matrix.draw_gc,
0, src_y,
FIXED_COLUMN_WIDTH(mw), height,
0, dest_y);
/*
* Copy cells in the trailing fixed columns on RightClip
*/
if (XtIsManaged(RightClip(mw)))
XCopyArea(XtDisplay(mw),
XtWindow(RightClip(mw)), XtWindow(RightClip(mw)),
mw->matrix.draw_gc,
0, src_y,
trailing_fixed_column_width, height,
0, dest_y);
/*
* Translate coordinates for row labels (on the parent matrix window).
*/
src_y += fixed_row_label_offset;
dest_y += fixed_row_label_offset;
/*
* Copy the row labels
*/
if (row_label_width)
XCopyArea(XtDisplay(mw),
XtWindow(mw), XtWindow(mw),
mw->matrix.draw_gc,
vert_sb_offset, src_y,
row_label_width, height,
vert_sb_offset, dest_y);
/*
* Copy trailing filled portion of the rows if necessary
*/
if (IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw))
{
XCopyArea(XtDisplay(mw), XtWindow(mw), XtWindow(mw),
mw->matrix.draw_gc,
trailing_fixed_column_label_offset +
trailing_fixed_column_width, src_y,
FILL_HORIZ_WIDTH(mw), height,
trailing_fixed_column_label_offset +
trailing_fixed_column_width, dest_y);
}
/*
* Clear newly scrolled chunk of fixed columns on LeftClip
*/
if (XtIsManaged(LeftClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(LeftClip(mw)),
0, y_clear, 0 /* Full Width */,
ClipChild(mw)->core.height - height, False);
/*
* Clear newly scrolled chunk of trailing fixed columns on RightClip
*/
if (XtIsManaged(RightClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(RightClip(mw)),
0, y_clear, 0 /* Full Width */,
ClipChild(mw)->core.height - height, False);
/*
* Translate coordinates for row labels on Matrix
*/
y_clear += fixed_row_label_offset;
/*
* Clear the newly scrolled chunk of row labels
*/
if (row_label_width)
XClearArea(XtDisplay(mw), XtWindow(mw),
vert_sb_offset, y_clear,
row_label_width,
CLIP_VERT_VISIBLE_SPACE(mw) +
mw->manager.shadow_thickness,
False);
/*
* Clear the trailing filled rows, if necessary
*/
if ((src_y > dest_y) && IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw))
XClearArea(XtDisplay(mw), XtWindow(mw),
trailing_fixed_column_label_offset +
trailing_fixed_column_width, y_clear,
FILL_HORIZ_WIDTH(mw),
ClipChild(mw)->core.height - height,
False);
/*
* Redraw the new chunk of fixed columns and row labels
*/
SETRECT(fixed,
vert_sb_offset, y_clear,
trailing_fixed_column_label_offset +
trailing_fixed_column_width - 1,
y_clear + CLIP_VERT_VISIBLE_SPACE(mw));
}
/*
* Perform the actual redraw. The call to draw the grid shadows
* must be done after any XClearAreas() to ensure we don't redraw
* more than we have to; that is, we could put the call in the
* redraw cells routine, but we would end up occasionally redrawing
* more than once.
*/
xbaeRedrawLabelsAndFixed(mw, &fixed);
xbaeRedrawCells(mw, &nonfixed);
}
/*
* Callback for horizontal scrollbar
*/
/* ARGSUSED */
void
xbaeScrollHorizCB(w, client_data, call_data)
Widget w;
XtPointer client_data;
XmScrollBarCallbackStruct *call_data;
{
XbaeMatrixWidget mw = (XbaeMatrixWidget) XtParent(w);
Rectangle fixed, nonfixed;
int src_x, dest_x, width;
int horiz_sb_offset = HORIZ_SB_OFFSET(mw);
int trailing_fixed_row_label_offset = TRAILING_FIXED_ROW_LABEL_OFFSET(mw);
int trailing_fixed_row_height = TRAILING_FIXED_ROW_HEIGHT(mw);
/* int trailing_fixed_column_label_offset =
TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw);*/
int column_label_height = COLUMN_LABEL_HEIGHT(mw);
int fixed_column_label_offset = FIXED_COLUMN_LABEL_OFFSET(mw);
int fixed_column_width = FIXED_COLUMN_WIDTH(mw);
int vert_dead_space_height = VERT_DEAD_SPACE_HEIGHT(mw);
Boolean need_vert_fill = NEED_VERT_FILL(mw);
Boolean has_attached_trailing_rows = HAS_ATTACHED_TRAILING_ROWS(mw);
Boolean need_vert_dead_space_fill = NEED_VERT_DEAD_SPACE_FILL(mw);
/*printf("%d\n", HORIZ_ORIGIN(mw));*/
/*
* Didn't scroll
*/
if (call_data->value == HORIZ_ORIGIN(mw))
return;
/*
* Scrolled right. We want to copy a chunk starting at src_x over to
* the left (dest_x=0)
*/
else if (call_data->value > HORIZ_ORIGIN(mw))
{
dest_x = 0;
src_x = call_data->value - HORIZ_ORIGIN(mw);
width = ClipChild(mw)->core.width - src_x;
}
/*
* Scrolled left. We want to copy a chunk starting at the left (src_x=0)
* over to the right to dest_x
*/
else
{
dest_x = HORIZ_ORIGIN(mw) - call_data->value;
src_x = 0;
width = ClipChild(mw)->core.width - dest_x;
}
/*
* The textField needs to scroll along with the cells.
*/
if (XtIsManaged(TextChild(mw)) &&
mw->matrix.current_column >= (int)mw->matrix.fixed_columns &&
mw->matrix.current_column < TRAILING_HORIZ_ORIGIN(mw))
{
XtMoveWidget(TextChild(mw),
TextChild(mw)->core.x + (HORIZ_ORIGIN(mw) -
call_data->value),
TextChild(mw)->core.y);
}
/*
* Now we can adjust our horizontal origin
*/
HORIZ_ORIGIN(mw) = call_data->value;
mw->matrix.left_column = xbaeXtoCol(mw, fixed_column_width +
HORIZ_ORIGIN(mw)) -
mw->matrix.fixed_columns;
if (!XtIsRealized((Widget)mw))
return;
/*
* If we scrolled more than a screenful, just clear and
* redraw the whole thing
*/
if (width <= 0)
{
/*
* Clear the whole clip window
*/
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
0, 0,
0 /* Full Width */, 0 /* Full Height */,
False);
/*
* Clear the whole Top and Bottom Clips
*/
if (XtIsManaged(TopClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(TopClip(mw)),
0, 0,
0 /*Full Width*/, 0 /*Full Height*/,
False);
if (XtIsManaged(BottomClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(BottomClip(mw)),
0, 0,
0 /*Full Width*/, 0 /*Full Height*/,
False);
/*
* Redraw all the non-fixed cells in the clip window
*/
SETRECT(nonfixed,
0, 0,
ClipChild(mw)->core.width - 1,
ClipChild(mw)->core.height - 1);
/*
* Clear the non-fixed column labels
*/
if (column_label_height)
XClearArea(XtDisplay(mw), XtWindow(mw),
fixed_column_label_offset, horiz_sb_offset,
VISIBLE_WIDTH(mw),
column_label_height - 1, False);
/*
* Clear the trailing fixed column
*/
if (IN_GRID_COLUMN_MODE(mw))
{
if (need_vert_fill && (! has_attached_trailing_rows))
XClearArea(XtDisplay(mw), XtWindow(mw),
fixed_column_label_offset,
trailing_fixed_row_label_offset +
trailing_fixed_row_height,
MATRIX_HORIZ_VISIBLE_SPACE(mw), 0, False);
if (need_vert_dead_space_fill)
XClearArea(XtDisplay(mw), XtWindow(mw),
fixed_column_label_offset,
UNATTACHED_TRAILING_ROWS_OFFSET(mw),
MATRIX_HORIZ_VISIBLE_SPACE(mw), 0, False);
}
/*
* Redraw non-fixed column labels and cells in fixed rows
*/
SETRECT(fixed,
fixed_column_label_offset, horiz_sb_offset,
fixed_column_label_offset + CLIP_HORIZ_VISIBLE_SPACE(mw),
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
}
/*
* If we scrolled less than a screenful, we want to copy as many
* pixels as we can and then clear and redraw the newly scrolled data.
*/
else
{
int x_clear = src_x > dest_x ? width : 0;
int unattached_trailing_rows_offset =
UNATTACHED_TRAILING_ROWS_OFFSET(mw);
/*
* Queue this scroll with the ScrollMgr
*/
xbaeSmAddScroll(mw->matrix.clip_scroll_mgr, dest_x - src_x, 0);
/*
* Copy the non-fixed cells in the clip widget
*/
XCopyArea(XtDisplay(mw),
XtWindow(ClipChild(mw)), XtWindow(ClipChild(mw)),
mw->matrix.draw_gc, src_x, 0, width,
ClipChild(mw)->core.height, dest_x, 0);
/*
* Clear the newly scrolled chunk of the clip widget
*/
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
x_clear, 0,
ClipChild(mw)->core.width - width, 0 /*Full Height*/,
False);
/*
* Redraw the non-fixed cells into the new chunk
*/
SETRECT(nonfixed,
x_clear, horiz_sb_offset,
(x_clear + (ClipChild(mw)->core.width - width)) - 1,
ClipChild(mw)->core.height - 1);
/*
* Queue this scroll with the ScrollMgr
*/
xbaeSmAddScroll(mw->matrix.matrix_scroll_mgr, dest_x - src_x, 0);
/*
* Copy cells across in fixed rows on TopClip
*/
if (XtIsManaged(TopClip(mw)))
XCopyArea(XtDisplay(mw),
XtWindow(TopClip(mw)), XtWindow(TopClip(mw)),
mw->matrix.draw_gc, src_x, 0,
width, FIXED_ROW_HEIGHT(mw), dest_x, 0);
/*
* Copy cells across in trailing fixed rows on BottomClip
*/
if (XtIsManaged(BottomClip(mw)))
XCopyArea(XtDisplay(mw),
XtWindow(BottomClip(mw)), XtWindow(BottomClip(mw)),
mw->matrix.draw_gc, src_x, horiz_sb_offset, width,
trailing_fixed_row_height, dest_x, 0);
/*
* Translate coordinates for column labels on the Matrix.
*/
src_x += fixed_column_label_offset;
dest_x += fixed_column_label_offset;
/*
* Copy the column labels
*/
if (column_label_height)
XCopyArea(XtDisplay(mw),
XtWindow(mw), XtWindow(mw),
mw->matrix.draw_gc,
src_x, horiz_sb_offset,
width, column_label_height,
dest_x, horiz_sb_offset);
/*
* Copy trailing filled portion of the columns if necessary
*/
if (IN_GRID_COLUMN_MODE(mw))
{
if (need_vert_fill && (! has_attached_trailing_rows))
XCopyArea(XtDisplay(mw), XtWindow(mw), XtWindow(mw),
mw->matrix.draw_gc,
src_x, trailing_fixed_row_label_offset +
trailing_fixed_row_height,
width, FILL_VERT_HEIGHT(mw),
dest_x, trailing_fixed_row_label_offset +
trailing_fixed_row_height);
if (need_vert_dead_space_fill)
XCopyArea(XtDisplay(mw), XtWindow(mw), XtWindow(mw),
mw->matrix.draw_gc,
src_x, unattached_trailing_rows_offset,
width, vert_dead_space_height,
dest_x, unattached_trailing_rows_offset);
}
/*
* Clear newly scrolled chunk of fixed rows on TopClip
*/
if (XtIsManaged(TopClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(TopClip(mw)),
x_clear, 0,
ClipChild(mw)->core.width - width, 0 /* Full Height */,
False);
/*
* Clear newly scrolled chunk of trailing fixed rows on BottomClip
*/
if (XtIsManaged(BottomClip(mw)))
XClearArea(XtDisplay(mw), XtWindow(BottomClip(mw)),
x_clear, 0,
ClipChild(mw)->core.width - width, 0 /* Full Height */,
False);
/*
* Translate coordinates for row labels on Matrix
*/
x_clear += fixed_column_label_offset;
/*
* Clear the newly scrolled chunk of column labels
*/
if (column_label_height)
XClearArea(XtDisplay(mw), XtWindow(mw),
x_clear, horiz_sb_offset,
ClipChild(mw)->core.width - width,
column_label_height,
False);
/*
* Clear the dead space if necessary
*/
if (IN_GRID_COLUMN_MODE(mw) && need_vert_dead_space_fill)
XClearArea(XtDisplay(mw), XtWindow(mw),
x_clear,unattached_trailing_rows_offset,
ClipChild(mw)->core.width - width,
vert_dead_space_height, False);
/*
* Redraw the new chunk of fixed rows and column labels
*/
SETRECT(fixed,
x_clear, horiz_sb_offset,
x_clear + CLIP_HORIZ_VISIBLE_SPACE(mw),
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
}
/*
* Perform the actual redraw. The call to draw the grid shadows
* must be done after any XClearAreas() to ensure we don't redraw
* more than we have to; that is, we could put the call in the
* redraw cells routine, but we would end up occasionally redrawing
* more than once.
*/
xbaeRedrawLabelsAndFixed(mw, &fixed);
xbaeRedrawCells(mw, &nonfixed);
}
/*
* Redraw all cells in the clip widget damaged by the passed Rectangle.
* The Rectangle must be within the bounds of the cells. These are the
* non-fixed cells.
*/
void
xbaeRedrawCells(mw, expose)
XbaeMatrixWidget mw;
Rectangle *expose;
{
int startCol, endCol, startRow, endRow, i, j;
Rectangle rect;
Boolean set_mask = False;
if ((mw->matrix.disable_redisplay) || (!mw->matrix.rows) ||
(!mw->matrix.columns))
return;
/*
* Translate the 'expose' Rectangle to take into account the
* fixed rows or columns.
*/
SETRECT(rect,
expose->x1 + FIXED_COLUMN_WIDTH(mw),
expose->y1 + FIXED_ROW_HEIGHT(mw),
expose->x2 + FIXED_COLUMN_WIDTH(mw),
expose->y2 + FIXED_ROW_HEIGHT(mw));
/*
* Calculate the starting and ending rows/columns of the cells
* which must be redrawn.
*/
startCol = xbaeXtoCol(mw, rect.x1 + HORIZ_ORIGIN(mw));
endCol = xbaeXtoCol(mw, rect.x2 + HORIZ_ORIGIN(mw));
startRow = YtoRow(mw, rect.y1 + mw->matrix.first_row_offset) +
VERT_ORIGIN(mw);
endRow = YtoRow(mw, rect.y2 + mw->matrix.first_row_offset) +
VERT_ORIGIN(mw);
SANITY_CHECK_ROW(mw, startRow);
SANITY_CHECK_ROW(mw, endRow);
SANITY_CHECK_COLUMN(mw, startCol);
SANITY_CHECK_COLUMN(mw, endCol);
/*
* Redraw all cells which were exposed.
*/
for (i = startRow; i <= endRow; i++)
{
/*
* If we need to clip the vertical fill
*/
if ((!set_mask) && IN_GRID_COLUMN_MODE(mw) &&
((mw->matrix.rows - 1) == i) && NEED_VERT_FILL(mw))
{
set_mask = True;
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
}
for (j = startCol; j <= endCol; j++)
xbaeDrawCell(mw, i, j);
}
if (set_mask)
xbaeSetClipMask(mw, CLIP_NONE);
}
/*
* Redraw the row and column labels and the cells in fixed rows/columns
* that are overlapped by the Rectangle argument.
*/
void
xbaeRedrawLabelsAndFixed(mw, expose)
XbaeMatrixWidget mw;
Rectangle *expose;
{
/*
* Set up some local variables to avoid calling too many macros :p
*/
int horiz_sb_offset = HORIZ_SB_OFFSET(mw);
int vert_sb_offset = VERT_SB_OFFSET(mw);
int column_label_height = COLUMN_LABEL_HEIGHT(mw);
int row_label_offset = ROW_LABEL_OFFSET(mw);
int row_label_width = ROW_LABEL_WIDTH(mw);
int fixed_row_label_offset = FIXED_ROW_LABEL_OFFSET(mw);
int trailing_fixed_row_label_offset = TRAILING_FIXED_ROW_LABEL_OFFSET(mw);
int trailing_fixed_row_height = TRAILING_FIXED_ROW_HEIGHT(mw);
int fixed_column_label_offset = FIXED_COLUMN_LABEL_OFFSET(mw);
int fixed_column_width = FIXED_COLUMN_WIDTH(mw);
int trailing_fixed_column_label_offset =
TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw);
int trailing_fixed_column_width = TRAILING_FIXED_COLUMN_WIDTH(mw);
int column_label_offset = COLUMN_LABEL_OFFSET(mw);
Boolean need_vert_fill = NEED_VERT_FILL(mw);
Boolean has_attached_trailing_rows = HAS_ATTACHED_TRAILING_ROWS(mw);
if (mw->matrix.disable_redisplay)
return;
/*
* Handle the row labels that are in fixed rows
*/
if (mw->matrix.rows && mw->matrix.fixed_rows && mw->matrix.row_labels)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the fixed row labels
*/
SETRECT(rect, vert_sb_offset, row_label_offset,
vert_sb_offset + row_label_width - 1,
fixed_row_label_offset - 1);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endRow, i;
/*
* Intersect the fixed-row-labels Rectangle with the expose
* Rectangle along the Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
Y_INTERSECT(rect, *expose, intersect);
/*
* Redraw each label that was intersected
*/
endRow = YtoRow(mw, intersect.y2 + mw->matrix.first_row_offset);
SANITY_CHECK_ROW(mw, endRow);
for (i = YtoRow(mw, intersect.y1 + mw->matrix.first_row_offset),
SANITY_CHECK_ROW(mw, i);
i <= endRow; i++)
xbaeDrawRowLabel(mw, i, False);
}
}
/*
* Handle the row labels that are in trailing fixed rows
*/
if (mw->matrix.rows && mw->matrix.trailing_fixed_rows &&
mw->matrix.row_labels)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the fixed row labels
*/
SETRECT(rect, vert_sb_offset, trailing_fixed_row_label_offset,
vert_sb_offset + row_label_width - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endRow, i;
/*
* Intersect the fixed-row-labels Rectangle with the expose
* Rectangle along the Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
Y_INTERSECT(rect, *expose, intersect);
/*
* Redraw each label that was intersected
*/
endRow = YtoRow(mw, intersect.y2) + TRAILING_VERT_ORIGIN(mw);
SANITY_CHECK_ROW(mw, endRow);
for (i = YtoRow(mw, intersect.y1) + TRAILING_VERT_ORIGIN(mw),
SANITY_CHECK_ROW(mw, i); i <= endRow; i++)
xbaeDrawRowLabel(mw, i, False);
}
}
/*
* Handle row labels that aren't in fixed rows
*/
if (mw->matrix.row_labels && mw->matrix.rows)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the non-fixed row labels
*/
SETRECT(rect, vert_sb_offset, fixed_row_label_offset,
vert_sb_offset + row_label_width - 1,
fixed_row_label_offset + VISIBLE_HEIGHT(mw) - 1);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endRow, i;
/*
* Intersect the fixed-row-labels Rectangle with the expose
* Rectangle along the Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
Y_INTERSECT(rect, *expose, intersect);
/*
* Translate 'intersect' to take into account any fixed rows.
* This gets it back into the coord system expected by YtoRow().
*/
intersect.y1 += FIXED_ROW_HEIGHT(mw);
intersect.y2 += FIXED_ROW_HEIGHT(mw);
/*
* Redraw each label that was intersected
*/
endRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw);
SANITY_CHECK_ROW(mw, endRow);
for (i = YtoRow(mw, intersect.y1) + VERT_ORIGIN(mw),
SANITY_CHECK_ROW(mw, i); i <= endRow; i++)
xbaeDrawRowLabel(mw, i, False);
}
}
/*
* Handle the column labels that are in fixed columns
*/
if (mw->matrix.columns && mw->matrix.fixed_columns &&
mw->matrix.column_labels)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the portion of the column labels
* that are in fixed columns
*/
SETRECT(rect,
column_label_offset, horiz_sb_offset,
fixed_column_label_offset - 1,
horiz_sb_offset + column_label_height - 1);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endCol, i;
/*
* Intersect the fixed-column-labels Rectangle with the expose
* Rectangle along the X axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
X_INTERSECT(rect, *expose, intersect);
/*
* Redraw each label that was intersected
*/
endCol = xbaeXtoCol(mw, intersect.x2);
SANITY_CHECK_COLUMN(mw, endCol);
for (i = xbaeXtoCol(mw, intersect.x1), SANITY_CHECK_COLUMN(mw, i);
i <= endCol; i++)
xbaeDrawColumnLabel(mw, i, False);
}
}
/*
* Handle the column labels that are in trailing fixed columns
*/
if (mw->matrix.columns && mw->matrix.trailing_fixed_columns &&
mw->matrix.column_labels)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the portion of the column labels
* that are in fixed columns
*/
SETRECT(rect,
trailing_fixed_column_label_offset, horiz_sb_offset,
trailing_fixed_column_label_offset +
trailing_fixed_column_width,
horiz_sb_offset + column_label_height);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endCol, i;
/*
* Intersect the fixed-column-labels Rectangle with the expose
* Rectangle along the X axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
X_INTERSECT(rect, *expose, intersect);
/*
* Redraw each label that was intersected
*/
endCol = xbaeXtoTrailingCol(mw, intersect.x2);
SANITY_CHECK_COLUMN(mw, endCol);
for (i = xbaeXtoTrailingCol(mw, intersect.x1),
SANITY_CHECK_COLUMN(mw, i); i <= endCol; i++)
xbaeDrawColumnLabel(mw, i, False);
}
}
/*
* Handle column labels that aren't in fixed columns
*/
if (mw->matrix.column_labels && mw->matrix.columns)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the non-fixed column labels
*/
SETRECT(rect,
fixed_column_label_offset, horiz_sb_offset,
fixed_column_label_offset + VISIBLE_WIDTH(mw) - 1,
horiz_sb_offset + column_label_height - 1);
/*
* If the expose Rectangle overlaps, then some labels must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int endCol, i;
/*
* Intersect the non-fixed-column-labels Rectangle with the expose
* Rectangle along the X axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
X_INTERSECT(rect, *expose, intersect);
/*
* Translate 'intersect' to take into account any fixed columns.
* This gets it back into the coord system expected by XtoCol().
*/
intersect.x1 += fixed_column_width;
intersect.x2 += fixed_column_width;
/*
* Redraw each label that was intersected
*/
endCol = xbaeXtoCol(mw, intersect.x2 + HORIZ_ORIGIN(mw));
SANITY_CHECK_COLUMN(mw, endCol);
for (i = xbaeXtoCol(mw, intersect.x1 + HORIZ_ORIGIN(mw)),
SANITY_CHECK_COLUMN(mw, i); i <= endCol; i++)
xbaeDrawColumnLabel(mw, i, False);
}
}
/*
* Handle cells in fixed rows except those also in fixed columns
*/
if (mw->matrix.rows && mw->matrix.columns && mw->matrix.fixed_rows)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the cells in fixed rows
*/
SETRECT(rect,
fixed_column_label_offset, row_label_offset,
fixed_column_label_offset + VISIBLE_WIDTH(mw) - 1,
fixed_row_label_offset - 1);
/*
* If the expose Rectangle overlaps, then some cells must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int startCol, endCol, startRow, endRow, i, j;
/*
* Intersect the fixed-cells Rectangle with the expose
* Rectangle along the X and Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
INTERSECT(rect, *expose, intersect);
intersect.x1 += fixed_column_width;
intersect.x2 += fixed_column_width;
/*
* Get starting and ending rows/columns. Always take into
* account the scrolling origins for the columns; for rows
* only if we are fixed in that dimension.
*/
startCol = xbaeXtoCol(mw, intersect.x1 + HORIZ_ORIGIN(mw));
endCol = xbaeXtoCol(mw, intersect.x2 + HORIZ_ORIGIN(mw));
startRow = YtoRow(mw, intersect.y1) +
(mw->matrix.fixed_rows
? 0
: VERT_ORIGIN(mw));
endRow = YtoRow(mw, intersect.y2) +
(mw->matrix.fixed_rows
? 0
: VERT_ORIGIN(mw));
/*
* Redraw each cell that was intersected
*/
SANITY_CHECK_ROW(mw, startRow);
SANITY_CHECK_ROW(mw, endRow);
SANITY_CHECK_COLUMN(mw, startCol);
SANITY_CHECK_COLUMN(mw, endCol);
for (i = startRow; i <= endRow; i++)
for (j = startCol; j <= endCol; j++)
xbaeDrawCell(mw, i, j);
}
}
/*
* Handle cells in trailing fixed rows except those also in fixed columns
*/
if (mw->matrix.rows && mw->matrix.columns &&
mw->matrix.trailing_fixed_rows)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the cells in trailing fixed rows
*/
SETRECT(rect, fixed_column_label_offset,
trailing_fixed_row_label_offset,
fixed_column_label_offset + VISIBLE_WIDTH(mw) - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
/*
* If the expose Rectangle overlaps, then some cells must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int startCol, endCol, startRow, endRow, i, j;
/*
* Intersect the fixed-cells Rectangle with the expose
* Rectangle along the X and Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
INTERSECT(rect, *expose, intersect);
intersect.x1 += fixed_column_width;
intersect.x2 += fixed_column_width;
/*
* Get starting and ending rows/columns. Always take into
* account the scrolling origins for the columns and never
* for the rows.
*/
startCol = xbaeXtoCol(mw, intersect.x1 + HORIZ_ORIGIN(mw));
endCol = xbaeXtoCol(mw, intersect.x2 + HORIZ_ORIGIN(mw));
startRow = YtoRow(mw, intersect.y1) + TRAILING_VERT_ORIGIN(mw);
endRow = YtoRow(mw, intersect.y2) + TRAILING_VERT_ORIGIN(mw);
/*
* Redraw each cell that was intersected
*/
SANITY_CHECK_ROW(mw, startRow);
SANITY_CHECK_ROW(mw, endRow);
SANITY_CHECK_COLUMN(mw, startCol);
SANITY_CHECK_COLUMN(mw, endCol);
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
for (i = startRow; i <= endRow; i++)
for (j = startCol; j <= endCol; j++)
xbaeDrawCell(mw, i, j);
xbaeSetClipMask(mw, CLIP_NONE);
}
}
/*
* Handle cells in fixed columns
*/
if (mw->matrix.rows && mw->matrix.columns && mw->matrix.fixed_columns)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the cells in fixed columns
*/
SETRECT(rect,
column_label_offset, row_label_offset,
fixed_column_label_offset - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
/*
* If the expose Rectangle overlaps, then some cells must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int startCol, endCol, startRow, endRow, skipRow = -1, i, j;
Boolean redrawFixedRows, redrawTrailingFixedRows;
unsigned int clip_reason = CLIP_NONE;
/*
* Intersect the fixed-cells Rectangle with the expose
* Rectangle along the X and Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
INTERSECT(rect, *expose, intersect);
/*
* If we have any fixed rows, we might need to redraw the cells
* located in the intersection of the fixed rows and columns.
* These cells may force use to be different than our current
* VERT_ORIGIN.
*/
redrawFixedRows = redrawTrailingFixedRows = False;
if (mw->matrix.fixed_rows)
{
clip_reason = CLIP_FIXED_COLUMNS;
SETRECT(rect,
column_label_offset, row_label_offset,
fixed_column_label_offset - 1,
fixed_row_label_offset - 1);
if (OVERLAP(*expose, rect))
redrawFixedRows = True;
}
if (mw->matrix.trailing_fixed_rows)
{
clip_reason = CLIP_FIXED_COLUMNS;
SETRECT(rect,
column_label_offset,
trailing_fixed_row_label_offset,
fixed_column_label_offset - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
if (OVERLAP(*expose, rect))
redrawTrailingFixedRows = True;
}
if (CLIP_NONE != clip_reason)
xbaeSetClipMask(mw, clip_reason);
/*
* Get starting and ending rows/columns. Never take into
* account the scrolling origins for the rows; for columns
* only if we are fixed in that dimension.
*/
startCol = xbaeXtoCol(mw, intersect.x1 +
(mw->matrix.fixed_columns
? 0
: HORIZ_ORIGIN(mw)));
endCol = xbaeXtoCol(mw, intersect.x2 +
(mw->matrix.fixed_columns
? 0
: HORIZ_ORIGIN(mw)));
startRow = redrawFixedRows ? 0 : YtoRow(mw, intersect.y1) +
VERT_ORIGIN(mw);
if (redrawTrailingFixedRows)
{
skipRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw) -
mw->matrix.trailing_fixed_rows + 1;
endRow = mw->matrix.rows - 1;
}
else
endRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw);
/*
* Redraw each cell that was intersected
*/
SANITY_CHECK_ROW(mw, startRow);
SANITY_CHECK_ROW(mw, endRow);
SANITY_CHECK_COLUMN(mw, startCol);
SANITY_CHECK_COLUMN(mw, endCol);
for (i = startRow; i <= endRow; i++)
for (j = startCol; j <= endCol; j++)
{
/*
* If we had to redraw cells located in both fixed rows
* and columns, when we are done redrawing those cells,
* we need to skip to the correct non-fixed row to draw,
* or alternatively, jump to the trailing fixed row
* to draw.
*/
if (redrawFixedRows && i == mw->matrix.fixed_rows)
i += VERT_ORIGIN(mw);
if (redrawTrailingFixedRows && i == skipRow &&
endRow > skipRow && i < TRAILING_VERT_ORIGIN(mw))
i = TRAILING_VERT_ORIGIN(mw);
/*
* If we need to clip the vertical fill
*/
if (!(clip_reason & CLIP_TRAILING_FIXED_ROWS) &&
IN_GRID_COLUMN_MODE(mw) &&
((mw->matrix.rows - 1) == i) &&
(need_vert_fill && (! has_attached_trailing_rows)))
{
clip_reason |= CLIP_FIXED_COLUMNS |
CLIP_TRAILING_FIXED_ROWS;
xbaeSetClipMask(mw, clip_reason);
}
xbaeDrawCell(mw, i, j);
}
if (CLIP_NONE != clip_reason)
xbaeSetClipMask(mw, CLIP_NONE);
}
}
/*
* Handle cells in trailing fixed columns
*/
if (mw->matrix.rows && mw->matrix.columns &&
mw->matrix.trailing_fixed_columns)
{
Rectangle rect;
/*
* Get the Rectangle enclosing the cells in trailing fixed columns
*/
SETRECT(rect,
trailing_fixed_column_label_offset, row_label_offset,
trailing_fixed_column_label_offset +
trailing_fixed_column_width - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
/*
* If the expose Rectangle overlaps, then some cells must be redrawn
*/
if (OVERLAP(*expose, rect))
{
Rectangle intersect;
int startCol, endCol, startRow, endRow, skipRow = -1, i, j;
Boolean redrawFixedRows, redrawTrailingFixedRows;
unsigned int clip_reason = CLIP_NONE;
/*
* Intersect the fixed-cells Rectangle with the expose
* Rectangle along the X and Y axis. The resulting Rectangle will
* be in 'rect's coordinate system.
*/
INTERSECT(rect, *expose, intersect);
/*
* If we have any fixed rows, we might need to redraw the cells
* located in the intersection of the fixed rows and columns.
* These cells may force us to be different than our current
* VERT_ORIGIN.
*/
redrawFixedRows = redrawTrailingFixedRows = False;
if (mw->matrix.fixed_rows)
{
clip_reason = CLIP_FIXED_COLUMNS;
SETRECT(rect, trailing_fixed_column_label_offset,
row_label_offset,
trailing_fixed_column_label_offset +
trailing_fixed_column_width - 1,
fixed_row_label_offset - 1);
if (OVERLAP(*expose, rect))
redrawFixedRows = True;
}
if (mw->matrix.trailing_fixed_rows)
{
clip_reason = CLIP_FIXED_COLUMNS;
SETRECT(rect, trailing_fixed_column_label_offset,
trailing_fixed_row_label_offset,
trailing_fixed_column_label_offset +
trailing_fixed_column_width - 1,
trailing_fixed_row_label_offset +
trailing_fixed_row_height - 1);
if (OVERLAP(*expose, rect))
redrawTrailingFixedRows = True;
}
if (CLIP_NONE != clip_reason)
xbaeSetClipMask(mw, clip_reason);
/*
* Get starting and ending rows/columns. Never take into
* account the scrolling origins for the rows; for columns
* only if we are fixed in that dimension.
*/
startCol = xbaeXtoTrailingCol(mw, intersect.x1);
endCol = xbaeXtoTrailingCol(mw, intersect.x2);
startRow = redrawFixedRows ? 0 : YtoRow(mw, intersect.y1) +
VERT_ORIGIN(mw);
if (redrawTrailingFixedRows)
{
skipRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw) -
mw->matrix.trailing_fixed_rows + 1;
endRow = mw->matrix.rows - 1;
}
else
endRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw);
/*
* Redraw each cell that was intersected
*/
SANITY_CHECK_ROW(mw, startRow);
SANITY_CHECK_ROW(mw, endRow);
SANITY_CHECK_COLUMN(mw, startCol);
SANITY_CHECK_COLUMN(mw, endCol);
for (i = startRow; i <= endRow; i++)
for (j = startCol; j <= endCol; j++)
{
/*
* If we had to redraw cells located in both fixed rows
* and columns, when we are done redrawing those cells,
* we need to skip to the correct non-fixed row to draw
*/
if (redrawFixedRows && (i == mw->matrix.fixed_rows))
i += VERT_ORIGIN(mw);
if (redrawTrailingFixedRows && (i == skipRow) &&
(endRow > skipRow))
i = TRAILING_VERT_ORIGIN(mw);
/*
* If we need to clip the vertical fill
*/
if (!(clip_reason & CLIP_TRAILING_FIXED_ROWS) &&
IN_GRID_COLUMN_MODE(mw) &&
((mw->matrix.rows - 1) == i) &&
(need_vert_fill && (! has_attached_trailing_rows)))
{
clip_reason |= CLIP_TRAILING_FIXED_COLUMNS |
CLIP_TRAILING_FIXED_ROWS;
xbaeSetClipMask(mw, clip_reason);
}
xbaeDrawCell(mw, i, j);
}
if (CLIP_NONE != clip_reason)
xbaeSetClipMask(mw, CLIP_NONE);
}
}
/*
* Draw a shadow just inside row/column labels and around outer edge
* of clip widget. We can't use height of clip widget because it is
* truncated to nearest row. We use cell_visible_height instead.
*/
if (mw->manager.shadow_thickness)
{
Dimension width, height;
if (! mw->matrix.fill)
{
width = ClipChild(mw)->core.width + fixed_column_width +
trailing_fixed_column_width +
2 * mw->manager.shadow_thickness;
height = mw->matrix.cell_visible_height + FIXED_ROW_HEIGHT(mw) +
trailing_fixed_row_height +
2 * mw->manager.shadow_thickness;
}
else
{
width = mw->core.width - row_label_width -
VERT_SB_SPACE(mw);
height = mw->core.height - column_label_height -
HORIZ_SB_SPACE(mw) ;
}
DRAW_SHADOW(XtDisplay(mw), XtWindow(mw),
mw->manager.top_shadow_GC,
mw->manager.bottom_shadow_GC,
mw->manager.shadow_thickness,
row_label_width + vert_sb_offset,
column_label_height + horiz_sb_offset,
width, height, mw->matrix.shadow_type);
}
}
syntax highlighted by Code2HTML, v. 0.9.1