home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Source: /u1/X/xterm/RCS/scrollbar.c,v $
- * $Header: scrollbar.c,v 10.100 86/12/01 14:45:27 jg Rel $
- */
-
- #include <stdio.h>
- #include <sys/time.h>
- #include <X/Xlib.h>
- #include <setjmp.h>
- #include "scrollbar.h"
- #include "ptyx.h"
- #include "data.h"
- #include "error.h"
- #ifdef MODEMENU
- #include "menu.h"
- #endif MODEMENU
-
- #include "button.ic"
- #include "dark.ic"
- #include "light.ic"
- #include "upline.ic"
- #include "downline.ic"
- #include "uppage.ic"
- #include "downpage.ic"
- #include "top.ic"
- #include "bottom.ic"
- #include "saveoff.ic"
- #include "saveon.ic"
- #ifndef lint
- static char sccs_id[] = "@(#)scrollbar.c\tX10/6.6B\t12/26/86";
- #endif lint
-
- static struct timeval stepspeed;
-
- ScrollBar *
- CreateScrollBar(w, x, y, height, fg, bg, bordertile, val, valregion,
- topval, botval, arrow)
- Window w;
- int x, y, height, fg, bg, val, valregion, topval, botval;
- Pixmap bordertile;
- Cursor arrow;
- {
- register ScrollBar *sb;
- register int i;
- Pixmap btile, bgnd;
- extern char *calloc();
- static Window Make_tiled_window();
- extern Pixmap Make_tile();
-
- if(!w || height < MINSCROLLBARHEIGHT ||
- (sb = (ScrollBar *)calloc(1, sizeof(ScrollBar))) == NULL)
- return(NULL);
- btile = bordertile;
- if(bg == BlackPixel && fg == WhitePixel) {
- bg = WhitePixel;
- fg = BlackPixel;
- if(btile == WhitePixmap)
- btile = BlackPixmap;
- }
- sb->fg = fg;
- sb->bg = bg;
- sb->cursor = arrow;
- if((sb->bar = Make_tiled_window(light_width, light_height, light_bits,
- fg, bg, &bgnd, w, x, y, (SCROLLBARWIDTH - 1), height, 1, bordertile))
- == NULL)
- goto failed_bar;
- if((sb->button = XCreateWindow(sb->bar, -1, -1, (SCROLLBARWIDTH - 1),
- BUTTONHEIGHT - 1, 1, btile, bgnd)) == NULL)
- goto failed_button;
- if((sb->save = XCreateWindow(sb->bar, -1, BUTTONHEIGHT - 1,
- (SCROLLBARWIDTH - 1), BUTTONHEIGHT - 1, 1, btile, bgnd)) == NULL)
- goto failed_save;
- if((sb->region = Make_tiled_window(dark_width, dark_height, dark_bits,
- fg, bg, &bgnd, sb->bar, 0, 0, (SCROLLBARWIDTH - 1), 10, 0,
- (Pixmap)NULL)) == NULL) {
- XDestroyWindow(sb->save);
- failed_save:
- XDestroyWindow(sb->button);
- failed_button:
- XDestroyWindow(sb->bar);
- failed_bar:
- free((char *)sb);
- return(NULL);
- }
- sb->savebits[SAVE_OFF] = saveoff_bits;
- sb->savebits[SAVE_ON] = saveon_bits;
- sb->buttonbits[BUTTON_UPLINE / 2] = upline_bits;
- sb->buttonbits[BUTTON_DOWNLINE / 2] = downline_bits;
- sb->buttonbits[BUTTON_UPPAGE / 2] = uppage_bits;
- sb->buttonbits[BUTTON_DOWNPAGE / 2] = downpage_bits;
- sb->buttonbits[BUTTON_TOP / 2] = top_bits;
- sb->buttonbits[BUTTON_BOTTOM / 2] = bottom_bits;
- sb->buttonbits[BUTTON_NORMAL / 2] = button_bits;
- XDefineCursor(sb->bar, sb->cursor);
- XSelectInput(sb->bar, ButtonPressed | ButtonReleased | ExposeWindow |
- EnterWindow | LeaveWindow | UnmapWindow);
- XSelectInput(sb->button, EnterWindow | LeaveWindow);
- XMapWindow(sb->button); /* will really map when bar is mapped */
- XMapWindow(sb->save); /* will really map when bar is mapped */
- sb->buttonstate = sb->buttonset = BUTTON_NORMAL;
- sb->savestate = sb->saveset = SAVE_ON;
- sb->set.value = val;
- sb->set.regionheight = valregion;
- sb->set.topvalue = topval;
- sb->set.bottomvalue = botval;
- sb->set.height = height - BARSTART;
- return(sb);
- }
-
- ShowScrollBar(sb)
- register ScrollBar *sb;
- {
- if(sb->visible)
- return;
- sb->visible = 1;
- if(sb->regionvisible) {
- XUnmapWindow(sb->region);
- sb->regionvisible = 0;
- }
- XMapWindow(sb->bar);
- DrawScrollRegion(sb);
- sb->action = SHOW;
- }
-
- HideScrollBar(sb)
- register ScrollBar *sb;
- {
- if(!sb->visible)
- return;
- sb->visible = 0;
- XUnmapWindow(sb->bar);
- }
-
- DrawScrollRegion(sb)
- register ScrollBar *sb;
- {
- register int region, temp;
-
- if(sb->set.regionheight <= 0)
- sb->set.regionheight = 0;
- if((region = sb->set.topvalue - sb->set.bottomvalue) >= 0) {
- if(sb->set.value > sb->set.topvalue)
- sb->set.value = sb->set.topvalue;
- else if(sb->set.value < sb->set.bottomvalue)
- sb->set.value = sb->set.bottomvalue;
- } else {
- region = -region;
- if(sb->set.value < sb->set.topvalue)
- sb->set.value = sb->set.topvalue;
- else if(sb->set.value > sb->set.bottomvalue)
- sb->set.value = sb->set.bottomvalue;
- }
- if(sb->set.value == sb->set.topvalue) {
- sb->set.pixelheight = (region == 0) ? sb->set.height :
- (sb->set.height - 1) * sb->set.regionheight /
- (sb->set.regionheight + region);
- sb->set.y = BARSTART;
- } else if(sb->set.value == sb->set.bottomvalue) {
- sb->set.pixelheight = (sb->set.height - 1) *
- sb->set.regionheight / (sb->set.regionheight + region);
- sb->set.y = BARSTART + sb->set.height - sb->set.pixelheight;
- } else {
- if(sb->set.topvalue >= sb->set.bottomvalue) {
- temp = sb->set.topvalue - 1;
- region = temp - (sb->set.bottomvalue + 1);
- sb->set.y = temp - sb->set.value;
- } else {
- temp = sb->set.topvalue + 1;
- region = (sb->set.bottomvalue - 1) - temp;
- sb->set.y = sb->set.value - temp;
- }
- sb->set.y = (BARSTART + 1) + sb->set.y * (sb->set.height - 2) /
- (temp = sb->set.regionheight + region);
- sb->set.pixelheight = (sb->set.height - 2) *
- sb->set.regionheight / temp;
- }
- if(sb->set.pixelheight <= 0)
- sb->set.pixelheight = 1;
- if(sb->set.regionheight == 0) {
- sb->state = sb->set;
- if(sb->regionvisible) {
- XUnmapWindow(sb->region);
- sb->regionvisible = 0;
- }
- return;
- }
- if(!sb->visible || sb->regionvisible
- && sb->state.y == sb->set.y
- && sb->state.pixelheight == sb->set.pixelheight) {
- sb->state = sb->set;
- return;
- }
- sb->state = sb->set;
- XConfigureWindow(sb->region, 0, sb->state.y, (SCROLLBARWIDTH - 1),
- sb->state.pixelheight);
- if(!sb->regionvisible) {
- XMapWindow(sb->region);
- sb->regionvisible = 1;
- }
- }
-
- DrawButton(sb)
- register ScrollBar *sb;
- {
- register int fg, bg;
-
- if(sb->visible && sb->buttonstate != sb->buttonset) {
- if((sb->buttonstate = sb->buttonset) & HILITED) {
- fg = sb->bg;
- bg = sb->fg;
- } else {
- fg = sb->fg;
- bg = sb->bg;
- }
- XBitmapBitsPut(sb->button, 0, 0, SCROLLBARWIDTH - 1,
- BUTTONHEIGHT - 1, sb->buttonbits[sb->buttonstate / 2],
- fg, bg, (Bitmap)0, GXcopy, AllPlanes);
- }
- }
-
- DrawSave(sb)
- register ScrollBar *sb;
- {
- if(sb->visible && sb->savestate != sb->saveset)
- XBitmapBitsPut(sb->save, 0, 0, SCROLLBARWIDTH - 1,
- BUTTONHEIGHT - 1, sb->savebits[sb->savestate = sb->saveset],
- sb->fg, sb->bg, (Bitmap)0, GXcopy, AllPlanes);
- }
-
- ResizeScrollBar(sb, x, y, height, region)
- register ScrollBar *sb;
- int x, y, height, region;
- {
- register int act;
-
- act = sb->action;
- sb->action = NONE;
- switch(act) {
- case SHOW:
- return;
- case HIDE:
- HideScrollBar(sb);
- return;
- }
- if(!sb->visible)
- return;
- if(sb->regionvisible) {
- XUnmapWindow(sb->region);
- sb->regionvisible = 0;
- }
- XConfigureWindow(sb->bar, x, y, (SCROLLBARWIDTH - 1), height);
- sb->set.height = height - BARSTART;
- sb->set.regionheight = region;
- DrawScrollRegion(sb);
- }
-
- PositionRegion(sb, y)
- register ScrollBar *sb;
- register int y;
- {
- if(y <= BARSTART)
- sb->set.value = sb->set.topvalue;
- else if(y >= BARSTART + sb->set.height *
- (sb->set.bottomvalue - sb->set.topvalue) /
- (sb->set.bottomvalue + sb->set.regionheight - sb->set.topvalue))
- sb->set.value = sb->set.bottomvalue;
- else
- sb->set.value = sb->set.topvalue + (y - BARSTART) *
- (sb->set.bottomvalue + sb->set.regionheight - sb->set.topvalue)
- / sb->set.height;
- DrawScrollRegion(sb);
- return(sb->state.value);
- }
-
- ButtonRegion(sb)
- register ScrollBar *sb;
- {
- register int reverse, pagesize;
-
- if(!(sb->buttonset & HILITED))
- return(sb->set.value);
- reverse = (sb->set.bottomvalue > sb->set.topvalue);
- pagesize = sb->set.regionheight - 1;
- switch(sb->buttonset) {
- case BUTTON_UPLINEHI:
- if(reverse)
- sb->set.value--;
- else
- sb->set.value++;
- break;
- case BUTTON_DOWNLINEHI:
- if(reverse)
- sb->set.value++;
- else
- sb->set.value--;
- break;
- case BUTTON_UPPAGEHI:
- if(reverse)
- sb->set.value -= pagesize;
- else
- sb->set.value += pagesize;
- break;
- case BUTTON_DOWNPAGEHI:
- if(reverse)
- sb->set.value += pagesize;
- else
- sb->set.value -= pagesize;
- break;
- case BUTTON_TOPHI:
- sb->set.value = sb->set.topvalue;
- break;
- case BUTTON_BOTTOMHI:
- sb->set.value = sb->set.bottomvalue;
- }
- DrawScrollRegion(sb);
- return(sb->set.value);
- }
-
- DownButtonDown(term, reply, pty)
- Terminal *term;
- register XKeyOrButtonEvent *reply;
- int pty; /* file descriptor of pty */
- {
- register Screen *screen = &term->screen;
- register ScrollBar *sb = screen->sb;
- register Window window = reply->subwindow;
-
- if(!window || window == sb->region) {
- WindowScroll(screen, PositionRegion(sb, reply->y));
- return;
- }
- if(window == sb->save) {
- SetSaveState(sb, !GetSaveState(sb));
- return;
- }
- if(window != sb->button || !XGrabMouse(sb->button, sb->cursor,
- ButtonReleased | EnterWindow | LeaveWindow)) {
- Bell();
- return;
- }
- if(reply->detail & ControlMask)
- sb->buttonset = BUTTON_BOTTOMHI;
- else if(reply->detail & ShiftMask)
- sb->buttonset = BUTTON_DOWNPAGEHI;
- else {
- sb->buttonset = BUTTON_DOWNLINEHI;
- stepspeed.tv_usec = PAUSETIME;
- screen->timeout = &stepspeed;
- WindowScroll(screen, ButtonRegion(screen->sb));
- }
- DrawButton(sb);
- }
-
- UpButtonDown(term, reply, pty)
- Terminal *term;
- register XKeyOrButtonEvent *reply;
- int pty; /* file descriptor of pty */
- {
- register Screen *screen = &term->screen;
- register ScrollBar *sb = screen->sb;
- register Window window = reply->subwindow;
-
- if(!window || window == sb->region) {
- WindowScroll(screen, PositionRegion(sb, reply->y));
- return;
- }
- if(window == sb->save) {
- SetSaveState(sb, !GetSaveState(sb));
- return;
- }
- if(window != sb->button || !XGrabMouse(sb->button, sb->cursor,
- ButtonReleased | EnterWindow | LeaveWindow)) {
- Bell();
- return;
- }
- if(reply->detail & ControlMask)
- sb->buttonset = BUTTON_TOPHI;
- else if(reply->detail & ShiftMask)
- sb->buttonset = BUTTON_UPPAGEHI;
- else {
- sb->buttonset = BUTTON_UPLINEHI;
- stepspeed.tv_usec = PAUSETIME;
- screen->timeout = &stepspeed;
- WindowScroll(screen, ButtonRegion(screen->sb));
- }
- DrawButton(sb);
- }
-
- ButtonUp(term, reply, pty)
- Terminal *term;
- XKeyOrButtonEvent *reply;
- int pty; /* file descriptor of pty */
- {
- register Screen *screen = &term->screen;
- register ScrollBar *sb = screen->sb;
- register int state;
-
- if((state = GetButtonState(sb)) == BUTTON_NORMAL)
- return;
- /* don't scroll further on line mode */
- if(state > BUTTON_DOWNLINEHI)
- WindowScroll(screen, ButtonRegion(sb));
- sb->buttonset = BUTTON_NORMAL;
- DrawButton(sb);
- screen->timeout = NULL;
- XUngrabMouse();
- }
-
- WindowScroll(screen, top)
- register Screen *screen;
- int top;
- {
- register int i, lines;
- register int scrolltop, scrollheight, refreshtop;
-
- if((i = screen->topline - top) == 0)
- return;
- if(screen->cursor_state)
- HideCursor();
- lines = i > 0 ? i : -i;
- if(lines > screen->max_row + 1)
- lines = screen->max_row + 1;
- scrollheight = screen->max_row - lines + 1;
- if(i > 0)
- refreshtop = scrolltop = 0;
- else {
- scrolltop = lines;
- refreshtop = scrollheight;
- }
- if(scrollheight > 0) {
- if (screen->multiscroll && scrollheight == 1 &&
- screen->topline == 0 && screen->top_marg == 0 &&
- screen->bot_marg == screen->max_row) {
- if (screen->incopy < 0 && screen->scrolls == 0)
- CopyWait (screen);
- screen->scrolls++;
- } else {
- if (screen->incopy)
- CopyWait (screen);
- screen->incopy = -1;
- }
- XMoveArea(VWindow(screen), screen->border, scrolltop *
- FontHeight(screen) + screen->border + Titlebar(screen),
- screen->border, (scrolltop + i) * FontHeight(screen) +
- screen->border + Titlebar(screen), Width(screen),
- scrollheight * FontHeight(screen));
- }
- screen->topline = top;
- XTileSet(VWindow(screen), screen->border, refreshtop * FontHeight(screen) +
- screen->border + Titlebar(screen), Width(screen), lines *
- FontHeight(screen), screen->bgndtile);
- ScrnRefresh(screen, refreshtop, 0, lines, screen->max_col + 1);
- }
-
- ScrollBarOn(screen, show, init)
- register Screen *screen;
- int show, init;
- {
- register int border = 2 * screen->border;
- register int i;
- char *realloc(), *calloc();
-
- if(screen->scrollbar)
- return;
- if(!screen->sb) {
- if((screen->sb = CreateScrollBar(VWindow(screen),
- Width(screen) + border, Titlebar(screen) - 1,
- Height(screen) + border, screen->foreground,
- screen->background, screen->bordertile, 0,
- screen->max_row + 1, 0, 0, screen->arrow)) == NULL) {
- Bell();
- return;
- }
- if((screen->allbuf = (ScrnBuf) realloc(screen->buf,
- 2*(screen->max_row + 2 + screen->savelines) * sizeof(char *)))
- == NULL)
- Error (ERROR_SBRALLOC);
- screen->buf = &screen->allbuf[2 * screen->savelines];
- bcopy ((char *)screen->allbuf, (char *)screen->buf,
- 2 * (screen->max_row + 2) * sizeof (char *));
- for(i = 2 * screen->savelines - 1 ; i >= 0 ; i--)
- if((screen->allbuf[i] =
- calloc(screen->max_col + 1, sizeof(char))) == NULL)
- Error (ERROR_SBRALLOC2);
- screen->sb->saveset = !screen->alternate;
- } else {
- XConfigureWindow(screen->sb->bar, FullWidth(screen),
- Titlebar(screen) - 1, (SCROLLBARWIDTH - 1),
- i = FullHeight(screen) - Titlebar(screen));
- screen->sb->set.height = i - BARSTART;
- screen->sb->set.regionheight = screen->max_row + 1;
- }
- if(show) {
- screen->scrollbar = SCROLLBARWIDTH;
- ShowScrollBar(screen->sb);
- if(!init) {
- XSetResizeHint(VWindow(screen), border + SCROLLBARWIDTH,
- border + Titlebar(screen) + screen->statusheight,
- FontWidth(screen), FontHeight(screen));
- XChangeWindow(VWindow(screen), (screen->max_col + 1) *
- FontWidth(screen) + border + SCROLLBARWIDTH,
- FontHeight(screen) * (screen->max_row + 1) +
- screen->statusheight + border + Titlebar(screen));
- }
- }
- }
-
- ScrollBarOff(screen)
- register Screen *screen;
- {
- register int border = 2 * screen->border;
-
- if(!screen->scrollbar)
- return;
- screen->sb->action = HIDE;
- screen->scrollbar = 0;
- XSetResizeHint(VWindow(screen), border, border + Titlebar(screen) +
- screen->statusheight, FontWidth(screen), FontHeight(screen));
- XChangeWindow(VWindow(screen), (screen->max_col + 1) * FontWidth(screen) +
- border, FontHeight(screen) * (screen->max_row + 1) + screen->statusheight
- + border + Titlebar(screen));
- }
-
- ClearLinesOffTop(screen)
- register Screen *screen;
- {
- if(!screen->sb)
- return;
- if(screen->topline)
- WindowScroll(screen, 0);
- SetScrollBarTop(screen->sb, 0);
- DrawScrollRegion(screen->sb);
- }
-
- SetSaveState(sb, state)
- register ScrollBar *sb;
- int state;
- {
- extern Terminal term;
- register Screen *screen = &term.screen;
-
- if(screen->alternate)
- return;
- if(screen->scroll_amt)
- FlushScroll(screen);
- sb->saveset = state;
- DrawSave(sb);
- }
-
- SetButtonState(sb, state)
- register ScrollBar *sb;
- int state;
- {
- sb->buttonset = state;
- DrawButton(sb);
- }
-
- static Window
- Make_tiled_window(bitmap_width, bitmap_height, bitmap_bits, foreground,
- background, bgnd, parent, x, y, width, height, borderwidth, bordertile)
- int bitmap_width, bitmap_height, foreground, background, x, y, width,
- height, borderwidth;
- short *bitmap_bits;
- Window parent;
- Pixmap *bgnd, bordertile;
- {
- register Pixmap pix;
- register Window w;
- extern Pixmap Make_tile();
-
- if((pix = Make_tile(bitmap_width, bitmap_height, bitmap_bits,
- foreground, background)) == NULL)
- return(NULL);
- w = XCreateWindow(parent, x, y, width, height, borderwidth, bordertile,
- pix);
- *bgnd = pix;
- return(w);
- }
-
- Pixmap
- Make_tile(bitmap_width, bitmap_height, bitmap_bits, foreground, background)
- int bitmap_width, bitmap_height, foreground, background;
- short *bitmap_bits;
- {
- register Bitmap bm;
- register Pixmap pix;
-
- if((bm = XStoreBitmap(bitmap_width, bitmap_height, bitmap_bits))
- == NULL)
- return(NULL);
- pix = XMakePixmap(bm, foreground, background);
- XFreeBitmap(bm);
- return(pix);
- }
-
- ScrollToBottom(sb)
- register ScrollBar *sb;
- {
- SetScrollBarValue(sb, GetScrollBarBottom(sb));
- DrawScrollRegion(sb);
- WindowScroll(&term.screen, GetScrollBarValue(sb));
- }
-
- #ifdef MODEMENU
- #define SMENU_SCROLLKEY 0
- #define SMENU_SCROLLINPUT (SMENU_SCROLLKEY+1)
- #define SMENU_LINESTOP (SMENU_SCROLLINPUT+1)
- #define SMENU_LINE (SMENU_LINESTOP+1)
- #define SMENU_CLEARTOP (SMENU_LINE+1)
- #define SMENU_HIDE (SMENU_CLEARTOP+1)
-
- static char *stext[] = {
- "Scroll to Bottom on Key",
- "Scroll to Bottom on Input",
- "Lines Off Top Saved",
- "-",
- "Clear Lines Off Top",
- "Hide Scrollbar",
- 0,
- };
-
-
- static int salternate;
- static int slinestop;
- static int sscrollinput;
- static int sscrollkey;
-
- Menu *ssetupmenu(menu)
- register Menu **menu;
- {
- register Screen *screen = &term.screen;
- register char **cp;
-
- if (*menu == NULL) {
- if ((*menu = NewMenu("Scrollbar", re_verse)) == NULL)
- return(NULL);
- for(cp = stext ; *cp ; cp++)
- AddMenuItem(*menu, *cp);
- if(sscrollkey = screen->scrollkey)
- CheckItem(*menu, SMENU_SCROLLKEY);
- if(sscrollinput = screen->scrollinput)
- CheckItem(*menu, SMENU_SCROLLINPUT);
- if(slinestop = (screen->sb && GetSaveState(screen->sb)))
- CheckItem(*menu, SMENU_LINESTOP);
- if(salternate = screen->alternate)
- DisableItem(*menu, SMENU_LINESTOP);
- DisableItem(*menu, SMENU_LINE);
- return(*menu);
- }
- if(sscrollkey != screen->scrollkey)
- SetItemCheck(*menu, SMENU_SCROLLKEY, (sscrollkey =
- screen->scrollkey));
- if(sscrollinput != screen->scrollinput)
- SetItemCheck(*menu, SMENU_SCROLLINPUT, (sscrollinput =
- screen->scrollinput));
- if(screen->sb && slinestop != GetSaveState(screen->sb))
- SetItemCheck(*menu, SMENU_LINESTOP, (slinestop =
- GetSaveState(screen->sb)));
- if(salternate != screen->alternate)
- SetItemDisable(*menu, SMENU_LINESTOP, (salternate =
- screen->alternate));
- return(*menu);
- }
-
- sdomenufunc(item)
- int item;
- {
- register Screen *screen = &term.screen;
-
- switch (item) {
- case SMENU_SCROLLKEY:
- screen->scrollkey = !screen->scrollkey;
- break;
-
- case SMENU_SCROLLINPUT:
- screen->scrollinput = !screen->scrollinput;
- break;
-
- case SMENU_LINESTOP:
- SetSaveState(screen->sb, !GetSaveState(screen->sb));
- break;
-
- case SMENU_CLEARTOP:
- ClearLinesOffTop(screen);
- break;
-
- case SMENU_HIDE:
- ScrollBarOff(screen);
- break;
- }
- }
- #endif MODEMENU
-