/* MouseSettings.c- mouse options (some are equivalent to xset)
 *
 *  WPrefs - Window Maker Preferences Program
 *
 *  Copyright (c) 1998-2003 Alfredo K. Kojima
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 *  USA.
 */


#include "WPrefs.h"

#include <X11/Xutil.h>

#include <math.h>

/* double-click tester */
#include "double.h"



#define XSET	"xset"



typedef struct _Panel {
    WMBox *box;

    char *sectionName;

    char *description;

    CallbackRec callbacks;

    WMWidget *parent;

    WMFrame *speedF;
    WMLabel *speedL;
    WMSlider *speedS;
    WMLabel *acceL;
    WMTextField *acceT;
    WMLabel *threL;
    WMTextField *threT;

    WMFrame *ddelaF;
    WMButton *ddelaB[5];
    WMTextField *ddelaT;
    WMLabel *ddelaL;
    DoubleTest *tester;

    WMFrame *menuF;
    WMLabel *button1L;
    WMLabel *button2L;
    WMLabel *button3L;
    WMLabel *wheelL;
    WMPopUpButton *button1P;
    WMPopUpButton *button2P;
    WMPopUpButton *button3P;
    WMPopUpButton *wheelP;

    WMButton *disaB;

    WMFrame *grabF;
    WMPopUpButton *grabP;

    /**/
    int maxThreshold;
    float acceleration;
} _Panel;


#define ICON_FILE "mousesettings"

#define SPEED_ICON_FILE "mousespeed"

#define DELAY_ICON "timer%i"
#define DELAY_ICON_S "timer%is"


/* need access to the double click variables */
#include <WINGs/WINGsP.h>



static char *modifierNames[8];


static char *buttonActions[4];

static char *wheelActions[2];


#define DELAY(i)		((i)*75+170)


int ModifierFromKey(Display *dpy, char *key);


static void
setMouseAccel(WMScreen *scr, float accel, int threshold)
{
    int n, d;

    d = 10;
    n = accel*d;

    XChangePointerControl(WMScreenDisplay(scr), True, True, n, d, threshold);
}


static void
speedChange(WMWidget *w, void *data)
{
    _Panel *panel = (_Panel*)data;
    int i;
    char buffer[64];
    int threshold;
    char *tmp;

    if (w == NULL) {
        float accel;

        tmp = WMGetTextFieldText(panel->acceT);
        if (sscanf(tmp, "%f", &accel)!=1 || accel < 0) {
            WMRunAlertPanel(WMWidgetScreen(panel->acceT), GetWindow(panel),
                            _("Error"),
                            _("Invalid mouse acceleration value. Must be a positive real value."),
                            _("OK"), NULL, NULL);
            wfree(tmp);
            return;
        }
        panel->acceleration = accel;
        wfree(tmp);
    } else {
        i = (int)WMGetSliderValue(panel->speedS);

        panel->acceleration = 0.25+(i*0.25);

        sprintf(buffer, "%.2f", 0.25+(i*0.25));
        WMSetTextFieldText(panel->acceT, buffer);
    }

    tmp = WMGetTextFieldText(panel->threT);
    if (sscanf(tmp, "%i", &threshold)!=1 || threshold < 0
        || threshold > panel->maxThreshold) {
        WMRunAlertPanel(WMWidgetScreen(panel->parent), GetWindow(panel), _("Error"),
                        _("Invalid mouse acceleration threshold value. Must be the number of pixels to travel before accelerating."),
                        _("OK"), NULL, NULL);
    } else {
        setMouseAccel(WMWidgetScreen(panel->parent), panel->acceleration,
                      threshold);
    }
    wfree(tmp);
}


static void
returnPressed(void *observerData, WMNotification *notification)
{
    _Panel *panel = (_Panel*)observerData;

    speedChange(NULL, panel);
}


static void
doubleClick(WMWidget *w, void *data)
{
    _Panel *panel = (_Panel*)data;
    int i;
    extern _WINGsConfiguration WINGsConfiguration;
    char buffer[32];

    for (i=0; i<5; i++) {
        if (panel->ddelaB[i]==w)
            break;
    }
    WINGsConfiguration.doubleClickDelay = DELAY(i);

    sprintf(buffer, "%i", DELAY(i));
    WMSetTextFieldText(panel->ddelaT, buffer);
}


