1 /* $XTermId: scrollbar.c,v 1.179 2011/02/09 10:05:19 tom Exp $ */
4 * Copyright 2000-2010,2011 by Thomas E. Dickey
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the
29 * sale, use or other dealings in this Software without prior written
33 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted,
39 * provided that the above copyright notice appear in all copies and that
40 * both that copyright notice and this permission notice appear in
41 * supporting documentation, and that the name of Digital Equipment
42 * Corporation not be used in advertising or publicity pertaining to
43 * distribution of the software without specific, written prior permission.
46 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
47 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
48 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
49 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
50 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
51 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
57 #include <X11/Xatom.h>
59 #if defined(HAVE_LIB_XAW)
60 #include <X11/Xaw/Scrollbar.h>
61 #elif defined(HAVE_LIB_XAW3D)
62 #include <X11/Xaw3d/Scrollbar.h>
63 #elif defined(HAVE_LIB_NEXTAW)
64 #include <X11/neXtaw/Scrollbar.h>
65 #elif defined(HAVE_LIB_XAWPLUS)
66 #include <X11/XawPlus/Scrollbar.h>
69 #if defined(HAVE_XKBQUERYEXTENSION) && defined(HAVE_X11_XKBLIB_H) && defined(HAVE_X11_EXTENSIONS_XKB_H)
70 #include <X11/extensions/XKB.h>
71 #include <X11/XKBlib.h>
73 #undef HAVE_XKBQUERYEXTENSION
79 #include <xcharmouse.h>
83 * The scrollbar's border overlaps the border of the vt100 window. If there
84 * is no border for the vt100, there can be no border for the scrollbar.
86 #define SCROLLBAR_BORDER(xw) (TScreenOf(xw)->scrollBarBorder)
88 #define ScrollBarBorder(xw) (BorderWidth(xw) ? SCROLLBAR_BORDER(xw) : 0)
90 #define ScrollBarBorder(xw) SCROLLBAR_BORDER(xw)
95 static void ScrollTextTo PROTO_XT_CALLBACK_ARGS;
96 static void ScrollTextUpDownBy PROTO_XT_CALLBACK_ARGS;
98 /* Resize the text window for a terminal screen, modifying the
99 * appropriate WM_SIZE_HINTS and taking advantage of bit gravity.
102 DoResizeScreen(XtermWidget xw)
104 TScreen *screen = TScreenOf(xw);
106 int border = 2 * screen->border;
107 int min_wide = border + screen->fullVwin.sb_info.width;
108 int min_high = border;
109 XtGeometryResult geomreqresult;
110 Dimension reqWidth, reqHeight, repWidth, repHeight;
111 #ifndef NO_ACTIVE_ICON
112 VTwin *saveWin = WhichVWin(screen);
114 /* all units here want to be in the normal font units */
115 WhichVWin(screen) = &screen->fullVwin;
116 #endif /* NO_ACTIVE_ICON */
119 * I'm going to try to explain, as I understand it, why we
120 * have to do XGetWMNormalHints and XSetWMNormalHints here,
121 * although I can't guarantee that I've got it right.
123 * In a correctly written toolkit program, the Shell widget
124 * parses the user supplied geometry argument. However,
125 * because of the way xterm does things, the VT100 widget does
126 * the parsing of the geometry option, not the Shell widget.
127 * The result of this is that the Shell widget doesn't set the
128 * correct window manager hints, and doesn't know that the
129 * user has specified a geometry.
131 * The XtVaSetValues call below tells the Shell widget to
132 * change its hints. However, since it's confused about the
133 * hints to begin with, it doesn't get them all right when it
134 * does the SetValues -- it undoes some of what the VT100
135 * widget did when it originally set the hints.
137 * To fix this, we do the following:
139 * 1. Get the sizehints directly from the window, going around
140 * the (confused) shell widget.
141 * 2. Call XtVaSetValues to let the shell widget know which
142 * hints have changed. Note that this may not even be
143 * necessary, since we're going to right ahead after that
144 * and set the hints ourselves, but it's good to put it
145 * here anyway, so that when we finally do fix the code so
146 * that the Shell does the right thing with hints, we
147 * already have the XtVaSetValues in place.
148 * 3. We set the sizehints directly, this fixing up whatever
149 * damage was done by the Shell widget during the
154 * The correct fix is to redo VTRealize, VTInitialize and
155 * VTSetValues so that font processing happens early enough to
156 * give back responsibility for the size hints to the Shell.
158 * Someday, we hope to have time to do this. Someday, we hope
159 * to have time to completely rewrite xterm.
162 TRACE(("DoResizeScreen\n"));
164 #if 1 /* ndef nothack */
166 * NOTE: the hints and the XtVaSetValues() must match.
168 TRACE(("%s@%d -- ", __FILE__, __LINE__));
170 getXtermSizeHints(xw);
172 xtermSizeHints(xw, ScrollbarWidth(screen));
174 /* These are obsolete, but old clients may use them */
175 xw->hints.width = MaxCols(screen) * FontWidth(screen) + xw->hints.min_width;
176 xw->hints.height = MaxRows(screen) * FontHeight(screen) + xw->hints.min_height;
178 /* assure single-increment resize for fullscreen */
179 if (xw->screen.fullscreen) {
180 xw->hints.width_inc = 1;
181 xw->hints.height_inc = 1;
183 #endif /* OPT_MAXIMIZE */
186 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints);
188 reqWidth = (Dimension) (MaxCols(screen) * FontWidth(screen) + min_wide);
189 reqHeight = (Dimension) (MaxRows(screen) * FontHeight(screen) + min_high);
192 /* compensate for fullscreen mode */
193 if (screen->fullscreen) {
194 Screen *xscreen = DefaultScreenOfDisplay(xw->screen.display);
195 reqWidth = (Dimension) WidthOfScreen(xscreen);
196 reqHeight = (Dimension) HeightOfScreen(xscreen);
197 ScreenResize(xw, reqWidth, reqHeight, &xw->flags);
199 #endif /* OPT_MAXIMIZE */
201 TRACE(("...requesting screensize chars %dx%d, pixels %dx%d\n",
204 reqHeight, reqWidth));
206 geomreqresult = REQ_RESIZE((Widget) xw, reqWidth, reqHeight,
207 &repWidth, &repHeight);
209 if (geomreqresult == XtGeometryAlmost) {
210 TRACE(("...almost, retry screensize %dx%d\n", repHeight, repWidth));
211 geomreqresult = REQ_RESIZE((Widget) xw, repWidth,
212 repHeight, NULL, NULL);
215 if (geomreqresult != XtGeometryYes) {
216 /* The resize wasn't successful, so we might need to adjust
217 our idea of how large the screen is. */
218 TRACE(("...still no (%d) - resize the core-class\n", geomreqresult));
219 xw->core.widget_class->core_class.resize((Widget) xw);
221 #if 1 /* ndef nothack */
223 * XtMakeResizeRequest() has the undesirable side-effect of clearing
224 * the window manager's hints, even on a failed request. This would
225 * presumably be fixed if the shell did its own work.
230 xw->hints.height = repHeight;
231 xw->hints.width = repWidth;
232 TRACE_HINTS(&xw->hints);
233 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints);
236 XSync(screen->display, False); /* synchronize */
237 if (XtAppPending(app_con))
240 #ifndef NO_ACTIVE_ICON
241 WhichVWin(screen) = saveWin;
242 #endif /* NO_ACTIVE_ICON */
246 CreateScrollBar(XtermWidget xw, int x, int y, int height)
251 XtSetArg(args[0], XtNx, x);
252 XtSetArg(args[1], XtNy, y);
253 XtSetArg(args[2], XtNheight, height);
254 XtSetArg(args[3], XtNreverseVideo, xw->misc.re_verse);
255 XtSetArg(args[4], XtNorientation, XtorientVertical);
256 XtSetArg(args[5], XtNborderWidth, ScrollBarBorder(xw));
258 result = XtCreateWidget("scrollbar", scrollbarWidgetClass,
259 (Widget) xw, args, XtNumber(args));
260 XtAddCallback(result, XtNscrollProc, ScrollTextUpDownBy, 0);
261 XtAddCallback(result, XtNjumpProc, ScrollTextTo, 0);
266 ScrollBarReverseVideo(Widget scrollWidget)
268 XtermWidget xw = getXtermWidget(scrollWidget);
271 SbInfo *sb = &(TScreenOf(xw)->fullVwin.sb_info);
273 Cardinal nargs = XtNumber(args);
276 * Remember the scrollbar's original colors.
278 if (sb->rv_cached == False) {
279 XtSetArg(args[0], XtNbackground, &(sb->bg));
280 XtSetArg(args[1], XtNforeground, &(sb->fg));
281 XtSetArg(args[2], XtNborderColor, &(sb->bdr));
282 XtSetArg(args[3], XtNborderPixmap, &(sb->bdpix));
283 XtGetValues(scrollWidget, args, nargs);
284 sb->rv_cached = True;
288 sb->rv_active = !(sb->rv_active);
289 XtSetArg(args[!(sb->rv_active)], XtNbackground, sb->bg);
290 XtSetArg(args[(sb->rv_active)], XtNforeground, sb->fg);
291 nargs = 2; /* don't set border_pixmap */
292 if (sb->bdpix == XtUnspecifiedPixmap) {
293 /* if not pixmap then pixel */
295 /* keep border visible */
296 XtSetArg(args[2], XtNborderColor, args[1].value);
298 XtSetArg(args[2], XtNborderColor, sb->bdr);
302 XtSetValues(scrollWidget, args, nargs);
307 ScrollBarDrawThumb(Widget scrollWidget)
309 XtermWidget xw = getXtermWidget(scrollWidget);
312 TScreen *screen = TScreenOf(xw);
313 int thumbTop, thumbHeight, totalHeight;
315 thumbTop = ROW2INX(screen, screen->savedlines);
316 thumbHeight = MaxRows(screen);
317 totalHeight = thumbHeight + screen->savedlines;
319 XawScrollbarSetThumb(scrollWidget,
320 ((float) thumbTop) / (float) totalHeight,
321 ((float) thumbHeight) / (float) totalHeight);
326 ResizeScrollBar(XtermWidget xw)
328 TScreen *screen = TScreenOf(xw);
330 if (screen->scrollWidget != 0) {
331 int height = screen->fullVwin.height + screen->border * 2;
332 int width = screen->scrollWidget->core.width;
333 int ypos = -ScrollBarBorder(xw);
334 #ifdef SCROLLBAR_RIGHT
335 int xpos = ((xw->misc.useRight)
336 ? (screen->fullVwin.fullwidth -
337 screen->scrollWidget->core.width -
338 BorderWidth(screen->scrollWidget))
339 : -ScrollBarBorder(xw));
341 int xpos = -ScrollBarBorder(xw);
344 TRACE(("ResizeScrollBar at %d,%d %dx%d\n", ypos, xpos, height, width));
347 screen->scrollWidget,
352 BorderWidth(screen->scrollWidget));
353 ScrollBarDrawThumb(screen->scrollWidget);
358 WindowScroll(XtermWidget xw, int top, Bool always GCC_UNUSED)
360 TScreen *screen = TScreenOf(xw);
362 int scrolltop, scrollheight, refreshtop;
365 if (screen->allowScrollLock && (screen->scroll_lock && !always)) {
366 if (screen->scroll_dirty) {
367 screen->scroll_dirty = False;
368 ScrnRefresh(xw, 0, 0, MaxRows(screen), MaxCols(screen), False);
373 if (top < -screen->savedlines) {
374 top = -screen->savedlines;
375 } else if (top > 0) {
379 if ((i = screen->topline - top) != 0) {
381 if (screen->cursor_state)
383 lines = i > 0 ? i : -i;
384 if (lines > MaxRows(screen))
385 lines = MaxRows(screen);
386 scrollheight = screen->max_row - lines + 1;
388 refreshtop = scrolltop = 0;
391 refreshtop = scrollheight;
393 scrolling_copy_area(xw, scrolltop, scrollheight, -i);
394 screen->topline = top;
396 ScrollSelection(screen, i, True);
402 OriginY(screen) + refreshtop * FontHeight(screen),
403 (unsigned) Width(screen),
404 (unsigned) (lines * FontHeight(screen)),
406 ScrnRefresh(xw, refreshtop, 0, lines, MaxCols(screen), False);
408 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
409 RestartBlinking(screen);
413 ScrollBarDrawThumb(screen->scrollWidget);
416 #ifdef SCROLLBAR_RIGHT
418 * Adjust the scrollbar position if we're asked to turn on scrollbars for the
419 * first time (or after resizing) after the xterm is already running. That
420 * makes the window grow after we've initially configured the scrollbar's
421 * position. (There must be a better way).
424 updateRightScrollbar(XtermWidget xw)
426 TScreen *screen = TScreenOf(xw);
428 if (xw->misc.useRight
429 && screen->fullVwin.fullwidth < xw->core.width)
430 XtVaSetValues(screen->scrollWidget,
431 XtNx, screen->fullVwin.fullwidth - BorderWidth(screen->scrollWidget),
437 ScrollBarOn(XtermWidget xw, Bool init)
439 TScreen *screen = TScreenOf(xw);
441 if (screen->fullVwin.sb_info.width || IsIcon(screen))
444 TRACE(("ScrollBarOn(init %s)\n", BtoS(init)));
445 if (init) { /* then create it only */
446 if (screen->scrollWidget == 0) {
447 /* make it a dummy size and resize later */
448 screen->scrollWidget = CreateScrollBar(xw,
449 -ScrollBarBorder(xw),
450 -ScrollBarBorder(xw),
452 if (screen->scrollWidget == NULL) {
453 Bell(xw, XkbBI_MinorError, 0);
456 } else if (!screen->scrollWidget || !XtIsRealized((Widget) xw)) {
457 Bell(xw, XkbBI_MinorError, 0);
458 Bell(xw, XkbBI_MinorError, 0);
462 xtermAddInput(screen->scrollWidget);
463 XtRealizeWidget(screen->scrollWidget);
464 TRACE_TRANS("scrollbar", screen->scrollWidget);
466 screen->fullVwin.sb_info.rv_cached = False;
468 screen->fullVwin.sb_info.width = (screen->scrollWidget->core.width
469 + BorderWidth(screen->scrollWidget));
471 TRACE(("setting scrollbar width %d = %d + %d\n",
472 screen->fullVwin.sb_info.width,
473 screen->scrollWidget->core.width,
474 BorderWidth(screen->scrollWidget)));
476 ScrollBarDrawThumb(screen->scrollWidget);
479 #ifdef SCROLLBAR_RIGHT
480 updateRightScrollbar(xw);
483 XtMapWidget(screen->scrollWidget);
485 if (screen->visbuf) {
493 ScrollBarOff(XtermWidget xw)
495 TScreen *screen = TScreenOf(xw);
497 if (!screen->fullVwin.sb_info.width || IsIcon(screen))
500 TRACE(("ScrollBarOff\n"));
501 if (XtIsRealized((Widget) xw)) {
502 XtUnmapWidget(screen->scrollWidget);
503 screen->fullVwin.sb_info.width = 0;
506 if (screen->visbuf) {
511 Bell(xw, XkbBI_MinorError, 0);
516 * Toggle the visibility of the scrollbars.
519 ToggleScrollBar(XtermWidget xw)
521 TScreen *screen = TScreenOf(xw);
523 if (IsIcon(screen)) {
524 Bell(xw, XkbBI_MinorError, 0);
526 TRACE(("ToggleScrollBar{{\n"));
527 if (screen->fullVwin.sb_info.width) {
530 ScrollBarOn(xw, False);
533 TRACE(("...ToggleScrollBar}}\n"));
540 Widget scrollbarWidget,
541 XtPointer client_data GCC_UNUSED,
544 XtermWidget xw = getXtermWidget(scrollbarWidget);
547 float *topPercent = (float *) call_data;
548 TScreen *screen = TScreenOf(xw);
549 int thumbTop; /* relative to first saved line */
553 * screen->savedlines : Number of offscreen text lines,
554 * MaxRows(screen) : Number of onscreen text lines,
556 thumbTop = (int) (*topPercent
557 * (float) (screen->savedlines + MaxRows(screen)));
558 newTopLine = thumbTop - screen->savedlines;
559 WindowScroll(xw, newTopLine, True);
566 Widget scrollbarWidget,
567 XtPointer client_data GCC_UNUSED,
570 XtermWidget xw = getXtermWidget(scrollbarWidget);
573 long pixels = (long) call_data;
575 TScreen *screen = TScreenOf(xw);
576 int rowOnScreen, newTopLine;
578 rowOnScreen = (int) (pixels / FontHeight(screen));
579 if (rowOnScreen == 0) {
585 newTopLine = ROW2INX(screen, rowOnScreen);
586 WindowScroll(xw, newTopLine, True);
591 * assume that b is alphabetic and allow plural
594 CompareWidths(const char *a, const char *b, int *modifier)
606 if (ca != cb || ca == '\0')
607 break; /* if not eq else both nul */
619 *modifier = (ca == '-' ? -1 : 1) * atoi(a + 1);
635 params_to_pixels(TScreen * screen, String * params, Cardinal n)
641 switch (n > 2 ? 2 : n) {
644 if (CompareWidths(s, "PAGE", &modifier)) {
645 mult = (MaxRows(screen) + modifier) * FontHeight(screen);
646 } else if (CompareWidths(s, "HALFPAGE", &modifier)) {
647 mult = ((MaxRows(screen) + modifier) * FontHeight(screen)) / 2;
648 } else if (CompareWidths(s, "PIXEL", &modifier)) {
651 /* else assume that it is Line */
652 mult = FontHeight(screen);
654 mult *= atoi(params[0]);
657 mult = atoi(params[0]) * FontHeight(screen); /* lines */
660 mult = screen->scrolllines * FontHeight(screen);
667 AmountToScroll(Widget w, String * params, Cardinal nparams)
672 if ((xw = getXtermWidget(w)) != 0) {
673 TScreen *screen = TScreenOf(xw);
675 || screen->send_mouse_pos == MOUSE_OFF) {
676 result = params_to_pixels(screen, params, nparams);
686 XEvent * event GCC_UNUSED,
692 if ((amount = AmountToScroll(xw, params, *nparams)) != 0) {
693 ScrollTextUpDownBy(xw, (XtPointer) 0, (XtPointer) amount);
701 XEvent * event GCC_UNUSED,
707 if ((amount = -AmountToScroll(xw, params, *nparams)) != 0) {
708 ScrollTextUpDownBy(xw, (XtPointer) 0, (XtPointer) amount);
713 #define SCROLL_LOCK_LED 3
715 #ifdef HAVE_XKBQUERYEXTENSION
717 * Check for Xkb on client and server.
720 have_xkb(Display * dpy)
722 static int initialized = -1;
724 if (initialized < 0) {
725 int xkbmajor = XkbMajorVersion;
726 int xkbminor = XkbMinorVersion;
727 int xkbopcode, xkbevent, xkberror;
730 if (XkbLibraryVersion(&xkbmajor, &xkbminor)
731 && XkbQueryExtension(dpy,
737 TRACE(("we have Xkb\n"));
746 xkb = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
749 TRACE(("XkbGetKeyboard ok\n"));
750 for (n = 0; n < XkbNumVirtualMods; ++n) {
751 if (xkb->names->vmods[n] != 0) {
752 modStr = XGetAtomName(xkb->dpy,
753 xkb->names->vmods[n]);
755 XkbVirtualModsToReal(xkb,
758 TRACE((" name[%d] %s (%#x)\n", n, modStr, mask));
762 XkbFreeKeyboard(xkb, 0, True);
772 getXkbLED(Display * dpy, const char *name, Boolean * result)
775 Boolean success = False;
779 my_atom = XInternAtom(dpy, name, False);
780 if ((my_atom != None) &&
781 XkbGetNamedIndicator(dpy, my_atom, NULL, &state, NULL, NULL)) {
782 *result = (Boolean) state;
791 * Use Xkb if we have it (still unreliable, but slightly better than hardcoded).
794 showXkbLED(Display * dpy, const char *name, Bool enable)
797 Boolean result = False;
800 my_atom = XInternAtom(dpy, name, False);
801 if ((my_atom != None) &&
802 XkbGetNamedIndicator(dpy, my_atom, NULL, NULL, NULL, NULL) &&
803 XkbSetNamedIndicator(dpy, my_atom, True, enable, False, NULL)) {
813 * xlsatoms agrees with this list. However Num/Caps lock are generally
814 * unusable due to special treatment in X. They are used here for
817 static const char *led_table[] =
825 xtermGetLED(TScreen * screen, Cardinal led_number)
827 Display *dpy = screen->display;
828 Boolean result = False;
830 #ifdef HAVE_XKBQUERYEXTENSION
831 if (!getXkbLED(dpy, led_table[led_number - 1], &result))
834 XKeyboardState state;
835 unsigned long my_bit = (unsigned long) (1 << (led_number - 1));
837 XGetKeyboardControl(dpy, &state);
839 result = (Boolean) ((state.led_mask & my_bit) != 0);
842 TRACE(("xtermGetLED %d:%s\n", led_number, BtoS(result)));
847 * Display the given LED, preferably independent of keyboard state.
850 xtermShowLED(TScreen * screen, Cardinal led_number, Bool enable)
852 TRACE(("xtermShowLED %d:%s\n", led_number, BtoS(enable)));
853 if ((led_number >= 1) && (led_number <= XtNumber(led_table))) {
854 Display *dpy = screen->display;
856 #ifdef HAVE_XKBQUERYEXTENSION
857 if (!showXkbLED(dpy, led_table[led_number - 1], enable))
860 XKeyboardState state;
861 XKeyboardControl values;
862 unsigned long use_mask;
863 unsigned long my_bit = (unsigned long) (1 << (led_number - 1));
865 XGetKeyboardControl(dpy, &state);
866 use_mask = state.led_mask;
873 if (state.led_mask != use_mask) {
874 values.led = (int) led_number;
875 values.led_mode = enable;
876 XChangeKeyboardControl(dpy, KBLed | KBLedMode, &values);
883 xtermClearLEDs(TScreen * screen)
885 Display *dpy = screen->display;
886 XKeyboardControl values;
888 TRACE(("xtermClearLEDs\n"));
889 #ifdef HAVE_XKBQUERYEXTENSION
890 ShowScrollLock(screen, False);
892 memset(&values, 0, sizeof(values));
893 XChangeKeyboardControl(dpy, KBLedMode, &values);
897 ShowScrollLock(TScreen * screen, Bool enable)
899 xtermShowLED(screen, SCROLL_LOCK_LED, enable);
903 GetScrollLock(TScreen * screen)
905 if (screen->allowScrollLock)
906 screen->scroll_lock = xtermGetLED(screen, SCROLL_LOCK_LED);
910 SetScrollLock(TScreen * screen, Bool enable)
912 if (screen->allowScrollLock) {
913 if (screen->scroll_lock != enable) {
914 screen->scroll_lock = (Boolean) enable;
915 ShowScrollLock(screen, enable);
922 HandleScrollLock(Widget w,
923 XEvent * event GCC_UNUSED,
925 Cardinal *param_count)
929 if ((xw = getXtermWidget(w)) != 0) {
930 TScreen *screen = TScreenOf(xw);
932 if (screen->allowScrollLock) {
934 * The default action (used with KeyRelease event) is to cycle the
937 if (*param_count == 0) {
938 SetScrollLock(screen, !screen->scroll_lock);
939 TRACE(("HandleScrollLock ->%d\n",
940 screen->scroll_lock));
942 SetScrollLock(screen, atoi(params[0]));
943 TRACE(("HandleScrollLock(%s) ->%d\n",
945 screen->scroll_lock));