Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wslider.c
dissimilarity index 96%
index 7815bc7..110c858 100644 (file)
-
-
-
-
-#include "WINGsP.h"
-
-
-#undef STRICT_NEXT_BEHAVIOUR
-
-
-typedef struct W_Slider {
-    W_Class widgetClass;
-    WMView *view;
-
-    int minValue;
-    int maxValue;
-
-    int value;
-
-    Pixmap knobPixmap;
-    WMPixmap *backPixmap;
-
-    WMAction *action;
-    void *clientData;
-
-    int knobThickness;
-
-    struct {
-        unsigned int continuous:1;
-
-        unsigned int vertical:1;
-        unsigned int dragging:1;
-    } flags;
-
-} Slider;
-
-
-
-
-static void didResizeSlider();
-
-
-W_ViewDelegate _SliderViewDelegate = {
-    NULL,
-    NULL,
-    didResizeSlider,
-    NULL,
-    NULL
-};
-
-
-
-static void destroySlider(Slider *sPtr);
-static void paintSlider(Slider *sPtr);
-
-static void handleEvents(XEvent *event, void *data);
-static void handleActionEvents(XEvent *event, void *data);
-
-static void makeKnobPixmap(Slider *sPtr);
-
-static void
-realizeObserver(void *self, WMNotification *not)
-{
-    makeKnobPixmap(self);
-}
-
-
-
-WMSlider*
-WMCreateSlider(WMWidget *parent)
-{
-    Slider *sPtr;
-
-    sPtr = wmalloc(sizeof(Slider));
-    memset(sPtr, 0, sizeof(Slider));
-
-    sPtr->widgetClass = WC_Slider;
-
-    sPtr->view = W_CreateView(W_VIEW(parent));
-    if (!sPtr->view) {
-        wfree(sPtr);
-        return NULL;
-    }
-    sPtr->view->self = sPtr;
-
-    sPtr->view->delegate = &_SliderViewDelegate;
-
-    WMCreateEventHandler(sPtr->view, ExposureMask|StructureNotifyMask,
-                         handleEvents, sPtr);
-
-
-    WMCreateEventHandler(sPtr->view, ButtonPressMask|ButtonReleaseMask
-                         |EnterWindowMask|LeaveWindowMask|ButtonMotionMask,
-                         handleActionEvents, sPtr);
-
-    W_ResizeView(sPtr->view, 100, 16);
-    sPtr->flags.vertical = 0;
-    sPtr->minValue = 0;
-    sPtr->maxValue = 100;
-    sPtr->value = 50;
-
-    sPtr->knobThickness = 20;
-
-    sPtr->flags.continuous = 1;
-
-    WMAddNotificationObserver(realizeObserver, sPtr,
-                              WMViewRealizedNotification, sPtr->view);
-
-    return sPtr;
-}
-
-
-void
-WMSetSliderImage(WMSlider *sPtr, WMPixmap *pixmap)
-{
-    if (sPtr->backPixmap)
-        WMReleasePixmap(sPtr->backPixmap);
-
-    sPtr->backPixmap = WMRetainPixmap(pixmap);
-
-    if (sPtr->view->flags.mapped) {
-        paintSlider(sPtr);
-    }
-}
-
-
-void
-WMSetSliderKnobThickness(WMSlider *sPtr, int thickness)
-{
-    assert(thickness > 0);
-
-    sPtr->knobThickness = thickness;
-
-    if (sPtr->knobPixmap) {
-        makeKnobPixmap(sPtr);
-    }
-
-    if (sPtr->view->flags.mapped) {
-        paintSlider(sPtr);
-    }
-}
-
-
-int
-WMGetSliderMinValue(WMSlider *slider)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    return slider->minValue;
-}
-
-
-int
-WMGetSliderMaxValue(WMSlider *slider)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    return slider->maxValue;
-}
-
-
-int
-WMGetSliderValue(WMSlider *slider)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    return slider->value;
-}
-
-
-void
-WMSetSliderMinValue(WMSlider *slider, int value)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    slider->minValue = value;
-    if (slider->value < value) {
-        slider->value = value;
-        if (slider->view->flags.mapped)
-            paintSlider(slider);
-    }
-}
-
-
-void
-WMSetSliderMaxValue(WMSlider *slider, int value)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    slider->maxValue = value;
-    if (slider->value > value) {
-        slider->value = value;
-        if (slider->view->flags.mapped)
-            paintSlider(slider);
-    }
-}
-
-
-void
-WMSetSliderValue(WMSlider *slider, int value)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    if (value < slider->minValue)
-        slider->value = slider->minValue;
-    else if (value > slider->maxValue)
-        slider->value = slider->maxValue;
-    else
-        slider->value = value;
-
-    if (slider->view->flags.mapped)
-        paintSlider(slider);
-}
-
-
-void
-WMSetSliderContinuous(WMSlider *slider, Bool flag)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    slider->flags.continuous = ((flag==0) ? 0 : 1);
-}
-
-
-void
-WMSetSliderAction(WMSlider *slider, WMAction *action, void *data)
-{
-    CHECK_CLASS(slider, WC_Slider);
-
-    slider->action = action;
-    slider->clientData = data;
-}
-
-
-static void
-makeKnobPixmap(Slider *sPtr)
-{
-    Pixmap pix;
-    WMScreen *scr = sPtr->view->screen;
-    int w, h;
-
-    if (sPtr->flags.vertical) {
-        w = sPtr->view->size.width-2;
-        h = sPtr->knobThickness;
-    } else {
-        w = sPtr->knobThickness;
-        h = sPtr->view->size.height-2;
-    }
-
-    pix = XCreatePixmap(scr->display, sPtr->view->window, w, h, scr->depth);
-    XFillRectangle(scr->display, pix, WMColorGC(scr->gray), 0, 0, w, h);
-
-    if (sPtr->knobThickness < 10) {
-        W_DrawRelief(scr, pix, 0, 0, w, h, WRRaised);
-    } else if (sPtr->flags.vertical) {
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h-3);
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h-3);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w-2, 1, w-2, h/2-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w-2, h/2, w-2, h-2);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w-2, 0);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h/2-2, w-3, h/2-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, h/2-1, w-3, h/2-1);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->black), w-1, 0, w-1, h-2);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h-3, w-2, h-3);
-        XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h-2, w-1, h-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h-1, w-1,h-1);
-    } else {
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w-3, 0);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h-2);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h-3);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w/2-2, 1, w/2-2, h-3);
-        XDrawLine(scr->display, pix, WMColorGC(scr->white), w/2-1, 0, w/2-1, h-3);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w-3, 0, w-3, h-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->black), w-2, 0, w-2, h-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w-1, 0, w-1, h-1);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->black), 1, h-1, w/2+1, h-1);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h-2, w/2-2, h-2);
-        XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w/2, h-2, w-3,h-2);
-
-        XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h-1, w-2, h-1);
-    }
-
-    if (sPtr->knobPixmap)
-        XFreePixmap(scr->display, sPtr->knobPixmap);
-    sPtr->knobPixmap = pix;
-}
-
-
-static void
-didResizeSlider(W_ViewDelegate *self, WMView *view)
-{
-    Slider *sPtr = (Slider*)view->self;
-    int width = sPtr->view->size.width;
-    int height = sPtr->view->size.height;
-
-    assert(width > 0);
-    assert(height > 0);
-
-    if (width > height) {
-        if (sPtr->flags.vertical) {
-            sPtr->flags.vertical = 0;
-            if (sPtr->view->flags.realized)
-                makeKnobPixmap(sPtr);
-        }
-    } else {
-        if (!sPtr->flags.vertical) {
-            sPtr->flags.vertical = 1;
-            if (sPtr->view->flags.realized)
-                makeKnobPixmap(sPtr);
-        }
-    }
-}
-
-
-
-static void
-paintSlider(Slider *sPtr)
-{
-    W_Screen *scr = sPtr->view->screen;
-    GC bgc;
-    GC wgc;
-    GC lgc;
-    WMSize size = sPtr->view->size;
-    int pos;
-    Pixmap buffer;
-
-#define MINV sPtr->minValue
-#define MAXV sPtr->maxValue
-#define POSV sPtr->value
-
-    bgc = WMColorGC(scr->black);
-    wgc = WMColorGC(scr->white);
-    lgc = WMColorGC(scr->gray);
-
-    buffer = XCreatePixmap(scr->display, sPtr->view->window,
-                           size.width, size.height, scr->depth);
-
-    if (sPtr->backPixmap) {
-        WMSize size = WMGetPixmapSize(sPtr->backPixmap);
-
-        XCopyArea(scr->display, WMGetPixmapXID(sPtr->backPixmap),
-                  buffer, scr->copyGC, 0, 0, size.width, size.height, 1, 1);
-    } else {
-        XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width,
-                       size.height);
-        XFillRectangle(scr->display, buffer, scr->stippleGC, 0, 0, size.width,
-                       size.height);
-    }
-
-    if (sPtr->flags.vertical) {
-        pos = (size.height-2-sPtr->knobThickness)*(POSV-MINV)/(MAXV-MINV)+1;
-        /* draw knob */
-        XCopyArea(scr->display, sPtr->knobPixmap, buffer,
-                  scr->copyGC, 0, 0, size.width-2, sPtr->knobThickness,
-                  1, pos);
-    } else {
-        pos = (size.width-2-sPtr->knobThickness)*(POSV-MINV)/(MAXV-MINV)+1;
-        /* draw knob */
-        XCopyArea(scr->display, sPtr->knobPixmap, buffer,
-                  scr->copyGC, 0, 0, sPtr->knobThickness, size.height, pos, 1);
-    }
-
-    XDrawLine(scr->display, buffer, bgc, 0, 0, 0, size.height-1);
-    XDrawLine(scr->display, buffer, bgc, 0, 0, size.width, 0);
-
-    XDrawLine(scr->display, buffer, wgc, size.width-1, 0,
-              size.width-1, size.height-1);
-    XDrawLine(scr->display, buffer, wgc, 0, size.height-1,
-              size.width-1, size.height-1);
-
-    XCopyArea(scr->display, buffer, sPtr->view->window, scr->copyGC, 0, 0,
-              size.width, size.height, 0, 0);
-    XFreePixmap(scr->display, buffer);
-}
-
-
-
-static void
-handleEvents(XEvent *event, void *data)
-{
-    Slider *sPtr = (Slider*)data;
-
-    CHECK_CLASS(data, WC_Slider);
-
-
-    switch (event->type) {
-    case Expose:
-        if (event->xexpose.count!=0)
-            break;
-        paintSlider(sPtr);
-        break;
-
-    case DestroyNotify:
-        destroySlider(sPtr);
-        break;
-
-    }
-}
-
-
-#define DECR_PART      1
-#define KNOB_PART      2
-#define INCR_PART      3
-
-static int
-getSliderPart(Slider *sPtr, int x, int y)
-{
-    int p;
-    int pos;
-    WMSize size = sPtr->view->size;
-
-
-    if (sPtr->flags.vertical) {
-        p = y;
-        pos = (size.height-2-sPtr->knobThickness)*(POSV-MINV)/(MAXV-MINV);
-        if (p < pos)
-            return INCR_PART;
-        if (p > pos + sPtr->knobThickness)
-            return DECR_PART;
-        return KNOB_PART;
-    } else {
-        p = x;
-        pos = (size.width-2-sPtr->knobThickness)*(POSV-MINV)/(MAXV-MINV);
-        if (p < pos)
-            return DECR_PART;
-        if (p > pos + sPtr->knobThickness)
-            return INCR_PART;
-        return KNOB_PART;
-    }
-}
-
-
-static int
-valueForMousePoint(Slider *sPtr, int x, int y)
-{
-    WMSize size = sPtr->view->size;
-    int f;
-
-    if (sPtr->flags.vertical) {
-        f = (y-sPtr->knobThickness/2)*(MAXV-MINV)
-            / ((int)size.height-2-sPtr->knobThickness);
-    } else {
-        f = (x-sPtr->knobThickness/2)*(MAXV-MINV)
-            / ((int)size.width-2-sPtr->knobThickness);
-    }
-
-    f += sPtr->minValue;
-    if (f < sPtr->minValue)
-        f = sPtr->minValue;
-    else if (f > sPtr->maxValue)
-        f = sPtr->maxValue;
-
-    return f;
-}
-
-
-static void
-handleActionEvents(XEvent *event, void *data)
-{
-    WMSlider *sPtr = (Slider*)data;
-
-    CHECK_CLASS(data, WC_Slider);
-
-
-    switch (event->type) {
-    case ButtonPress:
-        if (event->xbutton.button==WINGsConfiguration.mouseWheelUp
-            &&!sPtr->flags.dragging) {
-            /* Wheel up */
-            if (sPtr->value+1<=sPtr->maxValue) {
-                WMSetSliderValue(sPtr, sPtr->value+1);
-                if (sPtr->flags.continuous && sPtr->action) {
-                    (*sPtr->action)(sPtr, sPtr->clientData);
-                }
-            }
-        } else if (event->xbutton.button==WINGsConfiguration.mouseWheelDown
-                   &&!sPtr->flags.dragging) {
-            /* Wheel down */
-            if (sPtr->value-1>=sPtr->minValue)
-            {
-                WMSetSliderValue(sPtr, sPtr->value-1);
-                if (sPtr->flags.continuous && sPtr->action) {
-                    (*sPtr->action)(sPtr, sPtr->clientData);
-                }
-            }
-        }
-        else if (getSliderPart(sPtr, event->xbutton.x, event->xbutton.y)
-                 ==KNOB_PART)
-            sPtr->flags.dragging = 1;
-        else {
-#ifdef STRICT_NEXT_BEHAVIOUR
-            sPtr->flags.dragging = 1;
-
-            sPtr->value = valueForMousePoint(sPtr, event->xmotion.x,
-                                             event->xmotion.y);
-            paintSlider(sPtr);
-#else
-            int tmp;
-
-            if (event->xbutton.button == Button2) {
-                sPtr->flags.dragging = 1;
-
-                sPtr->value = valueForMousePoint(sPtr, event->xmotion.x,
-                                                 event->xmotion.y);
-                paintSlider(sPtr);
-            } else {
-                tmp = valueForMousePoint(sPtr, event->xmotion.x,
-                                         event->xmotion.y);
-                if (tmp < sPtr->value)
-                    tmp = sPtr->value-1;
-                else
-                    tmp = sPtr->value+1;
-                WMSetSliderValue(sPtr, tmp);
-            }
-#endif
-
-            if (sPtr->flags.continuous && sPtr->action) {
-                (*sPtr->action)(sPtr, sPtr->clientData);
-            }
-        }
-        break;
-
-    case ButtonRelease:
-        if (!sPtr->flags.continuous && sPtr->action) {
-            (*sPtr->action)(sPtr, sPtr->clientData);
-        }
-        sPtr->flags.dragging = 0;
-        break;
-
-    case MotionNotify:
-        if (sPtr->flags.dragging) {
-            sPtr->value = valueForMousePoint(sPtr, event->xmotion.x,
-                                             event->xmotion.y);
-            paintSlider(sPtr);
-
-            if (sPtr->flags.continuous && sPtr->action) {
-                (*sPtr->action)(sPtr, sPtr->clientData);
-            }
-        }
-        break;
-    }
-}
-
-
-
-static void
-destroySlider(Slider *sPtr)
-{
-    if (sPtr->knobPixmap)
-        XFreePixmap(sPtr->view->screen->display, sPtr->knobPixmap);
-
-    if (sPtr->backPixmap)
-        WMReleasePixmap(sPtr->backPixmap);
-
-    WMRemoveNotificationObserver(sPtr);
-
-    wfree(sPtr);
-}
-
+
+#include "WINGsP.h"
+
+#undef STRICT_NEXT_BEHAVIOUR
+
+typedef struct W_Slider {
+       W_Class widgetClass;
+       WMView *view;
+
+       int minValue;
+       int maxValue;
+
+       int value;
+
+       Pixmap knobPixmap;
+       WMPixmap *backPixmap;
+
+       WMAction *action;
+       void *clientData;
+
+       int knobThickness;
+
+       struct {
+               unsigned int continuous:1;
+
+               unsigned int vertical:1;
+               unsigned int dragging:1;
+       } flags;
+
+} Slider;
+
+static void didResizeSlider();
+
+W_ViewDelegate _SliderViewDelegate = {
+       NULL,
+       NULL,
+       didResizeSlider,
+       NULL,
+       NULL
+};
+
+static void destroySlider(Slider * sPtr);
+static void paintSlider(Slider * sPtr);
+
+static void handleEvents(XEvent * event, void *data);
+static void handleActionEvents(XEvent * event, void *data);
+
+static void makeKnobPixmap(Slider * sPtr);
+
+static void realizeObserver(void *self, WMNotification * not)
+{
+       makeKnobPixmap(self);
+}
+
+WMSlider *WMCreateSlider(WMWidget * parent)
+{
+       Slider *sPtr;
+
+       sPtr = wmalloc(sizeof(Slider));
+       memset(sPtr, 0, sizeof(Slider));
+
+       sPtr->widgetClass = WC_Slider;
+
+       sPtr->view = W_CreateView(W_VIEW(parent));
+       if (!sPtr->view) {
+               wfree(sPtr);
+               return NULL;
+       }
+       sPtr->view->self = sPtr;
+
+       sPtr->view->delegate = &_SliderViewDelegate;
+
+       WMCreateEventHandler(sPtr->view, ExposureMask | StructureNotifyMask, handleEvents, sPtr);
+
+       WMCreateEventHandler(sPtr->view, ButtonPressMask | ButtonReleaseMask
+                            | EnterWindowMask | LeaveWindowMask | ButtonMotionMask, handleActionEvents, sPtr);
+
+       W_ResizeView(sPtr->view, 100, 16);
+       sPtr->flags.vertical = 0;
+       sPtr->minValue = 0;
+       sPtr->maxValue = 100;
+       sPtr->value = 50;
+
+       sPtr->knobThickness = 20;
+
+       sPtr->flags.continuous = 1;
+
+       WMAddNotificationObserver(realizeObserver, sPtr, WMViewRealizedNotification, sPtr->view);
+
+       return sPtr;
+}
+
+void WMSetSliderImage(WMSlider * sPtr, WMPixmap * pixmap)
+{
+       if (sPtr->backPixmap)
+               WMReleasePixmap(sPtr->backPixmap);
+
+       sPtr->backPixmap = WMRetainPixmap(pixmap);
+
+       if (sPtr->view->flags.mapped) {
+               paintSlider(sPtr);
+       }
+}
+
+void WMSetSliderKnobThickness(WMSlider * sPtr, int thickness)
+{
+       assert(thickness > 0);
+
+       sPtr->knobThickness = thickness;
+
+       if (sPtr->knobPixmap) {
+               makeKnobPixmap(sPtr);
+       }
+
+       if (sPtr->view->flags.mapped) {
+               paintSlider(sPtr);
+       }
+}
+
+int WMGetSliderMinValue(WMSlider * slider)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       return slider->minValue;
+}
+
+int WMGetSliderMaxValue(WMSlider * slider)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       return slider->maxValue;
+}
+
+int WMGetSliderValue(WMSlider * slider)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       return slider->value;
+}
+
+void WMSetSliderMinValue(WMSlider * slider, int value)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       slider->minValue = value;
+       if (slider->value < value) {
+               slider->value = value;
+               if (slider->view->flags.mapped)
+                       paintSlider(slider);
+       }
+}
+
+void WMSetSliderMaxValue(WMSlider * slider, int value)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       slider->maxValue = value;
+       if (slider->value > value) {
+               slider->value = value;
+               if (slider->view->flags.mapped)
+                       paintSlider(slider);
+       }
+}
+
+void WMSetSliderValue(WMSlider * slider, int value)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       if (value < slider->minValue)
+               slider->value = slider->minValue;
+       else if (value > slider->maxValue)
+               slider->value = slider->maxValue;
+       else
+               slider->value = value;
+
+       if (slider->view->flags.mapped)
+               paintSlider(slider);
+}
+
+void WMSetSliderContinuous(WMSlider * slider, Bool flag)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       slider->flags.continuous = ((flag == 0) ? 0 : 1);
+}
+
+void WMSetSliderAction(WMSlider * slider, WMAction * action, void *data)
+{
+       CHECK_CLASS(slider, WC_Slider);
+
+       slider->action = action;
+       slider->clientData = data;
+}
+
+static void makeKnobPixmap(Slider * sPtr)
+{
+       Pixmap pix;
+       WMScreen *scr = sPtr->view->screen;
+       int w, h;
+
+       if (sPtr->flags.vertical) {
+               w = sPtr->view->size.width - 2;
+               h = sPtr->knobThickness;
+       } else {
+               w = sPtr->knobThickness;
+               h = sPtr->view->size.height - 2;
+       }
+
+       pix = XCreatePixmap(scr->display, sPtr->view->window, w, h, scr->depth);
+       XFillRectangle(scr->display, pix, WMColorGC(scr->gray), 0, 0, w, h);
+
+       if (sPtr->knobThickness < 10) {
+               W_DrawRelief(scr, pix, 0, 0, w, h, WRRaised);
+       } else if (sPtr->flags.vertical) {
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h - 3);
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h - 3);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 2, 1, w - 2, h / 2 - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 2, h / 2, w - 2, h - 2);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w - 2, 0);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h / 2 - 2, w - 3, h / 2 - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, h / 2 - 1, w - 3, h / 2 - 1);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->black), w - 1, 0, w - 1, h - 2);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h - 3, w - 2, h - 3);
+               XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h - 2, w - 1, h - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 0, h - 1, w - 1, h - 1);
+       } else {
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, w - 3, 0);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 0, 0, 0, h - 2);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), 1, 0, 1, h - 3);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w / 2 - 2, 1, w / 2 - 2, h - 3);
+               XDrawLine(scr->display, pix, WMColorGC(scr->white), w / 2 - 1, 0, w / 2 - 1, h - 3);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 3, 0, w - 3, h - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->black), w - 2, 0, w - 2, h - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w - 1, 0, w - 1, h - 1);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->black), 1, h - 1, w / 2 + 1, h - 1);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), 1, h - 2, w / 2 - 2, h - 2);
+               XDrawLine(scr->display, pix, WMColorGC(scr->darkGray), w / 2, h - 2, w - 3, h - 2);
+
+               XDrawLine(scr->display, pix, WMColorGC(scr->black), 0, h - 1, w - 2, h - 1);
+       }
+
+       if (sPtr->knobPixmap)
+               XFreePixmap(scr->display, sPtr->knobPixmap);
+       sPtr->knobPixmap = pix;
+}
+
+static void didResizeSlider(W_ViewDelegate * self, WMView * view)
+{
+       Slider *sPtr = (Slider *) view->self;
+       int width = sPtr->view->size.width;
+       int height = sPtr->view->size.height;
+
+       assert(width > 0);
+       assert(height > 0);
+
+       if (width > height) {
+               if (sPtr->flags.vertical) {
+                       sPtr->flags.vertical = 0;
+                       if (sPtr->view->flags.realized)
+                               makeKnobPixmap(sPtr);
+               }
+       } else {
+               if (!sPtr->flags.vertical) {
+                       sPtr->flags.vertical = 1;
+                       if (sPtr->view->flags.realized)
+                               makeKnobPixmap(sPtr);
+               }
+       }
+}
+
+static void paintSlider(Slider * sPtr)
+{
+       W_Screen *scr = sPtr->view->screen;
+       GC bgc;
+       GC wgc;
+       GC lgc;
+       WMSize size = sPtr->view->size;
+       int pos;
+       Pixmap buffer;
+
+#define MINV sPtr->minValue
+#define MAXV sPtr->maxValue
+#define POSV sPtr->value
+
+       bgc = WMColorGC(scr->black);
+       wgc = WMColorGC(scr->white);
+       lgc = WMColorGC(scr->gray);
+
+       buffer = XCreatePixmap(scr->display, sPtr->view->window, size.width, size.height, scr->depth);
+
+       if (sPtr->backPixmap) {
+               WMSize size = WMGetPixmapSize(sPtr->backPixmap);
+
+               XCopyArea(scr->display, WMGetPixmapXID(sPtr->backPixmap),
+                         buffer, scr->copyGC, 0, 0, size.width, size.height, 1, 1);
+       } else {
+               XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
+               XFillRectangle(scr->display, buffer, scr->stippleGC, 0, 0, size.width, size.height);
+       }
+
+       if (sPtr->flags.vertical) {
+               pos = (size.height - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV) + 1;
+               /* draw knob */
+               XCopyArea(scr->display, sPtr->knobPixmap, buffer,
+                         scr->copyGC, 0, 0, size.width - 2, sPtr->knobThickness, 1, pos);
+       } else {
+               pos = (size.width - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV) + 1;
+               /* draw knob */
+               XCopyArea(scr->display, sPtr->knobPixmap, buffer,
+                         scr->copyGC, 0, 0, sPtr->knobThickness, size.height, pos, 1);
+       }
+
+       XDrawLine(scr->display, buffer, bgc, 0, 0, 0, size.height - 1);
+       XDrawLine(scr->display, buffer, bgc, 0, 0, size.width, 0);
+
+       XDrawLine(scr->display, buffer, wgc, size.width - 1, 0, size.width - 1, size.height - 1);
+       XDrawLine(scr->display, buffer, wgc, 0, size.height - 1, size.width - 1, size.height - 1);
+
+       XCopyArea(scr->display, buffer, sPtr->view->window, scr->copyGC, 0, 0, size.width, size.height, 0, 0);
+       XFreePixmap(scr->display, buffer);
+}
+
+static void handleEvents(XEvent * event, void *data)
+{
+       Slider *sPtr = (Slider *) data;
+
+       CHECK_CLASS(data, WC_Slider);
+
+       switch (event->type) {
+       case Expose:
+               if (event->xexpose.count != 0)
+                       break;
+               paintSlider(sPtr);
+               break;
+
+       case DestroyNotify:
+               destroySlider(sPtr);
+               break;
+
+       }
+}
+
+#define DECR_PART      1
+#define KNOB_PART      2
+#define INCR_PART      3
+
+static int getSliderPart(Slider * sPtr, int x, int y)
+{
+       int p;
+       int pos;
+       WMSize size = sPtr->view->size;
+
+       if (sPtr->flags.vertical) {
+               p = y;
+               pos = (size.height - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV);
+               if (p < pos)
+                       return INCR_PART;
+               if (p > pos + sPtr->knobThickness)
+                       return DECR_PART;
+               return KNOB_PART;
+       } else {
+               p = x;
+               pos = (size.width - 2 - sPtr->knobThickness) * (POSV - MINV) / (MAXV - MINV);
+               if (p < pos)
+                       return DECR_PART;
+               if (p > pos + sPtr->knobThickness)
+                       return INCR_PART;
+               return KNOB_PART;
+       }
+}
+
+static int valueForMousePoint(Slider * sPtr, int x, int y)
+{
+       WMSize size = sPtr->view->size;
+       int f;
+
+       if (sPtr->flags.vertical) {
+               f = (y - sPtr->knobThickness / 2) * (MAXV - MINV)
+                   / ((int)size.height - 2 - sPtr->knobThickness);
+       } else {
+               f = (x - sPtr->knobThickness / 2) * (MAXV - MINV)
+                   / ((int)size.width - 2 - sPtr->knobThickness);
+       }
+
+       f += sPtr->minValue;
+       if (f < sPtr->minValue)
+               f = sPtr->minValue;
+       else if (f > sPtr->maxValue)
+               f = sPtr->maxValue;
+
+       return f;
+}
+
+static void handleActionEvents(XEvent * event, void *data)
+{
+       WMSlider *sPtr = (Slider *) data;
+
+       CHECK_CLASS(data, WC_Slider);
+
+       switch (event->type) {
+       case ButtonPress:
+               if (event->xbutton.button == WINGsConfiguration.mouseWheelUp && !sPtr->flags.dragging) {
+                       /* Wheel up */
+                       if (sPtr->value + 1 <= sPtr->maxValue) {
+                               WMSetSliderValue(sPtr, sPtr->value + 1);
+                               if (sPtr->flags.continuous && sPtr->action) {
+                                       (*sPtr->action) (sPtr, sPtr->clientData);
+                               }
+                       }
+               } else if (event->xbutton.button == WINGsConfiguration.mouseWheelDown && !sPtr->flags.dragging) {
+                       /* Wheel down */
+                       if (sPtr->value - 1 >= sPtr->minValue) {
+                               WMSetSliderValue(sPtr, sPtr->value - 1);
+                               if (sPtr->flags.continuous && sPtr->action) {
+                                       (*sPtr->action) (sPtr, sPtr->clientData);
+                               }
+                       }
+               } else if (getSliderPart(sPtr, event->xbutton.x, event->xbutton.y)
+                          == KNOB_PART)
+                       sPtr->flags.dragging = 1;
+               else {
+#ifdef STRICT_NEXT_BEHAVIOUR
+                       sPtr->flags.dragging = 1;
+
+                       sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
+                       paintSlider(sPtr);
+#else
+                       int tmp;
+
+                       if (event->xbutton.button == Button2) {
+                               sPtr->flags.dragging = 1;
+
+                               sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
+                               paintSlider(sPtr);
+                       } else {
+                               tmp = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
+                               if (tmp < sPtr->value)
+                                       tmp = sPtr->value - 1;
+                               else
+                                       tmp = sPtr->value + 1;
+                               WMSetSliderValue(sPtr, tmp);
+                       }
+#endif
+
+                       if (sPtr->flags.continuous && sPtr->action) {
+                               (*sPtr->action) (sPtr, sPtr->clientData);
+                       }
+               }
+               break;
+
+       case ButtonRelease:
+               if (!sPtr->flags.continuous && sPtr->action) {
+                       (*sPtr->action) (sPtr, sPtr->clientData);
+               }
+               sPtr->flags.dragging = 0;
+               break;
+
+       case MotionNotify:
+               if (sPtr->flags.dragging) {
+                       sPtr->value = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
+                       paintSlider(sPtr);
+
+                       if (sPtr->flags.continuous && sPtr->action) {
+                               (*sPtr->action) (sPtr, sPtr->clientData);
+                       }
+               }
+               break;
+       }
+}
+
+static void destroySlider(Slider * sPtr)
+{
+       if (sPtr->knobPixmap)
+               XFreePixmap(sPtr->view->screen->display, sPtr->knobPixmap);
+
+       if (sPtr->backPixmap)
+               WMReleasePixmap(sPtr->backPixmap);
+
+       WMRemoveNotificationObserver(sPtr);
+
+       wfree(sPtr);
+}