static int
getButtonAction(char *str)
{
    if (!str)
        return -2;

    if (strcasecmp(str, "None")==0)
        return 0;
    else if (strcasecmp(str, "OpenApplicationsMenu")==0)
        return 1;
    else if (strcasecmp(str, "OpenWindowListMenu")==0)
        return 2;
    else if (strcasecmp(str, "SelectWindows")==0)
        return 3;
    else
        return -1;

}


static int
getWheelAction(char *str)
{
    if (!str)
        return -2;

    if (strcasecmp(str, "None")==0)
        return 0;
    else if (strcasecmp(str, "SwitchWorkspaces")==0)
        return 1;
    else
        return -1;

}


static void
getMouseParameters(Display *dpy, float *accel, int *thre)
{
    int n, d;

    XGetPointerControl(dpy, &n, &d, thre);

    *accel = (float)n/(float)d;
}



static void
showData(_Panel *panel)
{
    char *str;
    int i;
    int a=-1, b=-1, c=-1, w=-1;
    float accel;
    char buffer[32];
    Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));

    str = GetStringForKey("MouseLeftButtonAction");
    i = getButtonAction(str);
    if (i<0) {
        a = 3;
        if (i==-1) {
            wwarning(_("bad value %s for option %s"), str, "MouseLeftButtonAction");
        }
    } else {
        a = i;
    }
    WMSetPopUpButtonSelectedItem(panel->button1P, a);

    str = GetStringForKey("MouseMiddleButtonAction");
    i = getButtonAction(str);
    if (i<0) {
        b = 2;
        if (i==-1) {
            wwarning(_("bad value %s for option %s"), str, "MouseMiddleButtonAction");
        }
    } else {
        b = i;
    }
    WMSetPopUpButtonSelectedItem(panel->button2P, b);

    str = GetStringForKey("MouseRightButtonAction");
    i = getButtonAction(str);
    if (i<0) {
        c = 1;
        if (i==-1) {
            wwarning(_("bad value %s for option %s"), str, "MouseRightButtonAction");
        }
    } else {
        c = i;
    }
    WMSetPopUpButtonSelectedItem(panel->button3P, c);

    str = GetStringForKey("MouseWheelAction");
    i = getWheelAction(str);
    if (i<0) {
        w = 0;
        if (i==-1) {
            wwarning(_("bad value %s for option %s"), str, "MouseWheelAction");
        }
    } else {
        w = i;
    }
    WMSetPopUpButtonSelectedItem(panel->wheelP, w);

    WMSetButtonSelected(panel->disaB, GetBoolForKey("DisableWSMouseActions"));

    /**/
    getMouseParameters(dpy, &accel, &a);
    panel->maxThreshold = WidthOfScreen(DefaultScreenOfDisplay(dpy));
    if (a > panel->maxThreshold) {
        panel->maxThreshold = a;
    }
    sprintf(buffer, "%i", a);
    WMSetTextFieldText(panel->threT, buffer);

    WMSetSliderValue(panel->speedS, (accel - 0.25)/0.25);

    panel->acceleration = accel;
    sprintf(buffer, "%.2f", accel);
    WMSetTextFieldText(panel->acceT, buffer);

    /**/
    b = GetIntegerForKey("DoubleClickTime");
    /* find best match */
    a = -1;
    for (i=0; i<5; i++) {
        if (DELAY(i) == b)
            a = i;
    }
    if (a >= 0)
        WMPerformButtonClick(panel->ddelaB[a]);
    sprintf(buffer, "%i", b);
    WMSetTextFieldText(panel->ddelaT, buffer);

    /**/
    str = GetStringForKey("ModifierKey");
    if (!str)
        str = "mod1";
    a = ModifierFromKey(dpy, str);

    if (a != -1) {
        str = modifierNames[a];

        a = 0;
        for (i=0; i<WMGetPopUpButtonNumberOfItems(panel->grabP); i++) {
            if (strstr(WMGetPopUpButtonItem(panel->grabP, i), str)) {
                WMSetPopUpButtonSelectedItem(panel->grabP, i);
                a = 1;
                break;
            }
        }
    }

    if (a < 1) {
        sscanf(WMGetPopUpButtonItem(panel->grabP, 0), "%s", buffer);
        WMSetPopUpButtonSelectedItem(panel->grabP, 0);
        wwarning(_("modifier key %s for option ModifierKey was not recognized. Using %s as default"),
                 str, buffer);
    }
}



