--- /dev/null
+diff -Naur linuxwacom-0.7.0/src/wcmCommon.c linuxwacom-0.7.0-rotate/src/wcmCommon.c
+--- linuxwacom-0.7.0/src/wcmCommon.c 2005-09-19 19:43:14.000000000 -0400
++++ linuxwacom-0.7.0-rotate/src/wcmCommon.c 2005-11-22 16:44:41.000000000 -0500
+@@ -440,6 +440,11 @@
+ y = x;
+ x = common->wcmMaxX - tmp_coord;
+ }
++ else if (common->wcmRotate == ROTATE_HALF)
++ {
++ x = common->wcmMaxX - x;
++ y = common->wcmMaxY - y;
++ }
+
+ is_absolute = (priv->flags & ABSOLUTE_FLAG);
+ is_core_pointer = xf86IsCorePointer(local->dev);
+diff -Naur linuxwacom-0.7.0/src/xf86Wacom.c linuxwacom-0.7.0-rotate/src/xf86Wacom.c
+--- linuxwacom-0.7.0/src/xf86Wacom.c 2005-09-19 19:43:14.000000000 -0400
++++ linuxwacom-0.7.0-rotate/src/xf86Wacom.c 2005-12-07 22:57:46.000000000 -0500
+@@ -199,7 +199,7 @@
+ LocalDevicePtr local = (LocalDevicePtr)pWcm->public.devicePrivate;
+ WacomDevicePtr priv = (WacomDevicePtr)PRIVATE(pWcm);
+ WacomCommonPtr common = priv->common;
+- int totalWidth = 0, maxHeight = 0, tabletSize = 0;
++ int totalWidth = 0, maxHeight = 0;
+ double screenRatio, tabletRatio;
+ char m1[32], m2[32];
+
+@@ -335,23 +335,13 @@
+ } /* end bounding rect */
+
+ /* x and y axes */
+- if (priv->twinview == TV_LEFT_RIGHT)
+- tabletSize = 2*(priv->bottomX - priv->topX - 2*priv->tvoffsetX);
+- else
+- tabletSize = priv->bottomX - priv->topX;
+-
+- InitValuatorAxisStruct(pWcm, 0, 0, tabletSize, /* max val */
+- common->wcmResolX, /* tablet resolution */
+- 0, common->wcmResolX); /* max_res */
+-
+- if (priv->twinview == TV_ABOVE_BELOW)
+- tabletSize = 2*(priv->bottomY - priv->topY - 2*priv->tvoffsetY);
+- else
+- tabletSize = priv->bottomY - priv->topY;
+-
+- InitValuatorAxisStruct(pWcm, 1, 0, tabletSize, /* max val */
+- common->wcmResolY, /* tablet resolution */
+- 0, common->wcmResolY); /* max_res */
++ InitValuatorAxisStruct(pWcm, 0, priv->topX, priv->bottomX, /* max val */
++ common->wcmResolX, /* tablet resolution */
++ 0, common->wcmResolX); /* max_res */
++
++ InitValuatorAxisStruct(pWcm, 1, priv->topY, priv->bottomY, /* max val */
++ common->wcmResolY, /* tablet resolution */
++ 0, common->wcmResolY); /* max_res */
+
+ /* pressure */
+ InitValuatorAxisStruct(pWcm, 2, 0,
+@@ -657,25 +647,40 @@
+ static int xf86WcmSetParam(LocalDevicePtr local, int param, int value)
+ {
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
++ WacomDevicePtr tmppriv;
+ char st[32];
++ int oldRotation, dev;
++ int tmpTopX, tmpTopY, tmpBottomX, tmpBottomY, oldMaxX, oldMaxY;
+
+ switch (param)
+ {
+ case XWACOM_PARAM_TOPX:
+ xf86ReplaceIntOption(local->options, "TopX", value);
+ priv->topX = xf86SetIntOption(local->options, "TopX", 0);
++ InitValuatorAxisStruct(local->dev, 0, priv->topX, priv->bottomX,
++ priv->common->wcmResolX, /* tablet resolution */
++ 0, priv->common->wcmResolX); /* max_res */
+ break;
+ case XWACOM_PARAM_TOPY:
+ xf86ReplaceIntOption(local->options, "TopY", value);
+ priv->topY = xf86SetIntOption(local->options, "TopY", 0);
++ InitValuatorAxisStruct(local->dev, 1, priv->topY, priv->bottomY, /* max val */
++ priv->common->wcmResolY, /* tablet resolution */
++ 0, priv->common->wcmResolY); /* max_res */
+ break;
+ case XWACOM_PARAM_BOTTOMX:
+ xf86ReplaceIntOption(local->options, "BottomX", value);
+ priv->bottomX = xf86SetIntOption(local->options, "BottomX", 0);
++ InitValuatorAxisStruct(local->dev, 0, priv->topX, priv->bottomX,
++ priv->common->wcmResolX, /* tablet resolution */
++ 0, priv->common->wcmResolX); /* max_res */
+ break;
+ case XWACOM_PARAM_BOTTOMY:
+ xf86ReplaceIntOption(local->options, "BottomY", value);
+ priv->bottomY = xf86SetIntOption(local->options, "BottomY", 0);
++ InitValuatorAxisStruct(local->dev, 1, priv->topY, priv->bottomY, /* max val */
++ priv->common->wcmResolY, /* tablet resolution */
++ 0, priv->common->wcmResolY); /* max_res */
+ break;
+ case XWACOM_PARAM_BUTTON1:
+ if ((value < 0) || (value > 19)) return BadValue;
+@@ -782,6 +787,12 @@
+ "BottomY", priv->common->wcmMaxY);
+ priv->bottomY = xf86SetIntOption(local->options,
+ "BottomY", priv->common->wcmMaxY);
++ InitValuatorAxisStruct(local->dev, 0, priv->topX, priv->bottomX,
++ priv->common->wcmResolX, /* tablet resolution */
++ 0, priv->common->wcmResolX); /* max_res */
++ InitValuatorAxisStruct(local->dev, 1, priv->topY, priv->bottomY, /* max val */
++ priv->common->wcmResolY, /* tablet resolution */
++ 0, priv->common->wcmResolY); /* max_res */
+ break;
+ case XWACOM_PARAM_GIMP:
+ if ((value != 0) && (value != 1)) return BadValue;
+@@ -819,6 +830,103 @@
+ xf86ReplaceStrOption(local->options, "TPCButton", "off");
+ }
+ break;
++ case XWACOM_PARAM_ROTATE:
++ if ((value < 0) || (value > 3)) return BadValue;
++ switch(value) {
++ case ROTATE_NONE:
++ xf86ReplaceStrOption(local->options, "Rotate", "NONE");
++ break;
++ case ROTATE_CW:
++ xf86ReplaceStrOption(local->options, "Rotate", "CW");
++ break;
++ case ROTATE_CCW:
++ xf86ReplaceStrOption(local->options, "Rotate", "CCW");
++ break;
++ case ROTATE_HALF:
++ xf86ReplaceStrOption(local->options, "Rotate", "HALF");
++ break;
++ default:
++ return BadValue;
++ }
++ oldRotation = priv->common->wcmRotate;
++ oldMaxX = priv->common->wcmMaxX;
++ oldMaxY = priv->common->wcmMaxY;
++ priv->common->wcmRotate = value;
++ if (((oldRotation == ROTATE_NONE || oldRotation == ROTATE_HALF) && (value == ROTATE_CW || value == ROTATE_CCW)) ||
++ ((oldRotation == ROTATE_CW || oldRotation == ROTATE_CCW) && (value == ROTATE_NONE || value == ROTATE_HALF)))
++ {
++ priv->common->wcmMaxX = oldMaxY;
++ priv->common->wcmMaxY = oldMaxX;
++ }
++
++ /* rotate all devices at once! else they get misaligned */
++ for (dev=0; dev < priv->common->wcmNumDevices; dev++)
++ {
++ tmppriv = (WacomDevicePtr)priv->common->wcmDevices[dev]->private;
++ /* recover the unrotated xy-rectangles */
++ switch (oldRotation) {
++ case ROTATE_CW:
++ tmpTopX = oldMaxY - tmppriv->bottomY;
++ tmpBottomX = oldMaxY - tmppriv->topY;
++ tmpTopY = tmppriv->topX;
++ tmpBottomY = tmppriv->bottomX;
++ break;
++ case ROTATE_CCW:
++ tmpTopX = tmppriv->topY;
++ tmpBottomX = tmppriv->bottomY;
++ tmpTopY = oldMaxX - tmppriv->bottomX;
++ tmpBottomY = oldMaxX - tmppriv->topX;
++ break;
++ case ROTATE_HALF:
++ tmpTopX = oldMaxX - tmppriv->bottomX;
++ tmpBottomX = oldMaxX - tmppriv->topX;
++ tmpTopY = oldMaxY - tmppriv->bottomY;
++ tmpBottomY = oldMaxY - tmppriv->topY;
++ break;
++ default: /* ROTATE_NONE */
++ tmpTopX = tmppriv->topX;
++ tmpBottomX = tmppriv->bottomX;
++ tmpTopY = tmppriv->topY;
++ tmpBottomY = tmppriv->bottomY;
++ break;
++ }
++ /* and rotate them back */
++ switch (value) {
++ case ROTATE_CW:
++ tmppriv->topX = tmpTopY;
++ tmppriv->bottomX = tmpBottomY;
++ tmppriv->topY = priv->common->wcmMaxY - tmpBottomX;
++ tmppriv->bottomY = priv->common->wcmMaxY - tmpTopX;
++ break;
++ case ROTATE_CCW:
++ tmppriv->topX = priv->common->wcmMaxX - tmpBottomY;
++ tmppriv->bottomX = priv->common->wcmMaxX - tmpTopY;
++ tmppriv->topY = tmpTopX;
++ tmppriv->bottomY = tmpBottomX;
++ break;
++ case ROTATE_HALF:
++ tmppriv->topX = priv->common->wcmMaxX - tmpBottomX;
++ tmppriv->bottomX = priv->common->wcmMaxX - tmpTopX;
++ tmppriv->topY= priv->common->wcmMaxY - tmpBottomY;
++ tmppriv->bottomY = priv->common->wcmMaxY - tmpTopY;
++ break;
++ default: /* ROTATE_NONE */
++ tmppriv->topX = tmpTopX;
++ tmppriv->bottomX = tmpBottomX;
++ tmppriv->topY = tmpTopY;
++ tmppriv->bottomY = tmpBottomY;
++ break;
++ }
++
++ InitValuatorAxisStruct(priv->common->wcmDevices[dev]->dev,
++ 0, tmppriv->topX, tmppriv->bottomX, priv->common->wcmResolX, /* tablet resolution */
++ 0, priv->common->wcmResolX); /* max_res */
++
++ InitValuatorAxisStruct(priv->common->wcmDevices[dev]->dev,
++ 1, tmppriv->topY, tmppriv->bottomY, priv->common->wcmResolY, /* tablet resolution */
++ 0, priv->common->wcmResolY); /* max_res */
++ }
++ break;
+ default:
+ DBG(10, ErrorF("xf86WcmSetParam invalid param %d\n",param));
+ return BadMatch;
+diff -Naur linuxwacom-0.7.0/src/xf86Wacom.h linuxwacom-0.7.0-rotate/src/xf86Wacom.h
+--- linuxwacom-0.7.0/src/xf86Wacom.h 2005-09-19 19:43:14.000000000 -0400
++++ linuxwacom-0.7.0-rotate/src/xf86Wacom.h 2005-11-22 17:06:57.000000000 -0500
+@@ -150,6 +150,12 @@
+ #define ERASER_PROX 4
+ #define OTHER_PROX 1
+
++
++#define ROTATE_NONE XWACOM_VALUE_ROTATE_NONE
++#define ROTATE_CW XWACOM_VALUE_ROTATE_CW
++#define ROTATE_CCW XWACOM_VALUE_ROTATE_CCW
++#define ROTATE_HALF XWACOM_VALUE_ROTATE_HALF
++
+ /******************************************************************************
+ * Forward Declarations
+ *****************************************************************************/
+@@ -412,10 +418,6 @@
+
+ #define DEVICE_ISDV4 0x000C
+
+-#define ROTATE_NONE 0
+-#define ROTATE_CW 1
+-#define ROTATE_CCW 2
+-
+ #define MAX_CHANNELS 2
+ #define MAX_USB_EVENTS 32
+
+diff -Naur linuxwacom-0.7.0/src/xsetwacom.c linuxwacom-0.7.0-rotate/src/xsetwacom.c
+--- linuxwacom-0.7.0/src/xsetwacom.c 2005-09-19 19:43:14.000000000 -0400
++++ linuxwacom-0.7.0-rotate/src/xsetwacom.c 2005-11-22 17:17:24.000000000 -0500
+@@ -190,6 +190,13 @@
+ "on for Tablet PC. ",
+ XWACOM_PARAM_TPCBUTTON, VALUE_OPTIONAL,
+ RANGE, 0, 1, BOOLEAN_VALUE, 1 },
++
++ { "Rotate",
++ "Sets the rotation of the tablet. "
++ "Values = NONE, CW, CCW, HALF (default is NONE).",
++ XWACOM_PARAM_ROTATE, VALUE_OPTIONAL,
++ RANGE, XWACOM_VALUE_ROTATE_NONE, XWACOM_VALUE_ROTATE_HALF, SINGLE_VALUE,
++ XWACOM_VALUE_ROTATE_NONE },
+
+ { "FileModel",
+ "Writes tablet models to /etc/wacom.dat",
+@@ -198,7 +205,7 @@
+ { "FileOption",
+ "Writes configuration options to /etc/X11/wcm.dev_name",
+ XWACOM_PARAM_FILEOPTION, VALUE_OPTIONAL },
+-
++
+ { NULL }
+ };
+
+@@ -403,6 +410,23 @@
+ !strcasecmp(pszValues[i],"false") ||
+ !strcasecmp(pszValues[i],"relative")))
+ nValues[i] = 0;
++ else if (p->nParamID == XWACOM_PARAM_ROTATE)
++ {
++ if (!strcasecmp(pszValues[i],"none"))
++ nValues[i] = XWACOM_VALUE_ROTATE_NONE;
++ else if (!strcasecmp(pszValues[i],"cw"))
++ nValues[i] = XWACOM_VALUE_ROTATE_CW;
++ else if (!strcasecmp(pszValues[i],"ccw"))
++ nValues[i] = XWACOM_VALUE_ROTATE_CCW;
++ else if (!strcasecmp(pszValues[i],"half"))
++ nValues[i] = XWACOM_VALUE_ROTATE_HALF;
++ else
++ {
++ fprintf(stderr,"Set: Value '%s' is "
++ "invalid.\n",pszValues[i]);
++ return 1;
++ }
++ }
+ else
+ {
+ fprintf(stderr,"Set: Value '%s' is "
+diff -Naur linuxwacom-0.7.0/src/Xwacom.h linuxwacom-0.7.0-rotate/src/Xwacom.h
+--- linuxwacom-0.7.0/src/Xwacom.h 2005-09-19 19:43:14.000000000 -0400
++++ linuxwacom-0.7.0-rotate/src/Xwacom.h 2005-11-22 17:06:00.000000000 -0500
+@@ -44,5 +44,11 @@
+ #define XWACOM_PARAM_GIMP 102
+ #define XWACOM_PARAM_MMT 103
+ #define XWACOM_PARAM_TPCBUTTON 104
++#define XWACOM_PARAM_ROTATE 105
++
++#define XWACOM_VALUE_ROTATE_NONE 0
++#define XWACOM_VALUE_ROTATE_CW 1
++#define XWACOM_VALUE_ROTATE_CCW 2
++#define XWACOM_VALUE_ROTATE_HALF 3
+
+ #endif /* __XF86_XWACOM_H */