Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wscrollview.c
dissimilarity index 97%
index 0285a23..7733e27 100644 (file)
-
-
-
-
-#include "WINGsP.h"
-
-
-typedef struct W_ScrollView {
-    W_Class widgetClass;
-    WMView *view;
-
-    WMView *contentView;
-    WMView *viewport;
-
-    WMScroller *vScroller;
-    WMScroller *hScroller;
-
-    short lineScroll;
-    short pageScroll;
-
-    struct {
-        WMReliefType relief:3;
-        unsigned int hasVScroller:1;
-        unsigned int hasHScroller:1;
-
-    } flags;
-
-} ScrollView;
-
-
-
-
-static void destroyScrollView(ScrollView *sPtr);
-
-static void paintScrollView(ScrollView *sPtr);
-static void handleEvents(XEvent *event, void *data);
-static void handleViewportEvents(XEvent *event, void *data);
-static void resizeScrollView();
-static void updateScrollerProportion();
-
-W_ViewDelegate _ScrollViewViewDelegate = {
-    NULL,
-    NULL,
-    resizeScrollView,
-    NULL,
-    NULL
-};
-
-
-
-WMScrollView*
-WMCreateScrollView(WMWidget *parent)
-{
-    ScrollView *sPtr;
-
-    sPtr = wmalloc(sizeof(ScrollView));
-    memset(sPtr, 0, sizeof(ScrollView));
-
-    sPtr->widgetClass = WC_ScrollView;
-
-    sPtr->view = W_CreateView(W_VIEW(parent));
-    if (!sPtr->view) {
-        wfree(sPtr);
-        return NULL;
-    }
-    sPtr->viewport = W_CreateView(sPtr->view);
-    if (!sPtr->viewport) {
-        W_DestroyView(sPtr->view);
-        wfree(sPtr);
-        return NULL;
-    }
-    sPtr->view->self = sPtr;
-    sPtr->viewport->self = sPtr;
-
-    sPtr->view->delegate = &_ScrollViewViewDelegate;
-
-    sPtr->viewport->flags.mapWhenRealized = 1;
-
-    WMCreateEventHandler(sPtr->view, StructureNotifyMask|ExposureMask,
-                         handleEvents, sPtr);
-    WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask,
-                         handleViewportEvents, sPtr);
-
-    sPtr->lineScroll = 4;
-
-    sPtr->pageScroll = 0;
-
-    return sPtr;
-}
-
-
-static void
-applyScrollerValues(WMScrollView *sPtr)
-{
-    int x, y;
-
-    if (sPtr->contentView == NULL)
-        return;
-
-    if (sPtr->flags.hasHScroller) {
-        float v = WMGetScrollerValue(sPtr->hScroller);
-        int size;
-
-        size = sPtr->contentView->size.width-sPtr->viewport->size.width;
-
-        x = v * size;
-    } else {
-        x = 0;
-    }
-
-    if (sPtr->flags.hasVScroller) {
-        float v = WMGetScrollerValue(sPtr->vScroller);
-
-        int size;
-
-        size = sPtr->contentView->size.height-sPtr->viewport->size.height;
-
-        y = v * size;
-    } else {
-        y = 0;
-    }
-
-
-
-    x = WMAX(0, x);
-    y = WMAX(0, y);
-
-    W_MoveView(sPtr->contentView, -x, -y);
-
-    W_RaiseView(sPtr->viewport);
-}
-
-
-static void
-reorganizeInterior(WMScrollView *sPtr)
-{
-    int hx, hy, hw;
-    int vx, vy, vh;
-    int cx, cy, cw, ch;
-
-
-    cw = hw = sPtr->view->size.width;
-    vh = ch = sPtr->view->size.height;
-
-    if (sPtr->flags.relief == WRSimple) {
-        cw -= 2;
-        ch -= 2;
-        cx = 1;
-        cy = 1;
-    } else if (sPtr->flags.relief != WRFlat) {
-        cw -= 3;
-        ch -= 3;
-        cx = 2;
-        cy = 2;
-    } else {
-        cx = 0;
-        cy = 0;
-    }
-
-    if (sPtr->flags.hasHScroller) {
-        int h = 20;
-
-        ch -= h;
-
-        if (sPtr->flags.relief == WRSimple) {
-            hx = 0;
-            hy = sPtr->view->size.height - h;
-        } else if (sPtr->flags.relief != WRFlat) {
-            hx = 1;
-            hy = sPtr->view->size.height - h - 1;
-            hw -= 2;
-        } else {
-            hx = 0;
-            hy = sPtr->view->size.height - h;
-        }
-    } else {
-        /* make compiler shutup */
-        hx = 0;
-        hy = 0;
-    }
-
-    if (sPtr->flags.hasVScroller) {
-        int w = 20;
-        cw -= w;
-        cx += w;
-        hx += w - 1;
-        hw -= w - 1;
-
-        if (sPtr->flags.relief == WRSimple) {
-            vx = 0;
-            vy = 0;
-        } else if (sPtr->flags.relief != WRFlat) {
-            vx = 1;
-            vy = 1;
-            vh -= 2;
-        } else {
-            vx = 0;
-            vy = 0;
-        }
-    } else {
-        /* make compiler shutup */
-        vx = 0;
-        vy = 0;
-    }
-
-    W_ResizeView(sPtr->viewport, cw, ch);
-    W_MoveView(sPtr->viewport, cx, cy);
-
-    if (sPtr->flags.hasHScroller) {
-        WMResizeWidget(sPtr->hScroller, hw, 20);
-        WMMoveWidget(sPtr->hScroller, hx, hy);
-    }
-    if (sPtr->flags.hasVScroller) {
-        WMResizeWidget(sPtr->vScroller, 20, vh);
-        WMMoveWidget(sPtr->vScroller, vx, vy);
-    }
-
-    applyScrollerValues(sPtr);
-}
-
-
-static void
-resizeScrollView(W_ViewDelegate *self, WMView *view)
-{
-    reorganizeInterior(view->self);
-    updateScrollerProportion(view->self);
-}
-
-
-
-void
-WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width,
-                          unsigned int height)
-{
-    int w, h, x;
-
-    w = width;
-    h = height;
-
-    x = 0;
-    if (sPtr->flags.relief == WRSimple) {
-        w += 2;
-        h += 2;
-    } else if (sPtr->flags.relief != WRFlat) {
-        w += 4;
-        h += 4;
-        x = 1;
-    }
-
-    if (sPtr->flags.hasVScroller) {
-        WMResizeWidget(sPtr->vScroller, 20, h);
-        width -= W_VIEW(sPtr->vScroller)->size.width;
-    }
-
-    if (sPtr->flags.hasHScroller) {
-        WMResizeWidget(sPtr->hScroller, w, 20);
-        WMMoveWidget(sPtr->hScroller, x, h);
-        height -= W_VIEW(sPtr->hScroller)->size.height;
-    }
-
-    W_ResizeView(sPtr->view, w, h);
-
-    W_ResizeView(sPtr->viewport, width, height);
-}
-
-
-void
-WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
-{
-    assert(amount > 0);
-
-    sPtr->lineScroll = amount;
-}
-
-
-void
-WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
-{
-    assert(amount >= 0);
-
-    sPtr->pageScroll = amount;
-}
-
-
-WMRect
-WMGetScrollViewVisibleRect(WMScrollView *sPtr)
-{
-    WMRect rect;
-
-    rect.pos.x = -sPtr->contentView->pos.x;
-    rect.pos.y = -sPtr->contentView->pos.y;
-    rect.size = sPtr->viewport->size;
-
-    return rect;
-}
-
-
-void
-WMScrollViewScrollPoint(WMScrollView *sPtr, WMPoint point)
-{
-    float xsize, ysize;
-    float xpos, ypos;
-
-    xsize = sPtr->contentView->size.width-sPtr->viewport->size.width;
-    ysize = sPtr->contentView->size.height-sPtr->viewport->size.height;
-
-    xpos = point.x / xsize;
-    ypos = point.y / ysize;
-
-    if (sPtr->hScroller)
-        WMSetScrollerParameters(sPtr->hScroller, xpos,
-                                WMGetScrollerKnobProportion(sPtr->hScroller));
-    if (sPtr->vScroller)
-        WMSetScrollerParameters(sPtr->vScroller, ypos,
-                                WMGetScrollerKnobProportion(sPtr->vScroller));
-
-    W_MoveView(sPtr->contentView, -point.x, -point.y);
-}
-
-
-static void
-doScrolling(WMWidget *self, void *data)
-{
-    ScrollView *sPtr = (ScrollView*)data;
-    float value;
-    int pos;
-    int vpsize;
-    float size;
-
-    if (sPtr->hScroller == (WMScroller *)self) {
-        pos = -sPtr->contentView->pos.x;
-        size = sPtr->contentView->size.width-sPtr->viewport->size.width;
-        vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
-    } else {
-        pos = -sPtr->contentView->pos.y;
-        size = sPtr->contentView->size.height-sPtr->viewport->size.height;
-        vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
-    }
-    if (vpsize <= 0)
-        vpsize = 1;
-
-    switch (WMGetScrollerHitPart(self)) {
-    case WSDecrementLine:
-        if (pos > 0) {
-            pos-=sPtr->lineScroll;
-            if (pos < 0)
-                pos = 0;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-    case WSIncrementLine:
-        if (pos < size) {
-            pos+=sPtr->lineScroll;
-            if (pos > size)
-                pos = size;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-
-    case WSKnob:
-        value = WMGetScrollerValue(self);
-        pos = value*size;
-        break;
-
-    case WSDecrementPage:
-        if (pos > 0) {
-            pos -= vpsize;
-            if (pos < 0)
-                pos = 0;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-
-    case WSDecrementWheel:
-        if (pos > 0) {
-            pos -= vpsize/3;
-            if (pos < 0)
-                pos = 0;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-
-    case WSIncrementPage:
-        if (pos < size) {
-            pos += vpsize;
-            if (pos > size)
-                pos = size;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-
-    case WSIncrementWheel:
-        if (pos < size) {
-            pos += vpsize/3;
-            if (pos > size)
-                pos = size;
-            value = (float)pos / size;
-            WMSetScrollerParameters(self, value,
-                                    WMGetScrollerKnobProportion(self));
-        }
-        break;
-
-    case WSNoPart:
-    case WSKnobSlot:
-        break;
-    }
-
-    if (sPtr->hScroller == (WMScroller *)self) {
-        W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
-    } else {
-        W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
-    }
-}
-
-
-WMScroller*
-WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
-{
-    return sPtr->hScroller;
-}
-
-
-
-WMScroller*
-WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
-{
-    return sPtr->vScroller;
-}
-
-
-void
-WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
-{
-    if (flag) {
-        if (sPtr->flags.hasHScroller)
-            return;
-        sPtr->flags.hasHScroller = 1;
-
-        sPtr->hScroller = WMCreateScroller(sPtr);
-        WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
-        /* make it a horiz. scroller */
-        WMResizeWidget(sPtr->hScroller, 2, 1);
-
-        if (W_VIEW_REALIZED(sPtr->view)) {
-            WMRealizeWidget(sPtr->hScroller);
-        }
-
-        reorganizeInterior(sPtr);
-
-        WMMapWidget(sPtr->hScroller);
-    } else {
-        if (!sPtr->flags.hasHScroller)
-            return;
-
-        WMUnmapWidget(sPtr->hScroller);
-        WMDestroyWidget(sPtr->hScroller);
-        sPtr->hScroller = NULL;
-        sPtr->flags.hasHScroller = 0;
-
-        reorganizeInterior(sPtr);
-    }
-}
-
-
-void
-WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
-{
-    if (flag) {
-        if (sPtr->flags.hasVScroller)
-            return;
-        sPtr->flags.hasVScroller = 1;
-
-        sPtr->vScroller = WMCreateScroller(sPtr);
-        WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
-        WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
-        /* make it a vert. scroller */
-        WMResizeWidget(sPtr->vScroller, 1, 2);
-
-        if (W_VIEW_REALIZED(sPtr->view)) {
-            WMRealizeWidget(sPtr->vScroller);
-        }
-
-        reorganizeInterior(sPtr);
-
-        WMMapWidget(sPtr->vScroller);
-    } else {
-        if (!sPtr->flags.hasVScroller)
-            return;
-        sPtr->flags.hasVScroller = 0;
-
-        WMUnmapWidget(sPtr->vScroller);
-        WMDestroyWidget(sPtr->vScroller);
-        sPtr->vScroller = NULL;
-
-        reorganizeInterior(sPtr);
-    }
-}
-
-
-void
-WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view)
-{
-    assert(sPtr->contentView == NULL);
-
-    sPtr->contentView = view;
-
-    W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0);
-
-    if (sPtr->flags.hasHScroller) {
-        float prop;
-
-        prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
-        WMSetScrollerParameters(sPtr->hScroller, 0, prop);
-    }
-    if (sPtr->flags.hasVScroller) {
-        float prop;
-
-        prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
-
-        WMSetScrollerParameters(sPtr->vScroller, 0, prop);
-    }
-}
-
-
-void
-WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
-{
-    sPtr->flags.relief = type;
-
-    reorganizeInterior(sPtr);
-
-    if (sPtr->view->flags.mapped)
-        paintScrollView(sPtr);
-
-
-}
-
-
-
-static void
-paintScrollView(ScrollView *sPtr)
-{
-    W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
-                 sPtr->view->size.width, sPtr->view->size.height,
-                 sPtr->flags.relief);
-}
-
-
-static void
-updateScrollerProportion(ScrollView *sPtr)
-{
-    float prop, value;
-    float oldV, oldP;
-
-    if (sPtr->flags.hasHScroller) {
-        oldV = WMGetScrollerValue(sPtr->hScroller);
-        oldP = WMGetScrollerKnobProportion(sPtr->hScroller);
-
-        prop = (float)sPtr->viewport->size.width/(float)sPtr->contentView->size.width;
-
-        if (oldP == 1.0)
-            value = 0;
-        else
-            value = (prop * oldV) / oldP;
-        WMSetScrollerParameters(sPtr->hScroller, value, prop);
-    }
-    if (sPtr->flags.hasVScroller) {
-        oldV = WMGetScrollerValue(sPtr->vScroller);
-        oldP = WMGetScrollerKnobProportion(sPtr->vScroller);
-
-        prop = (float)sPtr->viewport->size.height/(float)sPtr->contentView->size.height;
-
-        if (oldP == 1.0)
-            value = 0;
-        else
-            value = (prop * oldV) / oldP;
-        WMSetScrollerParameters(sPtr->vScroller, value, prop);
-    }
-    applyScrollerValues(sPtr);
-}
-
-
-static void
-handleViewportEvents(XEvent *event, void *data)
-{
-    ScrollView *sPtr = (ScrollView*)data;
-
-    if (sPtr->contentView
-        && event->xconfigure.window == sPtr->contentView->window)
-        updateScrollerProportion(sPtr);
-}
-
-
-static void
-handleEvents(XEvent *event, void *data)
-{
-    ScrollView *sPtr = (ScrollView*)data;
-
-    CHECK_CLASS(data, WC_ScrollView);
-
-    switch (event->type) {
-    case Expose:
-        if (event->xexpose.count!=0)
-            break;
-        if (event->xexpose.serial == 0) /* means it's artificial */
-            W_RedisplayView(sPtr->contentView);
-        else
-            paintScrollView(sPtr);
-        break;
-
-    case DestroyNotify:
-        destroyScrollView(sPtr);
-        break;
-
-    }
-}
-
-
-static void
-destroyScrollView(ScrollView *sPtr)
-{
-    wfree(sPtr);
-}
-
+
+#include "WINGsP.h"
+
+typedef struct W_ScrollView {
+       W_Class widgetClass;
+       WMView *view;
+
+       WMView *contentView;
+       WMView *viewport;
+
+       WMScroller *vScroller;
+       WMScroller *hScroller;
+
+       short lineScroll;
+       short pageScroll;
+
+       struct {
+               WMReliefType relief:3;
+               unsigned int hasVScroller:1;
+               unsigned int hasHScroller:1;
+
+       } flags;
+
+} ScrollView;
+
+static void destroyScrollView(ScrollView * sPtr);
+
+static void paintScrollView(ScrollView * sPtr);
+static void handleEvents(XEvent * event, void *data);
+static void handleViewportEvents(XEvent * event, void *data);
+static void resizeScrollView();
+static void updateScrollerProportion();
+
+W_ViewDelegate _ScrollViewViewDelegate = {
+       NULL,
+       NULL,
+       resizeScrollView,
+       NULL,
+       NULL
+};
+
+WMScrollView *WMCreateScrollView(WMWidget * parent)
+{
+       ScrollView *sPtr;
+
+       sPtr = wmalloc(sizeof(ScrollView));
+       memset(sPtr, 0, sizeof(ScrollView));
+
+       sPtr->widgetClass = WC_ScrollView;
+
+       sPtr->view = W_CreateView(W_VIEW(parent));
+       if (!sPtr->view) {
+               wfree(sPtr);
+               return NULL;
+       }
+       sPtr->viewport = W_CreateView(sPtr->view);
+       if (!sPtr->viewport) {
+               W_DestroyView(sPtr->view);
+               wfree(sPtr);
+               return NULL;
+       }
+       sPtr->view->self = sPtr;
+       sPtr->viewport->self = sPtr;
+
+       sPtr->view->delegate = &_ScrollViewViewDelegate;
+
+       sPtr->viewport->flags.mapWhenRealized = 1;
+
+       WMCreateEventHandler(sPtr->view, StructureNotifyMask | ExposureMask, handleEvents, sPtr);
+       WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask, handleViewportEvents, sPtr);
+
+       sPtr->lineScroll = 4;
+
+       sPtr->pageScroll = 0;
+
+       return sPtr;
+}
+
+static void applyScrollerValues(WMScrollView * sPtr)
+{
+       int x, y;
+
+       if (sPtr->contentView == NULL)
+               return;
+
+       if (sPtr->flags.hasHScroller) {
+               float v = WMGetScrollerValue(sPtr->hScroller);
+               int size;
+
+               size = sPtr->contentView->size.width - sPtr->viewport->size.width;
+
+               x = v * size;
+       } else {
+               x = 0;
+       }
+
+       if (sPtr->flags.hasVScroller) {
+               float v = WMGetScrollerValue(sPtr->vScroller);
+
+               int size;
+
+               size = sPtr->contentView->size.height - sPtr->viewport->size.height;
+
+               y = v * size;
+       } else {
+               y = 0;
+       }
+
+       x = WMAX(0, x);
+       y = WMAX(0, y);
+
+       W_MoveView(sPtr->contentView, -x, -y);
+
+       W_RaiseView(sPtr->viewport);
+}
+
+static void reorganizeInterior(WMScrollView * sPtr)
+{
+       int hx, hy, hw;
+       int vx, vy, vh;
+       int cx, cy, cw, ch;
+
+       cw = hw = sPtr->view->size.width;
+       vh = ch = sPtr->view->size.height;
+
+       if (sPtr->flags.relief == WRSimple) {
+               cw -= 2;
+               ch -= 2;
+               cx = 1;
+               cy = 1;
+       } else if (sPtr->flags.relief != WRFlat) {
+               cw -= 3;
+               ch -= 3;
+               cx = 2;
+               cy = 2;
+       } else {
+               cx = 0;
+               cy = 0;
+       }
+
+       if (sPtr->flags.hasHScroller) {
+               int h = 20;
+
+               ch -= h;
+
+               if (sPtr->flags.relief == WRSimple) {
+                       hx = 0;
+                       hy = sPtr->view->size.height - h;
+               } else if (sPtr->flags.relief != WRFlat) {
+                       hx = 1;
+                       hy = sPtr->view->size.height - h - 1;
+                       hw -= 2;
+               } else {
+                       hx = 0;
+                       hy = sPtr->view->size.height - h;
+               }
+       } else {
+               /* make compiler shutup */
+               hx = 0;
+               hy = 0;
+       }
+
+       if (sPtr->flags.hasVScroller) {
+               int w = 20;
+               cw -= w;
+               cx += w;
+               hx += w - 1;
+               hw -= w - 1;
+
+               if (sPtr->flags.relief == WRSimple) {
+                       vx = 0;
+                       vy = 0;
+               } else if (sPtr->flags.relief != WRFlat) {
+                       vx = 1;
+                       vy = 1;
+                       vh -= 2;
+               } else {
+                       vx = 0;
+                       vy = 0;
+               }
+       } else {
+               /* make compiler shutup */
+               vx = 0;
+               vy = 0;
+       }
+
+       W_ResizeView(sPtr->viewport, cw, ch);
+       W_MoveView(sPtr->viewport, cx, cy);
+
+       if (sPtr->flags.hasHScroller) {
+               WMResizeWidget(sPtr->hScroller, hw, 20);
+               WMMoveWidget(sPtr->hScroller, hx, hy);
+       }
+       if (sPtr->flags.hasVScroller) {
+               WMResizeWidget(sPtr->vScroller, 20, vh);
+               WMMoveWidget(sPtr->vScroller, vx, vy);
+       }
+
+       applyScrollerValues(sPtr);
+}
+
+static void resizeScrollView(W_ViewDelegate * self, WMView * view)
+{
+       reorganizeInterior(view->self);
+       updateScrollerProportion(view->self);
+}
+
+void WMResizeScrollViewContent(WMScrollView * sPtr, unsigned int width, unsigned int height)
+{
+       int w, h, x;
+
+       w = width;
+       h = height;
+
+       x = 0;
+       if (sPtr->flags.relief == WRSimple) {
+               w += 2;
+               h += 2;
+       } else if (sPtr->flags.relief != WRFlat) {
+               w += 4;
+               h += 4;
+               x = 1;
+       }
+
+       if (sPtr->flags.hasVScroller) {
+               WMResizeWidget(sPtr->vScroller, 20, h);
+               width -= W_VIEW(sPtr->vScroller)->size.width;
+       }
+
+       if (sPtr->flags.hasHScroller) {
+               WMResizeWidget(sPtr->hScroller, w, 20);
+               WMMoveWidget(sPtr->hScroller, x, h);
+               height -= W_VIEW(sPtr->hScroller)->size.height;
+       }
+
+       W_ResizeView(sPtr->view, w, h);
+
+       W_ResizeView(sPtr->viewport, width, height);
+}
+
+void WMSetScrollViewLineScroll(WMScrollView * sPtr, int amount)
+{
+       assert(amount > 0);
+
+       sPtr->lineScroll = amount;
+}
+
+void WMSetScrollViewPageScroll(WMScrollView * sPtr, int amount)
+{
+       assert(amount >= 0);
+
+       sPtr->pageScroll = amount;
+}
+
+WMRect WMGetScrollViewVisibleRect(WMScrollView * sPtr)
+{
+       WMRect rect;
+
+       rect.pos.x = -sPtr->contentView->pos.x;
+       rect.pos.y = -sPtr->contentView->pos.y;
+       rect.size = sPtr->viewport->size;
+
+       return rect;
+}
+
+void WMScrollViewScrollPoint(WMScrollView * sPtr, WMPoint point)
+{
+       float xsize, ysize;
+       float xpos, ypos;
+
+       xsize = sPtr->contentView->size.width - sPtr->viewport->size.width;
+       ysize = sPtr->contentView->size.height - sPtr->viewport->size.height;
+
+       xpos = point.x / xsize;
+       ypos = point.y / ysize;
+
+       if (sPtr->hScroller)
+               WMSetScrollerParameters(sPtr->hScroller, xpos, WMGetScrollerKnobProportion(sPtr->hScroller));
+       if (sPtr->vScroller)
+               WMSetScrollerParameters(sPtr->vScroller, ypos, WMGetScrollerKnobProportion(sPtr->vScroller));
+
+       W_MoveView(sPtr->contentView, -point.x, -point.y);
+}
+
+static void doScrolling(WMWidget * self, void *data)
+{
+       ScrollView *sPtr = (ScrollView *) data;
+       float value;
+       int pos;
+       int vpsize;
+       float size;
+
+       if (sPtr->hScroller == (WMScroller *) self) {
+               pos = -sPtr->contentView->pos.x;
+               size = sPtr->contentView->size.width - sPtr->viewport->size.width;
+               vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
+       } else {
+               pos = -sPtr->contentView->pos.y;
+               size = sPtr->contentView->size.height - sPtr->viewport->size.height;
+               vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
+       }
+       if (vpsize <= 0)
+               vpsize = 1;
+
+       switch (WMGetScrollerHitPart(self)) {
+       case WSDecrementLine:
+               if (pos > 0) {
+                       pos -= sPtr->lineScroll;
+                       if (pos < 0)
+                               pos = 0;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+       case WSIncrementLine:
+               if (pos < size) {
+                       pos += sPtr->lineScroll;
+                       if (pos > size)
+                               pos = size;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+
+       case WSKnob:
+               value = WMGetScrollerValue(self);
+               pos = value * size;
+               break;
+
+       case WSDecrementPage:
+               if (pos > 0) {
+                       pos -= vpsize;
+                       if (pos < 0)
+                               pos = 0;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+
+       case WSDecrementWheel:
+               if (pos > 0) {
+                       pos -= vpsize / 3;
+                       if (pos < 0)
+                               pos = 0;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+
+       case WSIncrementPage:
+               if (pos < size) {
+                       pos += vpsize;
+                       if (pos > size)
+                               pos = size;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+
+       case WSIncrementWheel:
+               if (pos < size) {
+                       pos += vpsize / 3;
+                       if (pos > size)
+                               pos = size;
+                       value = (float)pos / size;
+                       WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self));
+               }
+               break;
+
+       case WSNoPart:
+       case WSKnobSlot:
+               break;
+       }
+
+       if (sPtr->hScroller == (WMScroller *) self) {
+               W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
+       } else {
+               W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
+       }
+}
+
+WMScroller *WMGetScrollViewHorizontalScroller(WMScrollView * sPtr)
+{
+       return sPtr->hScroller;
+}
+
+WMScroller *WMGetScrollViewVerticalScroller(WMScrollView * sPtr)
+{
+       return sPtr->vScroller;
+}
+
+void WMSetScrollViewHasHorizontalScroller(WMScrollView * sPtr, Bool flag)
+{
+       if (flag) {
+               if (sPtr->flags.hasHScroller)
+                       return;
+               sPtr->flags.hasHScroller = 1;
+
+               sPtr->hScroller = WMCreateScroller(sPtr);
+               WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
+               /* make it a horiz. scroller */
+               WMResizeWidget(sPtr->hScroller, 2, 1);
+
+               if (W_VIEW_REALIZED(sPtr->view)) {
+                       WMRealizeWidget(sPtr->hScroller);
+               }
+
+               reorganizeInterior(sPtr);
+
+               WMMapWidget(sPtr->hScroller);
+       } else {
+               if (!sPtr->flags.hasHScroller)
+                       return;
+
+               WMUnmapWidget(sPtr->hScroller);
+               WMDestroyWidget(sPtr->hScroller);
+               sPtr->hScroller = NULL;
+               sPtr->flags.hasHScroller = 0;
+
+               reorganizeInterior(sPtr);
+       }
+}
+
+void WMSetScrollViewHasVerticalScroller(WMScrollView * sPtr, Bool flag)
+{
+       if (flag) {
+               if (sPtr->flags.hasVScroller)
+                       return;
+               sPtr->flags.hasVScroller = 1;
+
+               sPtr->vScroller = WMCreateScroller(sPtr);
+               WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
+               WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
+               /* make it a vert. scroller */
+               WMResizeWidget(sPtr->vScroller, 1, 2);
+
+               if (W_VIEW_REALIZED(sPtr->view)) {
+                       WMRealizeWidget(sPtr->vScroller);
+               }
+
+               reorganizeInterior(sPtr);
+
+               WMMapWidget(sPtr->vScroller);
+       } else {
+               if (!sPtr->flags.hasVScroller)
+                       return;
+               sPtr->flags.hasVScroller = 0;
+
+               WMUnmapWidget(sPtr->vScroller);
+               WMDestroyWidget(sPtr->vScroller);
+               sPtr->vScroller = NULL;
+
+               reorganizeInterior(sPtr);
+       }
+}
+
+void WMSetScrollViewContentView(WMScrollView * sPtr, WMView * view)
+{
+       assert(sPtr->contentView == NULL);
+
+       sPtr->contentView = view;
+
+       W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0);
+
+       if (sPtr->flags.hasHScroller) {
+               float prop;
+
+               prop = (float)sPtr->viewport->size.width / sPtr->contentView->size.width;
+               WMSetScrollerParameters(sPtr->hScroller, 0, prop);
+       }
+       if (sPtr->flags.hasVScroller) {
+               float prop;
+
+               prop = (float)sPtr->viewport->size.height / sPtr->contentView->size.height;
+
+               WMSetScrollerParameters(sPtr->vScroller, 0, prop);
+       }
+}
+
+void WMSetScrollViewRelief(WMScrollView * sPtr, WMReliefType type)
+{
+       sPtr->flags.relief = type;
+
+       reorganizeInterior(sPtr);
+
+       if (sPtr->view->flags.mapped)
+               paintScrollView(sPtr);
+
+}
+
+static void paintScrollView(ScrollView * sPtr)
+{
+       W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
+                    sPtr->view->size.width, sPtr->view->size.height, sPtr->flags.relief);
+}
+
+static void updateScrollerProportion(ScrollView * sPtr)
+{
+       float prop, value;
+       float oldV, oldP;
+
+       if (sPtr->flags.hasHScroller) {
+               oldV = WMGetScrollerValue(sPtr->hScroller);
+               oldP = WMGetScrollerKnobProportion(sPtr->hScroller);
+
+               prop = (float)sPtr->viewport->size.width / (float)sPtr->contentView->size.width;
+
+               if (oldP == 1.0)
+                       value = 0;
+               else
+                       value = (prop * oldV) / oldP;
+               WMSetScrollerParameters(sPtr->hScroller, value, prop);
+       }
+       if (sPtr->flags.hasVScroller) {
+               oldV = WMGetScrollerValue(sPtr->vScroller);
+               oldP = WMGetScrollerKnobProportion(sPtr->vScroller);
+
+               prop = (float)sPtr->viewport->size.height / (float)sPtr->contentView->size.height;
+
+               if (oldP == 1.0)
+                       value = 0;
+               else
+                       value = (prop * oldV) / oldP;
+               WMSetScrollerParameters(sPtr->vScroller, value, prop);
+       }
+       applyScrollerValues(sPtr);
+}
+
+static void handleViewportEvents(XEvent * event, void *data)
+{
+       ScrollView *sPtr = (ScrollView *) data;
+
+       if (sPtr->contentView && event->xconfigure.window == sPtr->contentView->window)
+               updateScrollerProportion(sPtr);
+}
+
+static void handleEvents(XEvent * event, void *data)
+{
+       ScrollView *sPtr = (ScrollView *) data;
+
+       CHECK_CLASS(data, WC_ScrollView);
+
+       switch (event->type) {
+       case Expose:
+               if (event->xexpose.count != 0)
+                       break;
+               if (event->xexpose.serial == 0) /* means it's artificial */
+                       W_RedisplayView(sPtr->contentView);
+               else
+                       paintScrollView(sPtr);
+               break;
+
+       case DestroyNotify:
+               destroyScrollView(sPtr);
+               break;
+
+       }
+}
+
+static void destroyScrollView(ScrollView * sPtr)
+{
+       wfree(sPtr);
+}