static void
fillModifierPopUp(WMPopUpButton *pop)
{
    XModifierKeymap *mapping;
    Display *dpy = WMScreenDisplay(WMWidgetScreen(pop));
    int i, j;
    char *str;
    char buffer[64];


    mapping = XGetModifierMapping(dpy);

    if (!mapping || mapping->max_keypermod==0) {
        WMAddPopUpButtonItem(pop, "Mod1");
        WMAddPopUpButtonItem(pop, "Mod2");
        WMAddPopUpButtonItem(pop, "Mod3");
        WMAddPopUpButtonItem(pop, "Mod4");
        WMAddPopUpButtonItem(pop, "Mod5");
        wwarning(_("could not retrieve keyboard modifier mapping"));
        return;
    }


    for (j=0; j<8; j++) {
        int idx;
        char *array[8];
        int a;
        KeySym ksym;
        int k;
        char *ptr;
        char *tmp;

        a = 0;
        memset(array, 0, sizeof(char*)*8);
        for (i=0; i < mapping->max_keypermod; i++) {
            idx = i+j*mapping->max_keypermod;
            if (mapping->modifiermap[idx]!=0) {
                int l;
                for (l=0; l<4; l++) {
                    ksym = XKeycodeToKeysym(dpy, mapping->modifiermap[idx], l);
                    if (ksym!=NoSymbol)
                        break;
                }
                if (ksym!=NoSymbol)
                    str = XKeysymToString(ksym);
                else
                    str = NULL;
                if (str && !strstr(str, "_Lock") && !strstr(str, "Shift")
                    && !strstr(str, "Control")) {
                    array[a++] = wstrdup(str);
                }
            }
        }

        for (k=0; k<a; k++) {
            if (array[k]==NULL)
                continue;
            tmp = wstrdup(array[k]);
            ptr = strstr(tmp, "_L");
            if (ptr)
                *ptr = 0;
            ptr = strstr(tmp, "_R");
            if (ptr)
                *ptr = 0;
            sprintf(buffer, "%s (%s)", modifierNames[j], tmp);
            /*sprintf(buffer, "%s", tmp);*/
            WMAddPopUpButtonItem(pop, buffer);
            for (i=k+1; i<a; i++) {
                if (array[i] == NULL)
                    continue;
                if (strstr(array[i], tmp)) {
                    wfree(array[i]);
                    array[i]=NULL;
                    break;
                }
            }
            wfree(tmp);
        }

        while (--a>0) {
            if (array[a])
                wfree(array[a]);
        }
    }

    if (mapping)
        XFreeModifiermap(mapping);
}



