/*
* xmouse.c - a Python wrapper for XFree86's misc extention's mouse
*            functions.
*
* Matt Wilson <[email protected]>
*
* Copyright 2000 Red Hat, Inc.
*
* This software may be freely redistributed under the terms of the GNU
* public license.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/

#include <X11/Intrinsic.h>
#include <X11/Xmd.h>
#include <X11/extensions/xf86misc.h>
#include <X11/Xos.h>
#include <X11/X.h>
#include <Python.h>

static char *Mouses[] = { "None", "Microsoft", "MouseSystems", "MMSeries",
                         "Logitech", "BusMouse", "Mouseman", "PS/2",
                         "MMHitTab", "GlidePoint", "IntelliMouse",
                         "ThinkingMouse", "IMPS/2", "ThinkingMousePS/2",
                         "MouseManPlusPS/2", "GlidePointPS/2",
                         "NetMousePS/2", "NetScrollPS/2", "SysMouse",
                         "Auto", "Xqueue", "OSMouse" };
static int numMouses = (sizeof (Mouses) / sizeof (*Mouses));

static int (*olderror)();
static char error[512];
static int error_set = FALSE;

static PyObject * mouse_get (PyObject * s, PyObject * args);
static PyObject * mouse_reopen (PyObject * s, PyObject * args);
static PyObject * mouse_set (PyObject * s, PyObject * args);

static PyMethodDef xmouseMethods[] = {
   { "get", mouse_get, 1 },
   { "reopen", mouse_reopen, 1 },
   { "set", mouse_set, 1 },
   { NULL, NULL }
};

static int miscError(Display *disp, XErrorEvent *err)
{
   XGetErrorText (disp, err->error_code, error, 512);
   error_set = TRUE;
   return 0;
}

PyObject *
mouse_get (PyObject * s, PyObject * args)
{
   XF86MiscMouseSettings settings;
   char *name;
   PyObject *ret;

   Display *disp = XOpenDisplay (NULL);
   if (!disp) {
       PyErr_SetString(PyExc_RuntimeError, "Unable to open display");
       return NULL;
   }

   if (!XF86MiscGetMouseSettings(disp, &settings)) {
       PyErr_SetString(PyExc_RuntimeError, "Unable to get mouse settings");
       XCloseDisplay (disp);
       return NULL;
   }

   if (settings.type == MTYPE_XQUEUE)
       name = "Xqueue";
   else if (settings.type == MTYPE_OSMOUSE)
       name = "OSMouse";
   else if (settings.type < 0 || (settings.type >= numMouses))
       name = "Unknown";
   else
       name = Mouses[settings.type+1];

   ret = Py_BuildValue("[ssiiiiiiii]",
                       settings.device == NULL ? "no device": settings.device,
                       name,
                       settings.baudrate,
                       settings.samplerate,
                       settings.resolution,
                       settings.buttons,
                       settings.emulate3buttons,
                       settings.emulate3timeout,
                       settings.chordmiddle,
                       settings.flags);

   if (settings.device)
       free(settings.device);

   XCloseDisplay (disp);

   return ret;
}

PyObject *
mouse_reopen (PyObject * s, PyObject * args)
{
   XF86MiscMouseSettings settings;
   Status rc;

   Display *disp = XOpenDisplay (NULL);
   if (!disp) {
       PyErr_SetString(PyExc_RuntimeError, "Unable to open display");
       return NULL;
   }

   if (!XF86MiscGetMouseSettings(disp, &settings)) {
       PyErr_SetString(PyExc_RuntimeError, "Unable to get mouse settings");
       XCloseDisplay (disp);
       return NULL;
   }
   settings.flags |= MF_REOPEN;

   XSync(disp, False);
   olderror = XSetErrorHandler(miscError);
   rc = XF86MiscSetMouseSettings(disp, &settings);
   XSync(disp, False);
   XSetErrorHandler(olderror);
   XCloseDisplay (disp);
   if (error_set) {
       PyErr_SetString(PyExc_RuntimeError, error);
       error_set = 0;
       return NULL;
   }
   if (!rc) {
       PyErr_SetString(PyExc_RuntimeError, "unknown error reopening mouse device");
       return NULL;
   }

   Py_INCREF(Py_None);
   return Py_None;
}

PyObject *
mouse_set (PyObject * s, PyObject * args)
{
   XF86MiscMouseSettings settings;
   char *proto;
   int i = 0;
   Status rc;

   Display *disp = XOpenDisplay (NULL);
   if (!disp) {
       PyErr_SetString(PyExc_RuntimeError, "Unable to open display");
       return NULL;
   }

   if (!PyArg_ParseTuple(args, "ssiiiiiiii", &settings.device, &proto,
                         &settings.baudrate,
                         &settings.samplerate,
                         &settings.resolution,
                         &settings.buttons,
                         &settings.emulate3buttons,
                         &settings.emulate3timeout,
                         &settings.chordmiddle,
                         &settings.flags))
       return NULL;

   while (i < numMouses && strcasecmp (Mouses[i + 1], proto))
       i++;
   if (i >= numMouses) {
       PyErr_SetString(PyExc_TypeError, "Bad mouse protocol");
       return NULL;
   }

   settings.type = i;

   XSync(disp, False);
   olderror = XSetErrorHandler(miscError);
   rc = XF86MiscSetMouseSettings(disp, &settings);
   XSync(disp, False);
   XSetErrorHandler(olderror);
   XCloseDisplay (disp);
   if (error_set) {
       PyErr_SetString(PyExc_RuntimeError, error);
       error_set = 0;
       return NULL;
   }
   if (!rc) {
       PyErr_SetString(PyExc_RuntimeError, "unknown error setting mouse");
       return NULL;
   }

   Py_INCREF(Py_None);
   return Py_None;
}


#define registerConst(name, val) \
   PyDict_SetItemString(d, name, PyInt_FromLong(val))
void
initxmouse ()
{
   PyObject * d;

   d = Py_InitModule ("xmouse", xmouseMethods);
}