|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 17852 (0x45bc)
Types: TextFile
Names: »scrollbar.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/xterm/scrollbar.c«
/*
* $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.6\t11/3/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