Example 10-1. The scroll_cells.c program (continued)
x = (int)xv_get(horiz_scrollbar, SCROLLBAR_VIEW_START);
y = (int)xv_get(vert_scrollbar, SCROLLBAR_VIEW_START);
for (xrects->count--; xrects->count >= 0; xrects->count--) {
printf("top–left cell = %d, %d –– %d,%d %d,%d0, x+1, y+1,
xrects->rect_array[xrects->count].x,
xrects->rect_array[xrects->count].y,
xrects->rect_array[xrects->count].width,
xrects->rect_array[xrects->count].height);
XCopyPlane(dpy, cell_map, win, gc,
xrects->rect_array[xrects->count].x,
xrects->rect_array[xrects->count].y,
xrects->rect_array[xrects->count].width,
xrects->rect_array[xrects->count].height,
xrects->rect_array[xrects->count].x,
xrects->rect_array[xrects->count].y, 1L);
}
}
10.4 Managing Your Own Scrollbar
A scrollbar may have delayed binding—that is, it may be created without an owner and
attached to objects that were created separately.
In most cases, you would probably never need to create a scrollbar that was not part of a text
subwindow or a canvas. These two packages handle all of the dirty work involved in manag-
ing and maintaining the types of attributes mentioned above. If you are using the CANVAS or
TEXTSW packages, you do not need to worry about any of this. If you do try to create your
own scrollbars and have them manage your own windows, you will probably find that you
will have reinvented the wheel in the form of the
CANVAS package.
If you are going to attempt this type of activity, you will need to follow these guidelines:
• Maintain the relationship between the object to be scrolled and the scrollbar itself. This
includes using all the scrollbar attributes mentioned in Section 10.1, “Creating
Scrollbars.”
• Manage geometry (size, position, and orientation) of the scrollbar. You must place the
scrollbars in the appropriate places around the object you intend to scroll. Typically, the
scrollbars should match the width and height of the object being scrolled.
• Install appropriate
SCROLLBAR_NORMALIZE_PROC and SCROLLBAR_COMPUTE_
SCROLL_PROC
procedures to change the display of the scrolling object.
Scrollbars
Scrollbars 263
10.4.1 Monitoring When Scrollbar Events Occur
When events take place in the scrollbar, the scrollbar normally interprets these events as
scrolling events and adjusts itself appropriately. Since scrollbars are attached to objects such
as canvases and text subwindows, those objects are also notified of the scrolling event so they
can control the display of the data within their associated windows. For example, a canvas
may get a SCROLLBAR_REQUEST event indicating that the user has initiated a scrolling action
and that the object associated with the scrollbar needs to change its display by the requested
amount.
The object to which the scrollbar is attached is set using the scrollbar attribute,
SCROLLBAR_NOTIFY_CLIENT.* The internals to the scrollbar attempt to get information
from this client, such as its size. For canvases, the view window is used. Since you normally
query for user events on the canvas’s paint window, this doesn’t interfere with the scrollbar
processing and also explains why your event handlers never see this event. For text subwin-
dows, programmers normally do not concern themselves with events, so again, scrollbar pro-
cessing is not affected.
If you are interested in managing the scrolling mechanisms of a scrollbar, or if all you need is
to be notified of when the user invokes scrolling actions, you can install an event-interposing
function on the scrollbar itself. This involves using the routine notify_inter-
pose_event_func() discussed in Chapter 20, The Notifier. You can set one up in the
following way:
Canvas canvas;
Scrollbar sb;
Notify_func monitor_scroll();
...
canvas = xv_create(frame, CANVAS, NULL);
sb = xv_create(canvas, SCROLLBAR, NULL);
notify_interpose_event_func( xv_get(sb, SCROLLBAR_NOTIFY_CLIENT),
monitor_scroll, NOTIFY_SAFE);
...
When the user invokes any scrolling events in the scrollbar, the function monitor_scroll
is called with the event type set to SCROLLBAR_REQUEST.
Example 10-2 demonstrates how this is done in an application. By default, a canvas is set up
of size 1000x1000 and a scrollbar attached. When the user scrolls the canvas, the function
monotir_scroll() is called, which prints information about how much the canvas
scrolled.
Example 10-2. The scrollto.c program
/* scroll_to.c -- demonstrate how to monitor the scrolling
* requests invoked by the user. Requests can be monitored,
* ignored or changed programmatically. This program creates
*While this is a settable attribute, it is not recommended that you change the notify client for scrollbars for the current
release.
264 XView Programming Manual
Example 10-2. The scrollto.c program (continued)
* a canvas window by default or a textsw with the -textsw
* command line option. Both contain a scrollbar.
*/
#include <stdio.h>
#include <xview/xview.h>
#include <xview/textsw.h>
#include <xview/canvas.h>
#include <xview/scrollbar.h>
main(argc, argv)
int argc;
char *argv[ ];
{
Frame frame;
Textsw textsw;
Canvas canvas;
Scrollbar sbar;
Notify_value monitor_scroll();
(void) xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
frame = xv_create(NULL, FRAME, NULL);
if (argc > 1 && !strcmp(argv[1 ], "-textsw")) {
textsw = xv_create(frame, TEXTSW,
TEXTSW_FILE_CONTENTS, "/etc/termcap",
NULL);
sbar = xv_get(textsw, TEXTSW_SCROLLBAR);
} else {
canvas = xv_create(frame, CANVAS,
CANVAS_WIDTH, 1000,
CANVAS_HEIGHT, 1000,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, FALSE,
NULL);
sbar = xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
SCROLLBAR_PIXELS_PER_UNIT, 10,
NULL);
}
notify_interpose_event_func(xv_get(sbar, SCROLLBAR_NOTIFY_CLIENT),
monitor_scroll, NOTIFY_SAFE);
xv_main_loop(frame);
}
/*
* To change the behavior of the scrolling of the canvas, do not pass
* on the event via notify_next_event_func() when the event type is
* SCROLLBAR_REQUEST.
*/
Notify_value
monitor_scroll(client, event, sbar, type)
Notify_client client;
Event *event;
Scrollbar sbar;
Scrollbars
Scrollbars 265
Example 10-2. The scrollto.c program (continued)
Notify_event_type type;
{
int view_start, last_view_start, pixels_per, is_neg = 0, total;
if (event_id(event) == SCROLLBAR_REQUEST) {
view_start = (int)xv_get(sbar, SCROLLBAR_VIEW_START);
last_view_start = (int)xv_get(sbar, SCROLLBAR_LAST_VIEW_START);
pixels_per = (int)xv_get(sbar, SCROLLBAR_PIXELS_PER_UNIT);
if ((total = view_start - last_view_start) < 0)
total = -total, is_neg = 1;
printf("scrolled from %d to %d: %d pixels (%d units) %s\n",
last_view_start, view_start, pixels_per * total, total,
is_neg? "up" : "down");
}
return notify_next_event_func(client, event, sbar, type);
}
If the command-line option -textsw is given, a text subwindow is used instead of a canvas.
The application can change the scrolling behavior by not calling the function
notify_next_event_func(). It can choose to set the scrollbar to any position it
desires via xv_set() and the appropriate attributes, or it can ignore the scroll request
entirely. In any event, the function should return either
NOTIFY_DONE or the return value of
notify_next_event_func().
The parameters to monitor_scroll() include the client (the object set by
SCROLLBAR_NOTIFY_CLIENT), as well as the event (which is probably
SCROLLBAR_REQUEST), the scrollbar itself, and an unused type parameter indicating
whether this was called via NOTIFY_SAFE or NOTIFY_IMMEDIATE.
10.4.2 Providing a Scrollbar Compute Procedure
Normally, the starting position of the scrollbar’s current view is computed by its package’s
default scroll procedure, scrollbar_default_compute_scroll_proc(). You can
install you own scroll procedure using the
SCROLLBAR_COMPUTE_SCROLL_PROC attribute.
This procedure converts the physical scrollbar information into client object information;
that is, it returns the offset and the object length of the object to scroll. The form of the com-
pute scroll routine is:
void
scrollbar_compute_scroll_proc(sb, pos, length, motion,
&offset, &object_length)
Scrollbar sb;
int pos;
int length;
Scroll_motion motion;
unsigned long offset;
unsigned long object_length;
This procedure computes the offset, and the scrollbar package will scroll to this offset into
the object when the compute procedure returns. This function should return the offset and
266 XView Programming Manual
object_length where pos is the position in the cable. The default_com-
pute_scroll_proc can be called to perform the normal scroll. If a normalize_proc
is not set then the offset becomes the viewstart, after bounds checking, and the scrollbar
package will scroll to this offset into the object. For example:
Example 10-3. Scrollbar compute scroll procedure example
void
compute_scroll1(scrollpub,pos,avail_cable,motion,offset,object_len)
Scrollbar scrollpub;
int pos;
int avail_cable;
Scroll_motion motion;
unsigned long *offset;
unsigned long *object_len;
{
int new_start = TEXTSW_CANNOT_SET;
int lines = 0;
*obj_length = es_get_length(folio->views->esh);
switch (motion) {
case SCROLLBAR_ABSOLUTE:
if (length == 0)
new_start = pos;
else
new_start = *obj_length * pos / length;
break;
case SCROLLBAR_POINT_TO_MIN:
case SCROLLBAR_MIN_TO_POINT:{
if (lines == 0)
lines++; /* Always make some progress */
if (motion == SCROLLBAR_MIN_TO_POINT)
lines = -lines;
}
break;
case SCROLLBAR_PAGE_FORWARD:
lines = line_table.last_plus_one - 2;
break;
case SCROLLBAR_PAGE_BACKWARD:
lines = last_plus_one + 2;
break;
case SCROLLBAR_LINE_FORWARD:
lines = 1;
break;
case SCROLLBAR_LINE_BACKWARD:
lines = -1;
break;
case SCROLLBAR_TO_START:
new_start = 0;
break;
case SCROLLBAR_TO_END:
new_start = *obj_length;
break;
default:
break;
}
Scrollbars
Scrollbars 267
Get Volume 7A: XView Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.