static void
createPanel(Panel *p)
{
    _Panel *panel = (_Panel*)p;
    WMScreen *scr = WMWidgetScreen(panel->parent);
    WMPixmap *icon;
    char *buf1, *buf2;
    int i;
    RColor color;
    char *path;

    color.red = 0xae;
    color.green = 0xaa;
    color.blue = 0xae;

    panel->box = WMCreateBox(panel->parent);
    WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);

    /**************** Mouse Speed ****************/
    panel->speedF = WMCreateFrame(panel->box);
    WMResizeWidget(panel->speedF, 245, 100);
    WMMoveWidget(panel->speedF, 15, 5);
    WMSetFrameTitle(panel->speedF, _("Mouse Speed"));

    panel->speedL = WMCreateLabel(panel->speedF);
    WMResizeWidget(panel->speedL, 40, 46);
    WMMoveWidget(panel->speedL, 15, 14);
    WMSetLabelImagePosition(panel->speedL, WIPImageOnly);
    path = LocateImage(SPEED_ICON_FILE);
    if (path) {
        icon = WMCreateBlendedPixmapFromFile(scr, path, &color);
        if (icon) {
            WMSetLabelImage(panel->speedL, icon);
            WMReleasePixmap(icon);
        } else {
            wwarning(_("could not load icon %s"), path);
        }
        wfree(path);
    }

    panel->speedS = WMCreateSlider(panel->speedF);
    WMResizeWidget(panel->speedS, 160, 15);
    WMMoveWidget(panel->speedS, 70, 35);
    WMSetSliderMinValue(panel->speedS, 0);
    WMSetSliderMaxValue(panel->speedS, 40);
    WMSetSliderContinuous(panel->speedS, False);
    WMSetSliderAction(panel->speedS, speedChange, panel);

    panel->acceL = WMCreateLabel(panel->speedF);
    WMResizeWidget(panel->acceL, 70, 16);
    WMMoveWidget(panel->acceL, 10, 67);
    WMSetLabelTextAlignment(panel->acceL, WARight);
    WMSetLabelText(panel->acceL, _("Acceler.:"));

    panel->acceT = WMCreateTextField(panel->speedF);
    WMResizeWidget(panel->acceT, 40, 20);
    WMMoveWidget(panel->acceT, 80, 65);
    WMAddNotificationObserver(returnPressed, panel,
                              WMTextDidEndEditingNotification, panel->acceT);


    panel->threL = WMCreateLabel(panel->speedF);
    WMResizeWidget(panel->threL, 80, 16);
    WMMoveWidget(panel->threL, 120, 67);
    WMSetLabelTextAlignment(panel->threL, WARight);
    WMSetLabelText(panel->threL, _("Threshold:"));

    panel->threT = WMCreateTextField(panel->speedF);
    WMResizeWidget(panel->threT, 30, 20);
    WMMoveWidget(panel->threT, 200, 65);
    WMAddNotificationObserver(returnPressed, panel,
                              WMTextDidEndEditingNotification, panel->threT);

    WMMapSubwidgets(panel->speedF);

    /***************** Doubleclick Delay ****************/

    panel->ddelaF = WMCreateFrame(panel->box);
    WMResizeWidget(panel->ddelaF, 245, 105);
    WMMoveWidget(panel->ddelaF, 15, 115);
    WMSetFrameTitle(panel->ddelaF, _("Double-Click Delay"));

    buf1 = wmalloc(strlen(DELAY_ICON)+2);
    buf2 = wmalloc(strlen(DELAY_ICON_S)+2);

    for (i = 0; i < 5; i++) {
        panel->ddelaB[i] = WMCreateCustomButton(panel->ddelaF,
                                                WBBStateChangeMask);
        WMResizeWidget(panel->ddelaB[i], 25, 25);
        WMMoveWidget(panel->ddelaB[i], 30+(40*i), 25);
        WMSetButtonBordered(panel->ddelaB[i], False);
        WMSetButtonImagePosition(panel->ddelaB[i], WIPImageOnly);
        WMSetButtonAction(panel->ddelaB[i], doubleClick, panel);
        if (i>0) {
            WMGroupButtons(panel->ddelaB[0], panel->ddelaB[i]);
        }
        sprintf(buf1, DELAY_ICON, i+1);
        sprintf(buf2, DELAY_ICON_S, i+1);
        path = LocateImage(buf1);
        if (path) {
            icon = WMCreatePixmapFromFile(scr, path);
            if (icon) {
                WMSetButtonImage(panel->ddelaB[i], icon);
                WMReleasePixmap(icon);
            } else {
                wwarning(_("could not load icon file %s"), path);
            }
            wfree(path);
        }
        path = LocateImage(buf2);
        if (path) {
            icon = WMCreatePixmapFromFile(scr, path);
            if (icon) {
                WMSetButtonAltImage(panel->ddelaB[i], icon);
                WMReleasePixmap(icon);
            } else {
                wwarning(_("could not load icon file %s"), path);
            }
            wfree(path);
        }
    }
    wfree(buf1);
    wfree(buf2);

    panel->tester = CreateDoubleTest(panel->ddelaF, _("Test"));
    WMResizeWidget(panel->tester, 84, 29);
    WMMoveWidget(panel->tester, 35, 60);

    panel->ddelaT = WMCreateTextField(panel->ddelaF);
    WMResizeWidget(panel->ddelaT, 40, 20);
    WMMoveWidget(panel->ddelaT, 140, 65);

    panel->ddelaL = WMCreateLabel(panel->ddelaF);
    WMResizeWidget(panel->ddelaL, 40, 16);
    WMMoveWidget(panel->ddelaL, 185, 70);
    {
        WMFont *font;
        WMColor *color;

        font = WMSystemFontOfSize(scr, 10);
        color = WMDarkGrayColor(scr);
        WMSetLabelTextColor(panel->ddelaL, color);
        WMSetLabelFont(panel->ddelaL, font);
        WMReleaseFont(font);
        WMReleaseColor(color);
    }
    WMSetLabelText(panel->ddelaL, _("msec"));

    WMMapSubwidgets(panel->ddelaF);

    /* ************** Workspace Action Buttons **************** */
    panel->menuF = WMCreateFrame(panel->box);
    WMResizeWidget(panel->menuF, 240, 160);
    WMMoveWidget(panel->menuF, 270, 5);
    WMSetFrameTitle(panel->menuF, _("Workspace Mouse Actions"));

    panel->disaB = WMCreateSwitchButton(panel->menuF);
    WMResizeWidget(panel->disaB, 205, 18);
    WMMoveWidget(panel->disaB, 10, 18);
    WMSetButtonText(panel->disaB, _("Disable mouse actions"));

    panel->button1L = WMCreateLabel(panel->menuF);
    WMResizeWidget(panel->button1L, 87, 20);
    WMMoveWidget(panel->button1L, 5, 45);
    WMSetLabelTextAlignment(panel->button1L, WARight);
    WMSetLabelText(panel->button1L, _("Left Button"));

    panel->button1P = WMCreatePopUpButton(panel->menuF);
    WMResizeWidget(panel->button1P, 135, 20);
    WMMoveWidget(panel->button1P, 95, 45);

    panel->button2L = WMCreateLabel(panel->menuF);
    WMResizeWidget(panel->button2L, 87, 20);
    WMMoveWidget(panel->button2L, 5, 73);
    WMSetLabelTextAlignment(panel->button2L, WARight);
    WMSetLabelText(panel->button2L, _("Middle Button"));

    panel->button2P = WMCreatePopUpButton(panel->menuF);
    WMResizeWidget(panel->button2P, 135, 20);
    WMMoveWidget(panel->button2P, 95, 73);

    panel->button3L = WMCreateLabel(panel->menuF);
    WMResizeWidget(panel->button3L, 87, 20);
    WMMoveWidget(panel->button3L, 5, 101);
    WMSetLabelTextAlignment(panel->button3L, WARight);
    WMSetLabelText(panel->button3L, _("Right Button"));

    panel->button3P = WMCreatePopUpButton(panel->menuF);
    WMResizeWidget(panel->button3P, 135, 20);
    WMMoveWidget(panel->button3P, 95, 101);

    panel->wheelL = WMCreateLabel(panel->menuF);
    WMResizeWidget(panel->wheelL, 87, 20);
    WMMoveWidget(panel->wheelL, 5, 129);
    WMSetLabelTextAlignment(panel->wheelL, WARight);
    WMSetLabelText(panel->wheelL, _("Mouse Wheel"));

    panel->wheelP = WMCreatePopUpButton(panel->menuF);
    WMResizeWidget(panel->wheelP, 135, 20);
    WMMoveWidget(panel->wheelP, 95, 129);

    for (i = 0; i < sizeof(buttonActions)/sizeof(char*); i++) {
        WMAddPopUpButtonItem(panel->button1P, buttonActions[i]);
        WMAddPopUpButtonItem(panel->button2P, buttonActions[i]);
        WMAddPopUpButtonItem(panel->button3P, buttonActions[i]);
    }

    for (i = 0; i < sizeof(wheelActions)/sizeof(char*); i++) {
        WMAddPopUpButtonItem(panel->wheelP, wheelActions[i]);
    }

    WMMapSubwidgets(panel->menuF);

    /* ************** Grab Modifier **************** */
    panel->grabF = WMCreateFrame(panel->box);
    WMResizeWidget(panel->grabF, 240, 50);
    WMMoveWidget(panel->grabF, 270, 170);
    WMSetFrameTitle(panel->grabF, _("Mouse Grab Modifier"));

    WMSetBalloonTextForView(_("Keyboard modifier to use for actions that\n"
                              "involve dragging windows with the mouse,\n"
                              "clicking inside the window."),
                            WMWidgetView(panel->grabF));

    panel->grabP = WMCreatePopUpButton(panel->grabF);
    WMResizeWidget(panel->grabP, 160, 20);
    WMMoveWidget(panel->grabP, 40, 20);

    fillModifierPopUp(panel->grabP);

    WMMapSubwidgets(panel->grabF);

    WMRealizeWidget(panel->box);
    WMMapSubwidgets(panel->box);


    showData(panel);
}


