1 /* scrollbar implementation -- X interface.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994 Amdahl Corporation.
4 Copyright (C) 1995 Sun Microsystems, Inc.
5 Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>.
7 This file is part of SXEmacs
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /* Synched up with: Not in FSF. */
25 /* This file Mule-ized (more like Mule-verified) by Ben Wing, 7-8-00. */
30 #include "console-x.h"
31 #include "EmacsFrame.h"
34 #include "scrollbar-x.h"
37 #include "ui/window.h"
39 static void x_update_vertical_scrollbar_callback(Widget widget, LWLIB_ID id,
40 XtPointer client_data);
41 static void x_update_horizontal_scrollbar_callback(Widget widget, LWLIB_ID id,
42 XtPointer client_data);
44 /* Used to prevent changing the size of the slider while drag
45 scrolling, under Motif. This is necessary because the Motif
46 scrollbar is incredibly stupid about updating the slider and causes
47 lots of flicker if it is done too often. */
48 static int inhibit_slider_size_change;
49 int stupid_vertical_scrollbar_drag_hack;
51 /* Doesn't work with athena */
52 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
53 static int vertical_drag_in_progress;
56 /* A device method. */
57 static int x_inhibit_scrollbar_slider_size_change(void)
59 /* Doesn't work with Athena */
60 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
61 return inhibit_slider_size_change;
67 /* A device method. */
68 static void x_free_scrollbar_instance(struct scrollbar_instance *instance)
70 if ( instance && instance->scrollbar_data ) {
72 if (SCROLLBAR_X_NAME(instance))
73 xfree(SCROLLBAR_X_NAME(instance));
75 if (SCROLLBAR_X_WIDGET(instance)) {
76 if (XtIsManaged(SCROLLBAR_X_WIDGET(instance)))
77 XtUnmanageChild(SCROLLBAR_X_WIDGET(instance));
79 lw_destroy_all_widgets(SCROLLBAR_X_ID(instance));
81 xfree(instance->scrollbar_data);
85 /* A device method. */
86 static void x_release_scrollbar_instance(struct scrollbar_instance *instance)
88 if (XtIsManaged(SCROLLBAR_X_WIDGET(instance)))
89 XtUnmanageChild(SCROLLBAR_X_WIDGET(instance));
92 /* A device method. */
94 x_create_scrollbar_instance(struct frame *f, int vertical,
95 struct scrollbar_instance *instance)
100 /* initialize the X specific data section. */
101 instance->scrollbar_data = xnew_and_zero(struct x_scrollbar_data);
103 SCROLLBAR_X_ID(instance) = new_lwlib_id();
104 sz = snprintf(buffer, sizeof(buffer), "scrollbar_%d", SCROLLBAR_X_ID(instance));
105 assert(sz >= 0 && (size_t)sz < sizeof(buffer));
106 SCROLLBAR_X_NAME(instance) = xstrdup(buffer);
107 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
108 defined (LWLIB_SCROLLBARS_ATHENA3D)
109 SCROLLBAR_X_VDRAG_ORIG_VALUE(instance) = -1;
113 SCROLLBAR_X_WIDGET(instance) =
114 lw_create_widget("vertical-scrollbar",
115 SCROLLBAR_X_NAME(instance),
116 SCROLLBAR_X_ID(instance), NULL,
117 FRAME_X_CONTAINER_WIDGET(f), 0,
118 x_update_vertical_scrollbar_callback, NULL,
121 SCROLLBAR_X_WIDGET(instance) =
122 lw_create_widget("horizontal-scrollbar",
123 SCROLLBAR_X_NAME(instance),
124 SCROLLBAR_X_ID(instance), NULL,
125 FRAME_X_CONTAINER_WIDGET(f), 0,
126 x_update_horizontal_scrollbar_callback,
131 #define UPDATE_DATA_FIELD(field) \
132 if (new_##field >= 0 && \
133 SCROLLBAR_X_POS_DATA (inst).field != new_##field) { \
134 SCROLLBAR_X_POS_DATA (inst).field = new_##field; \
135 inst->scrollbar_instance_changed = 1; \
138 /* A device method. */
139 /* #### The -1 check is such a hack. */
141 x_update_scrollbar_instance_values(struct window *w,
142 struct scrollbar_instance *inst,
143 int new_line_increment,
144 int new_page_increment,
145 int new_minimum, int new_maximum,
147 int new_slider_position,
148 int new_scrollbar_width,
149 int new_scrollbar_height,
150 int new_scrollbar_x, int new_scrollbar_y)
152 UPDATE_DATA_FIELD(line_increment);
153 UPDATE_DATA_FIELD(page_increment);
154 UPDATE_DATA_FIELD(minimum);
155 UPDATE_DATA_FIELD(maximum);
156 UPDATE_DATA_FIELD(slider_size);
157 UPDATE_DATA_FIELD(slider_position);
158 UPDATE_DATA_FIELD(scrollbar_width);
159 UPDATE_DATA_FIELD(scrollbar_height);
160 UPDATE_DATA_FIELD(scrollbar_x);
161 UPDATE_DATA_FIELD(scrollbar_y);
163 /* This doesn't work with Athena, why? */
164 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
165 if (w && !vertical_drag_in_progress) {
166 int new_vov = SCROLLBAR_X_POS_DATA(inst).slider_position;
167 int new_vows = marker_position(w->start[CURRENT_DISP]);
169 if (SCROLLBAR_X_VDRAG_ORIG_VALUE(inst) != new_vov) {
170 SCROLLBAR_X_VDRAG_ORIG_VALUE(inst) = new_vov;
171 inst->scrollbar_instance_changed = 1;
173 if (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START(inst) != new_vows) {
174 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START(inst) = new_vows;
175 inst->scrollbar_instance_changed = 1;
181 /* Used by x_update_scrollbar_instance_status. */
182 static void update_one_scrollbar_bs(struct frame *f, Widget sb_widget)
184 Boolean use_backing_store;
186 Xt_GET_VALUE(FRAME_X_TEXT_WIDGET(f), XtNuseBackingStore,
189 if (use_backing_store && sb_widget) {
190 unsigned long mask = CWBackingStore;
191 XSetWindowAttributes attrs;
193 attrs.backing_store = Always;
194 XChangeWindowAttributes(XtDisplay(sb_widget),
195 XtWindow(sb_widget), mask, &attrs);
199 /* Create a widget value structure for passing down to lwlib so that
200 it can update the scrollbar widgets. Used by
201 x_update_scrollbar_instance_status. */
202 static widget_value *scrollbar_instance_to_widget_value(struct
208 wv = xmalloc_widget_value();
209 /* #### maybe should add malloc_scrollbar_values to resource these? */
210 wv->scrollbar_data = xnew(scrollbar_values);
212 wv->name = SCROLLBAR_X_NAME(instance);
213 wv->name = xstrdup(wv->name);
216 wv->enabled = instance->scrollbar_is_active;
218 wv->call_data = NULL;
220 *wv->scrollbar_data = SCROLLBAR_X_POS_DATA(instance);
227 /* Used by x_update_scrollbar_instance_status. */
228 static void update_one_widget_scrollbar_pointer(struct window *w, Widget wid)
230 if (POINTER_IMAGE_INSTANCEP(w->scrollbar_pointer)) {
231 XDefineCursor(XtDisplay(wid), XtWindow(wid),
232 XIMAGE_INSTANCE_X_CURSOR(w->scrollbar_pointer));
233 XSync(XtDisplay(wid), False);
237 /* A device method. */
239 x_update_scrollbar_instance_status(struct window *w, int active, int size,
240 struct scrollbar_instance *instance)
242 struct frame *f = XFRAME(w->frame);
243 Boolean managed = XtIsManaged(SCROLLBAR_X_WIDGET(instance));
245 if (active && size) {
246 widget_value *wv = scrollbar_instance_to_widget_value(instance);
248 if (instance->scrollbar_instance_changed) {
249 lw_modify_all_widgets(SCROLLBAR_X_ID(instance), wv, 0);
250 instance->scrollbar_instance_changed = 0;
254 XtManageChild(SCROLLBAR_X_WIDGET(instance));
255 if (XtWindow(SCROLLBAR_X_WIDGET(instance))) {
256 /* Raise this window so that it's visible on top of the
257 text window below it. */
258 XRaiseWindow(XtDisplay
259 (SCROLLBAR_X_WIDGET(instance)),
260 XtWindow(SCROLLBAR_X_WIDGET
262 update_one_widget_scrollbar_pointer(w,
265 if (!SCROLLBAR_X_BACKING_STORE_INITIALIZED
267 update_one_scrollbar_bs(f,
270 SCROLLBAR_X_BACKING_STORE_INITIALIZED
276 if (!wv->scrollbar_data)
278 free_widget_value_tree(wv);
279 } else if (managed) {
280 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
281 /* This isn't needed with Athena Scrollbars. It might not be needed */
282 /* with Motif scrollbars (it is apparently needed with Lesstif). */
283 XtUngrabKeyboard(SCROLLBAR_X_WIDGET(instance), CurrentTime);
285 XtUnmanageChild(SCROLLBAR_X_WIDGET(instance));
289 enum x_scrollbar_loop {
290 X_FIND_SCROLLBAR_WINDOW_MIRROR,
291 X_SET_SCROLLBAR_POINTER,
292 X_WINDOW_IS_SCROLLBAR,
293 X_UPDATE_FRAME_SCROLLBARS
296 static struct window_mirror *x_scrollbar_loop(enum x_scrollbar_loop type,
298 struct window_mirror *mir,
299 LWLIB_ID id, Window x_win)
301 struct window_mirror *retval = NULL;
304 struct scrollbar_instance *vinstance =
305 mir->scrollbar_vertical_instance;
306 struct scrollbar_instance *hinstance =
307 mir->scrollbar_horizontal_instance;
308 struct window *w = XWINDOW(window);
312 x_scrollbar_loop(type, w->vchild, mir->vchild, id,
314 else if (mir->hchild)
316 x_scrollbar_loop(type, w->hchild, mir->hchild, id,
321 if (hinstance || vinstance) {
323 case X_FIND_SCROLLBAR_WINDOW_MIRROR:
325 && SCROLLBAR_X_ID(vinstance) == id)
327 && SCROLLBAR_X_ID(hinstance) == id))
330 case X_UPDATE_FRAME_SCROLLBARS:
331 if (!mir->vchild && !mir->hchild)
332 update_window_scrollbars(w, mir, 1, 0);
334 case X_SET_SCROLLBAR_POINTER:
335 if (!mir->vchild && !mir->hchild) {
338 widget = SCROLLBAR_X_WIDGET(hinstance);
339 if (widget && XtIsManaged(widget))
340 update_one_widget_scrollbar_pointer
343 widget = SCROLLBAR_X_WIDGET(vinstance);
344 if (widget && XtIsManaged(widget))
345 update_one_widget_scrollbar_pointer
349 case X_WINDOW_IS_SCROLLBAR:
350 if (!mir->vchild && !mir->hchild) {
353 widget = SCROLLBAR_X_WIDGET(hinstance);
354 if (widget && XtIsManaged(widget) &&
355 XtWindow(widget) == x_win)
356 return (struct window_mirror *)
359 widget = SCROLLBAR_X_WIDGET(vinstance);
360 if (widget && XtIsManaged(widget) &&
361 XtWindow(widget) == x_win)
362 return (struct window_mirror *)
378 /* Used by callbacks. */
379 static struct window_mirror *find_scrollbar_window_mirror(struct frame *f,
383 update_frame_window_mirror(f);
384 return x_scrollbar_loop(X_FIND_SCROLLBAR_WINDOW_MIRROR, f->root_window,
385 f->root_mirror, id, (Window) NULL);
389 * This is the only callback provided for vertical scrollbars. It
390 * should be able to handle all of the scrollbar events in
391 * scroll_action (see lwlib.h). The client data will be of type
392 * scroll_event (see lwlib.h). */
394 x_update_vertical_scrollbar_callback(Widget widget, LWLIB_ID id,
395 XtPointer client_data)
397 /* This function can GC */
398 scroll_event *data = (scroll_event *) client_data;
399 struct device *d = get_device_from_display(XtDisplay(widget));
400 struct frame *f = x_any_window_to_frame(d, XtWindow(widget));
401 Lisp_Object win, frame;
402 struct scrollbar_instance *instance;
403 struct window_mirror *mirror;
408 mirror = find_scrollbar_window_mirror(f, id);
412 win = real_window(mirror, 1);
416 instance = mirror->scrollbar_vertical_instance;
417 frame = WINDOW_FRAME(XWINDOW(win));
419 /* It seems that this is necessary whenever signal_special_Xt_user_event()
420 is called. #### Why??? */
421 DEVICE_X_MOUSE_TIMESTAMP(d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d);
423 switch (data->action) {
424 case SCROLLBAR_LINE_UP:
425 signal_special_Xt_user_event(frame, Qscrollbar_line_up, win);
428 case SCROLLBAR_LINE_DOWN:
429 signal_special_Xt_user_event(frame, Qscrollbar_line_down, win);
432 /* The Athena scrollbar paging behavior is that of xterms.
433 Depending on where you click the size of the page varies.
434 Motif always does a standard Emacs page. */
435 case SCROLLBAR_PAGE_UP: {
436 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
437 !defined (LWLIB_SCROLLBARS_ATHENA3D)
438 double tmp = ((double)data->slider_value /
439 (double)SCROLLBAR_X_POS_DATA(instance).
442 tmp * (double)window_displayed_height(XWINDOW(win));
447 signal_special_Xt_user_event(frame, Qscrollbar_page_up,
448 Fcons(win, make_int((int)line)));
450 signal_special_Xt_user_event(frame, Qscrollbar_page_up,
456 case SCROLLBAR_PAGE_DOWN: {
457 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
458 !defined (LWLIB_SCROLLBARS_ATHENA3D)
459 double tmp = ((double)data->slider_value /
460 (double)SCROLLBAR_X_POS_DATA(instance).
463 tmp * (double)window_displayed_height(XWINDOW(win));
465 if (SCROLLBAR_X_POS_DATA(instance).maximum >
466 (SCROLLBAR_X_POS_DATA(instance).slider_size +
467 SCROLLBAR_X_POS_DATA(instance).slider_position)) {
471 signal_special_Xt_user_event(
473 Qscrollbar_page_down,
474 Fcons(win, make_int((int)line)));
477 signal_special_Xt_user_event(frame, Qscrollbar_page_down,
484 signal_special_Xt_user_event(frame, Qscrollbar_to_top, win);
487 case SCROLLBAR_BOTTOM:
488 signal_special_Xt_user_event(frame, Qscrollbar_to_bottom, win);
491 case SCROLLBAR_CHANGE:
492 inhibit_slider_size_change = 0;
493 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
494 vertical_drag_in_progress = 0;
495 SCROLLBAR_X_VDRAG_ORIG_VALUE(instance) = data->slider_value;
496 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START(instance) =
497 XINT(Fwindow_start(win));
499 stupid_vertical_scrollbar_drag_hack = 0;
503 case SCROLLBAR_DRAG: {
506 inhibit_slider_size_change = 1;
508 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
509 /* Doing drags with Motif-like scrollbars is a mess, since we
510 want to avoid having the window position jump when you
511 first grab the scrollbar, but we also want to ensure that
512 you can scroll all the way to the top or bottom of the
513 buffer. This can all be replaced with something sane when
514 we get line-based scrolling. */
516 vertical_drag_in_progress = 1;
518 if (SCROLLBAR_X_VDRAG_ORIG_VALUE(instance) < 0) {
519 SCROLLBAR_X_VDRAG_ORIG_VALUE(instance) =
521 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START(instance) =
522 XINT(Fwindow_start(win));
525 /* Could replace this piecewise linear scrolling with a
526 quadratic through the three points, but I'm not sure that
527 would feel any nicer in practice. */
528 if (data->slider_value <
529 SCROLLBAR_X_VDRAG_ORIG_VALUE(instance)) {
530 /* We've dragged up; slide linearly from original position to
531 window-start=data.minimum, slider-value=data.minimum. */
533 if (SCROLLBAR_X_VDRAG_ORIG_VALUE(instance)
534 <= SCROLLBAR_X_POS_DATA(instance).minimum) {
535 /* shouldn't get here, but just in case */
537 SCROLLBAR_X_POS_DATA(instance).
541 (SCROLLBAR_X_POS_DATA(instance).
543 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START(instance)
547 * (data->slider_value -
551 (SCROLLBAR_X_VDRAG_ORIG_VALUE
555 (instance).minimum)));
558 /* We've dragged down; slide linearly from original position to
559 window-start=data.maximum, slider-value=data.maximum. */
561 if (SCROLLBAR_X_VDRAG_ORIG_VALUE(instance)
562 >= (SCROLLBAR_X_POS_DATA(instance).maximum -
563 SCROLLBAR_X_POS_DATA(instance).
565 /* avoid divide by zero */
567 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START
571 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START
574 (SCROLLBAR_X_POS_DATA
576 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START
578 * (data->slider_value -
579 SCROLLBAR_X_VDRAG_ORIG_VALUE
582 (SCROLLBAR_X_POS_DATA(instance).
584 SCROLLBAR_X_POS_DATA(instance).
586 SCROLLBAR_X_VDRAG_ORIG_VALUE
591 stupid_vertical_scrollbar_drag_hack = 0;
592 value = data->slider_value;
595 if (value >= SCROLLBAR_X_POS_DATA(instance).maximum)
597 SCROLLBAR_X_POS_DATA(instance).maximum - 1;
598 if (value < SCROLLBAR_X_POS_DATA(instance).minimum)
599 value = SCROLLBAR_X_POS_DATA(instance).minimum;
601 signal_special_Xt_user_event(frame,
602 Qscrollbar_vertical_drag,
608 /* maybe punish the user here? */
615 * This is the only callback provided for horizontal scrollbars. It
616 * should be able to handle all of the scrollbar events in
617 * scroll_action (see lwlib.h). The client data will be of type
618 * scroll_event (see lwlib.h). */
620 x_update_horizontal_scrollbar_callback(Widget widget, LWLIB_ID id,
621 XtPointer client_data)
623 scroll_event *data = (scroll_event *) client_data;
624 struct device *d = get_device_from_display(XtDisplay(widget));
625 struct frame *f = x_any_window_to_frame(d, XtWindow(widget));
626 Lisp_Object win, frame;
627 struct window_mirror *mirror;
632 mirror = find_scrollbar_window_mirror(f, id);
636 win = real_window(mirror, 1);
640 frame = WINDOW_FRAME(XWINDOW(win));
642 /* It seems that this is necessary whenever signal_special_Xt_user_event()
643 is called. #### Why??? */
644 DEVICE_X_MOUSE_TIMESTAMP(d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d);
646 switch (data->action) {
647 case SCROLLBAR_LINE_UP:
648 signal_special_Xt_user_event(frame, Qscrollbar_char_left, win);
650 case SCROLLBAR_LINE_DOWN:
651 signal_special_Xt_user_event(frame, Qscrollbar_char_right, win);
653 case SCROLLBAR_PAGE_UP:
654 signal_special_Xt_user_event(frame, Qscrollbar_page_left, win);
656 case SCROLLBAR_PAGE_DOWN:
657 signal_special_Xt_user_event(frame, Qscrollbar_page_right, win);
660 signal_special_Xt_user_event(frame, Qscrollbar_to_left, win);
662 case SCROLLBAR_BOTTOM:
663 signal_special_Xt_user_event(frame, Qscrollbar_to_right, win);
665 case SCROLLBAR_CHANGE:
666 inhibit_slider_size_change = 0;
669 inhibit_slider_size_change = 1;
670 /* #### Fix the damn toolkit code so they all work the same way.
671 Lucid is the one mostly wrong. */
672 #if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D)
673 signal_special_Xt_user_event(frame, Qscrollbar_horizontal_drag,
676 make_int(data->slider_value))));
678 signal_special_Xt_user_event(frame, Qscrollbar_horizontal_drag,
681 make_int(data->slider_value -
690 static void x_scrollbar_pointer_changed_in_window(struct window *w)
694 XSETWINDOW(window, w);
695 x_scrollbar_loop(X_SET_SCROLLBAR_POINTER, window, find_window_mirror(w),
699 /* Make sure that all scrollbars on frame are up-to-date. Called
700 directly from x_set_frame_properties in frame-x.c*/
701 void x_update_frame_scrollbars(struct frame *f)
703 /* Consider this code to be "in_display" so that we abort() if Fsignal()
706 x_scrollbar_loop(X_UPDATE_FRAME_SCROLLBARS, f->root_window,
707 f->root_mirror, 0, (Window) NULL);
713 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
716 x_compute_scrollbar_instance_usage(struct device *d,
717 struct scrollbar_instance *inst,
718 struct overhead_stats *ovstats)
723 struct x_scrollbar_data *data =
724 (struct x_scrollbar_data *)inst->scrollbar_data;
726 total += malloced_storage_size(data, sizeof(*data), ovstats);
728 malloced_storage_size(data->name, 1 + strlen(data->name),
736 #endif /* MEMORY_USAGE_STATS */
738 /************************************************************************/
740 /************************************************************************/
742 void console_type_create_scrollbar_x(void)
744 CONSOLE_HAS_METHOD(x, inhibit_scrollbar_slider_size_change);
745 CONSOLE_HAS_METHOD(x, free_scrollbar_instance);
746 CONSOLE_HAS_METHOD(x, release_scrollbar_instance);
747 CONSOLE_HAS_METHOD(x, create_scrollbar_instance);
748 CONSOLE_HAS_METHOD(x, update_scrollbar_instance_values);
749 CONSOLE_HAS_METHOD(x, update_scrollbar_instance_status);
750 CONSOLE_HAS_METHOD(x, scrollbar_pointer_changed_in_window);
751 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
752 CONSOLE_HAS_METHOD(x, compute_scrollbar_instance_usage);
753 #endif /* MEMORY_USAGE_STATS */
756 void reinit_vars_of_scrollbar_x(void)
758 stupid_vertical_scrollbar_drag_hack = 1;
761 void vars_of_scrollbar_x(void)
763 reinit_vars_of_scrollbar_x();
765 #if defined (LWLIB_SCROLLBARS_LUCID)
766 Fprovide(intern("lucid-scrollbars"));
767 #elif defined (LWLIB_SCROLLBARS_MOTIF)
768 Fprovide(intern("motif-scrollbars"));
769 #elif defined (LWLIB_SCROLLBARS_ATHENA)
770 Fprovide(intern("athena-scrollbars"));