#include "openaxiom-c-macros.h"
#include "debug.h"
#include "halloc.h"
#include "sockio.h"
#include "extent.h"
#include "display.h"
#include "group.h"
#include "initx.h"
#include "scrollbar.h"
#include "parse.h"
static int ch(int height);
static void changeWindowBackgroundPixmap(Window window , Pixmap pixmap);
static void drawScroller3DEffects(HDWindow * hdWindow , int x1 , int y1 , int x2 , int y2);
static int ch(int height);
static void changeWindowBackgroundPixmap(Window window, Pixmap pixmap);
static Pixmap sup = 0, sdown = 0, sup_pressed = 0, sdown_pressed = 0, scroller = 0, scrollbar_pix = 0;
#ifdef BITMAPS2D
#define CONTROLS_3D 0
#include "sdown.bitmap"
#include "sup.bitmap"
#define BACKCOLOR gBackgroundColor
#define FORECOLOR gActiveColor
#else
#define CONTROLS_3D 1
#include "sdown3d.bitmap"
#include "sdown3dpr.bitmap"
#include "sup3d.bitmap"
#include "sup3dpr.bitmap"
#define sup_width sup3d_width
#define sup_height sup3d_height
#define sup_bits sup3d_bits
#define sdown_width sdown3d_width
#define sdown_height sdown3d_height
#define sdown_bits sdown3d_bits
#define BACKCOLOR gControlBackgroundColor
#define FORECOLOR gControlForegroundColor
#endif
#if 0
#define scroller_width 3
#define scroller_height 3
static char scroller_bits[] = {0x05, 0x07, 0x03};
#endif
#define scroller_width 2
#define scroller_height 2
static char scroller_bits[] = {
0x01, 0x02};
static int supheight = sup_height;
static int supwidth = sup_width;
#define scrollbar_pix_width 3
#define scrollbar_pix_height 3
static char scrollbar_pix_bits[] = {0x00, 0x03, 0x00};
int gScrollbarWidth = sup_width + 2;
void
makeScrollBarWindows()
{
XSetWindowAttributes at;
at.cursor = gActiveCursor;
at.event_mask = ButtonPress;
if (supwidth != sdown_width || supheight != sdown_height) {
fprintf(stderr,
"Scrollbar error, up and down pointers must have the same dimensions\n");
exit(-1);
}
if (sup == 0)
sup = XCreatePixmapFromBitmapData(
gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
const_cast<char*>(as_chars(sup_bits)), supwidth, supheight,
FORECOLOR, BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
if (sdown == 0)
sdown = XCreatePixmapFromBitmapData(
gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
const_cast<char*>(as_chars(sdown_bits)), sdown_width, sdown_height,
FORECOLOR, BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
if (CONTROLS_3D) {
sup_pressed = XCreatePixmapFromBitmapData(
gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
const_cast<char*>(as_chars(sup3dpr_bits)), sup3dpr_width, sup3dpr_height,
FORECOLOR, BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
sdown_pressed = XCreatePixmapFromBitmapData(
gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
const_cast<char*>(as_chars(sdown3dpr_bits)), sdown3dpr_width, sdown3dpr_height,
FORECOLOR, BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
}
gWindow->fScrollUpWindow = XCreateSimpleWindow(gXDisplay, gWindow->fMainWindow,
1, 1, supwidth, supheight,
gWindow->border_width,
gBorderColor,
BACKCOLOR);
gWindow->fScrollDownWindow = XCreateSimpleWindow(gXDisplay, gWindow->fMainWindow,
1, 1, sdown_width, sdown_height,
gWindow->border_width,
gBorderColor,
BACKCOLOR);
gWindow->scrollbar = XCreateSimpleWindow(gXDisplay, gWindow->fMainWindow,
1, 1, 1, 1,
gWindow->border_width,
gBorderColor,
BACKCOLOR);
gWindow->scroller = XCreateSimpleWindow(gXDisplay, gWindow->scrollbar,
1, 1, 1, 1, 0,
gBorderColor,
BACKCOLOR);
#ifdef DEBUG
fprintf(stderr, "Changing Window Attributes in scrollbar.c #2\n");
#endif
at.background_pixmap = sup;
XChangeWindowAttributes(gXDisplay, gWindow->fScrollUpWindow,
CWBackPixmap | CWEventMask | CWCursor, &at);
at.background_pixmap = sdown;
XChangeWindowAttributes(gXDisplay, gWindow->fScrollDownWindow,
CWBackPixmap | CWEventMask | CWCursor, &at);
XChangeWindowAttributes(gXDisplay, gWindow->scrollbar,
CWEventMask | CWCursor, &at);
if (scroller == 0)
scroller = XCreatePixmapFromBitmapData(gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
scroller_bits, scroller_width,
scroller_height,
FORECOLOR,
BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
if (scrollbar_pix == 0)
scrollbar_pix = XCreatePixmapFromBitmapData(gXDisplay,
RootWindow(gXDisplay, gXScreenNumber),
scrollbar_pix_bits,
scrollbar_pix_width,
scrollbar_pix_height,
FORECOLOR,
BACKCOLOR,
DefaultDepth(gXDisplay, gXScreenNumber));
at.background_pixmap = scroller;
XChangeWindowAttributes(gXDisplay, gWindow->scroller,
CWBackPixmap | CWCursor, &at);
at.background_pixmap = scrollbar_pix;
XChangeWindowAttributes(gXDisplay, gWindow->scrollbar,
CWBackPixmap, &at);
}
static void
drawScroller3DEffects(HDWindow * hdWindow, int x1, int y1, int x2, int y2)
{
XClearWindow(gXDisplay, hdWindow->scroller);
XDrawLine(gXDisplay, hdWindow->scroller, hdWindow->fControlGC,
x2 - 3, y1 + 2, x2 - 3, y2 - 3);
XDrawLine(gXDisplay, hdWindow->scroller, hdWindow->fControlGC,
x1 + 2, y2 - 3, x2 - 3, y2 - 3);
XSetBackground(gXDisplay, hdWindow->fControlGC, gControlForegroundColor);
XSetForeground(gXDisplay, hdWindow->fControlGC, gControlBackgroundColor);
XDrawLine(gXDisplay, hdWindow->scroller, hdWindow->fControlGC,
x1 + 2, y1 + 2, x2 - 3, y1 + 2);
XDrawLine(gXDisplay, hdWindow->scroller, hdWindow->fControlGC,
x1 + 2, y1 + 2, x1 + 2, y2 - 3);
XSetBackground(gXDisplay, hdWindow->fControlGC, gControlBackgroundColor);
XSetForeground(gXDisplay, hdWindow->fControlGC, gControlForegroundColor);
}
void
showScrollBars(HDWindow * hdWindow)
{
XWindowChanges wc;
if (hdWindow->page->scrolling->height <= hdWindow->scrollheight)
return;
wc.x = hdWindow->scrollx;
wc.y = hdWindow->scrollupy;
wc.height = supheight;
wc.width = supwidth;
XConfigureWindow(gXDisplay, hdWindow->fScrollUpWindow, CWX | CWY | CWHeight
| CWWidth, &wc);
wc.y = hdWindow->scrolldowny;
XConfigureWindow(gXDisplay, hdWindow->fScrollDownWindow,
CWX | CWY | CWHeight | CWWidth,
&wc);
wc.height = hdWindow->fScrollBarHeight;
wc.y = hdWindow->scrollbary;
XConfigureWindow(gXDisplay, hdWindow->scrollbar,
CWX | CWY | CWHeight | CWWidth,
&wc);
wc.x = 0;
wc.y = hdWindow->fScrollerTopPos;
wc.width = supwidth;
wc.height = hdWindow->fScrollerHeight;
XConfigureWindow(gXDisplay, hdWindow->scroller,
CWX | CWY | CWHeight | CWWidth,
&wc);
XMapWindow(gXDisplay, hdWindow->fScrollUpWindow);
XMapWindow(gXDisplay, hdWindow->fScrollDownWindow);
XMapWindow(gXDisplay, hdWindow->scrollbar);
XMapWindow(gXDisplay, hdWindow->scroller);
drawScroller3DEffects(hdWindow, 0, 0, wc.width, wc.height);
}
void
moveScroller(HDWindow * hdWindow)
{
XWindowChanges wc;
int t = (int) (hdWindow->fScrollBarHeight * (-hdWindow->page->scroll_off));
hdWindow->fScrollerTopPos = (int) (t / hdWindow->page->scrolling->height);
wc.x = 0;
wc.y = hdWindow->fScrollerTopPos;
wc.width = supwidth;
wc.height = hdWindow->fScrollerHeight;
XConfigureWindow(gXDisplay, hdWindow->scroller,
CWX | CWY | CWHeight | CWWidth,
&wc);
drawScroller3DEffects(hdWindow, 0, 0, wc.width, wc.height);
}
#define tophalf(y) ((y % 2 == 0)?(y/2):(y/2) + 1)
#define bothalf(y) (y/2)
void
drawScrollLines()
{
if (!(gWindow->page->page_flags & NOLINES)) {
line_top_group();
if (gWindow->page->header->height) {
XDrawLine(gXDisplay, gWindow->fMainWindow, gWindow->fStandardGC,
0,
gWindow->page->top_scroll_margin - tophalf(gWindow->border_width)
- 2 * scroll_top_margin,
gWindow->scrollwidth,
gWindow->page->top_scroll_margin - tophalf(gWindow->border_width)
- 2 * scroll_top_margin);
}
if (gWindow->page->footer->height) {
XDrawLine(gXDisplay, gWindow->fMainWindow, gWindow->fStandardGC,
0,
gWindow->page->bot_scroll_margin + bothalf(gWindow->border_width) - 1,
gWindow->scrollwidth,
gWindow->page->bot_scroll_margin + bothalf(gWindow->border_width) - 1);
}
pop_group_stack();
}
}
void
calculateScrollBarMeasures()
{
int t;
gWindow->scrollheight = gWindow->page->bot_scroll_margin -
gWindow->page->top_scroll_margin - scroll_top_margin;
gWindow->scrollheight = gWindow->scrollheight - gWindow->scrollheight % line_height;
if (gWindow->scrollheight >= gWindow->page->scrolling->height) {
gWindow->page->scroll_off = 0;
return;
}
gWindow->fScrollBarHeight = gWindow->page->bot_scroll_margin -
gWindow->page->top_scroll_margin - 2 * supheight -
2 * gWindow->border_width;
gWindow->scrollupy = gWindow->page->top_scroll_margin - gWindow->border_width;
gWindow->scrollupy -= 2 * scroll_top_margin;
gWindow->scrolldowny = gWindow->page->bot_scroll_margin
- supheight - gWindow->border_width;
gWindow->scrollbary = gWindow->scrollupy + supheight + gWindow->border_width;
gWindow->scrollx = gWindow->width - supwidth - gWindow->border_width;
gWindow->fScrollerHeight = 1 + 2 * scroll_top_margin +
(int) (gWindow->fScrollBarHeight * gWindow->scrollheight / gWindow->page->scrolling->height);
if (-(gWindow->page->scroll_off) >
(gWindow->page->scrolling->height - gWindow->scrollheight))
gWindow->page->scroll_off =
-(gWindow->page->scrolling->height - gWindow->scrollheight);
gWindow->fScrollBarHeight += 2 * scroll_top_margin;
t = (int) (gWindow->fScrollBarHeight * (-gWindow->page->scroll_off));
gWindow->fScrollerTopPos = (int) (t / (gWindow->page->scrolling->height));
}
void
linkScrollBars()
{
HyperLink *uplink = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
HyperLink *downlink = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
HyperLink *barlink = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
uplink->win = gWindow->fScrollUpWindow;
downlink->win = gWindow->fScrollDownWindow;
barlink->win = gWindow->scrollbar;
uplink->type = Scrollupbutton;
downlink->type = Scrolldownbutton;
barlink->type = openaxiom_Scrollbar_token;
barlink->x = barlink->y = 0;
uplink->x = uplink->y = 0;
downlink->x = downlink->y = 0;
uplink->reference.node = NULL;
downlink->reference.node = NULL;
hash_insert(gLinkHashTable, (char *)uplink,(char *) &uplink->win);
hash_insert(gLinkHashTable, (char *)barlink,(char *) &barlink->win);
hash_insert(gLinkHashTable, (char *)downlink,(char *) &downlink->win);
}
void
scrollUp()
{
if (gWindow->page->scroll_off == 0);
else {
changeWindowBackgroundPixmap(gWindow->fScrollUpWindow, sup_pressed);
gWindow->page->scroll_off += line_height;
if (gWindow->page->scroll_off > 0)
gWindow->page->scroll_off = 0;
XCopyArea(gXDisplay, gWindow->fScrollWindow, gWindow->fScrollWindow, gWindow->fStandardGC,
0, 0,
gWindow->scrollwidth, gWindow->scrollheight - line_height + 1,
0, line_height);
XClearArea(gXDisplay, gWindow->fScrollWindow, 0, 0,
gWindow->scrollwidth,
line_height, False);
scroll_page(gWindow->page);
changeWindowBackgroundPixmap(gWindow->fScrollUpWindow, sup);
}
}
void
scrollUpPage()
{
if (gWindow->page->scroll_off == 0);
else {
gWindow->page->scroll_off += ch(gWindow->scrollheight) - line_height;
if (gWindow->page->scroll_off > 0)
gWindow->page->scroll_off = 0;
XClearWindow(gXDisplay, gWindow->fScrollWindow);
scroll_page(gWindow->page);
}
}
void
scrollToFirstPage()
{
if (gWindow->page->scroll_off == 0);
else {
gWindow->page->scroll_off = 0;
XClearWindow(gXDisplay, gWindow->fScrollWindow);
scroll_page(gWindow->page);
}
}
void
scrollDown()
{
if (-(gWindow->page->scroll_off) >=
(gWindow->page->scrolling->height - gWindow->scrollheight)) {
;
}
else {
changeWindowBackgroundPixmap(gWindow->fScrollDownWindow, sdown_pressed);
gWindow->page->scroll_off -= line_height;
XCopyArea(gXDisplay, gWindow->fScrollWindow, gWindow->fScrollWindow, gWindow->fStandardGC,
0, line_height,
gWindow->scrollwidth, gWindow->scrollheight - line_height + 1,
0, 0);
XClearArea(gXDisplay, gWindow->fScrollWindow, 0,
gWindow->scrollheight - line_height,
gWindow->scrollwidth,
line_height, False);
scroll_page(gWindow->page);
changeWindowBackgroundPixmap(gWindow->fScrollDownWindow, sdown);
}
}
void
scrollDownPage()
{
if (gWindow->page->scrolling == NULL || (-(gWindow->page->scroll_off) >=
(gWindow->page->scrolling->height - gWindow->scrollheight))) {
;
}
else {
gWindow->page->scroll_off -= ch(gWindow->scrollheight) - line_height;
if (-(gWindow->page->scroll_off) >
(gWindow->page->scrolling->height - gWindow->scrollheight))
gWindow->page->scroll_off = -
(gWindow->page->scrolling->height - gWindow->scrollheight);
XClearWindow(gXDisplay, gWindow->fScrollWindow);
scroll_page(gWindow->page);
}
}
void
scrollScroller(XButtonEvent * event)
{
int y = event->y;
int top = y;
if (top < 0) {
top = 0;
if (gWindow->fScrollerTopPos == 0)
return;
gWindow->page->scroll_off = 0;
}
else if ((top + gWindow->fScrollerHeight) > gWindow->fScrollBarHeight) {
top = gWindow->fScrollBarHeight - gWindow->fScrollerHeight;
if (top == gWindow->fScrollerTopPos)
return;
gWindow->page->scroll_off =
-(gWindow->page->scrolling->height - gWindow->scrollheight);
gWindow->page->scroll_off -= gWindow->page->scroll_off % line_height;
}
else {
int t;
t = -(gWindow->page->scrolling->height) * top;
t = t / (gWindow->fScrollBarHeight);
if (gWindow->page->scroll_off == (t -= t % line_height))
return;
gWindow->page->scroll_off = t;
gWindow->fScrollerTopPos = top;
}
XClearWindow(gXDisplay, gWindow->fScrollWindow);
scroll_page(gWindow->page);
}
void
hideScrollBars(HDWindow * hdWindow)
{
XUnmapWindow(gXDisplay, hdWindow->fScrollDownWindow);
XUnmapWindow(gXDisplay, hdWindow->fScrollUpWindow);
XUnmapWindow(gXDisplay, hdWindow->scrollbar);
XUnmapWindow(gXDisplay, hdWindow->scroller);
}
void
getScrollBarMinimumSize(int *width, int *height)
{
(*width) = sup_width + 4;
(*height) = sup_height + sdown_height + 5;
}
static int
ch(int height)
{
int rem = height % line_height;
if (rem == 0)
return height;
return height - rem + line_height;
}
static void
changeWindowBackgroundPixmap(Window window, Pixmap pixmap)
{
if (pixmap) {
XSetWindowAttributes at;
at.background_pixmap = pixmap;
XChangeWindowAttributes(gXDisplay, window, CWBackPixmap, &at);
XClearWindow(gXDisplay, window);
}
}