static void
storeCommandInScript(char *cmd, char *line)
{
    char *path;
    FILE *f;
    char buffer[128];

    path = wstrconcat(wusergnusteppath(), "/Library/WindowMaker/autostart");

    f = fopen(path, "rb");
    if (!f) {
        f = fopen(path, "wb");
        if (!f) {
            wsyserror(_("could not create %s"), path);
            goto end;
        }
        fprintf(f, "#!/bin/sh\n");
        fputs(line, f);
        fputs("\n", f);
    } else {
        int len = strlen(cmd);
        int ok = 0;
        char *tmppath;
        FILE *fo;

        tmppath = wstrconcat(wusergnusteppath(),
                             "/Library/WindowMaker/autostart.tmp");
        fo = fopen(tmppath, "wb");
        if (!fo) {
            wsyserror(_("could not create temporary file %s"), tmppath);
            wfree(tmppath);
            goto end;
        }

        while (!feof(f)) {
            if (!fgets(buffer, 127, f)) {
                break;
            }
            if (buffer[0] == '\n') {
                /* don't write empty lines, else the file will grow
                 * indefinitely (one '\n' added at end of file on each save).
                 */
                continue;
            }
            if (strncmp(buffer, cmd, len)==0) {
                if (!ok) {
                    fputs(line, fo);
                    fputs("\n", fo);
                    ok = 1;
                }
            } else {
                fputs(buffer, fo);
            }
        }
        if (!ok) {
            fputs(line, fo);
            fputs("\n", fo);
        }
        fclose(fo);

        if (rename(tmppath, path)!=0) {
            wsyserror(_("could not rename file %s to %s\n"), tmppath, path);
        }
        wfree(tmppath);
    }
    sprintf(buffer, "chmod u+x %s", path);
    system(buffer);

end:
    wfree(path);
    if (f)
        fclose(f);
}


static void
storeData(_Panel *panel)
{
    char buffer[64];
    int i;
    char *tmp, *p;
    static char *button[4] = {"None", "OpenApplicationsMenu", "OpenWindowListMenu", "SelectWindows"};
    static char *wheel[2] = {"None", "SwitchWorkspaces"};
    WMUserDefaults *udb = WMGetStandardUserDefaults();

    if (!WMGetUDBoolForKey(udb, "NoXSetStuff")) {
        tmp = WMGetTextFieldText(panel->threT);
        if (strlen(tmp)==0) {
            wfree(tmp);
            tmp = wstrdup("4");
        }

        sprintf(buffer, XSET" m %i/%i %s\n", (int)(panel->acceleration*10),
                10, tmp);
        storeCommandInScript(XSET" m", buffer);

        wfree(tmp);
    }

    tmp = WMGetTextFieldText(panel->ddelaT);
    if (sscanf(tmp, "%i", &i) == 1 && i > 0)
        SetIntegerForKey(i, "DoubleClickTime");

    SetBoolForKey(WMGetButtonSelected(panel->disaB), "DisableWSMouseActions");

    i = WMGetPopUpButtonSelectedItem(panel->button1P);
    SetStringForKey(button[i], "MouseLeftButtonAction");

    i = WMGetPopUpButtonSelectedItem(panel->button2P);
    SetStringForKey(button[i], "MouseMiddleButtonAction");

    i = WMGetPopUpButtonSelectedItem(panel->button3P);
    SetStringForKey(button[i], "MouseRightButtonAction");

    i = WMGetPopUpButtonSelectedItem(panel->wheelP);
    SetStringForKey(wheel[i], "MouseWheelAction");

    tmp = WMGetPopUpButtonItem(panel->grabP,
                               WMGetPopUpButtonSelectedItem(panel->grabP));
    tmp = wstrdup(tmp);
    p = strchr(tmp, ' ');
    *p = 0;

    SetStringForKey(tmp, "ModifierKey");

    wfree(tmp);
}


Panel*
InitMouseSettings(WMScreen *scr, WMWidget *parent)
{
    _Panel *panel;

    modifierNames[0] = wstrdup(_("Shift"));
    modifierNames[1] = wstrdup(_("Lock"));
    modifierNames[2] = wstrdup(_("Control"));
    modifierNames[3] = wstrdup(_("Mod1"));
    modifierNames[4] = wstrdup(_("Mod2"));
    modifierNames[5] = wstrdup(_("Mod3"));
    modifierNames[6] = wstrdup(_("Mod4"));
    modifierNames[7] = wstrdup(_("Mod5"));

    buttonActions[0] = wstrdup(_("None"));
    buttonActions[1] = wstrdup(_("Applications Menu"));
    buttonActions[2] = wstrdup(_("Window List Menu"));
    buttonActions[3] = wstrdup(_("Select Windows"));

    wheelActions[0] = wstrdup(_("None"));
    wheelActions[1] = wstrdup(_("Switch Workspaces"));

    panel = wmalloc(sizeof(_Panel));
    memset(panel, 0, sizeof(_Panel));

    panel->sectionName = _("Mouse Preferences");

    panel->description = _("Mouse speed/acceleration, double click delay,\n"
                           "mouse button bindings etc.");

    panel->parent = parent;

    panel->callbacks.createWidgets = createPanel;
    panel->callbacks.updateDomain = storeData;

    AddSection(panel, ICON_FILE);

    return panel;
}



syntax highlighted by Code2HTML, v. 0.9.1