2014-11-06 13:19:51 +01:00

1167 lines
26 KiB
C

/***********************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/* $XConsortium: qvss_io.c,v 1.105 91/07/17 17:26:20 rws Exp $ */
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <errno.h>
#include <dev/wscons/wsconsio.h>
#include "X.h"
#define NEED_EVENTS
#include "Xproto.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "pixmap.h"
#include "input.h"
#include "windowstr.h"
#include "regionstr.h"
#include "resource.h"
#include <machine/qvioctl.h>
#include "mfb.h"
#include "mi.h"
static Bool qvRealizeCursor(), qvUnrealizeCursor(), qvDisplayCursor();
static Bool qvSetCursorPosition();
static void qvCursorLimits();
static void qvPointerNonInterestBox();
static void qvConstrainCursor();
static void qvQueryBestSize();
void qvResolveColor();
Bool qvCreateColormap();
void qvDestroyColormap();
extern void miRecolorCursor();
static int qvGetMotionEvents();
static void qvChangePointerControl(), qvChangeKeyboardControl(), qvBell();
extern Bool mfbScreenInit();
extern int monitorResolution;
extern int errno;
/*
* Ultrix 3.0 uses new names for everything!
*/
#ifdef _QVEVENT_
# define ULTRIX3_0
#endif
#ifdef ULTRIX3_0
/*
* the stuff below makes this code work on
* both qv and sm drivers under Ultrix 3.0 (ne 2.4)
*/
/* XXX WARNING!!! This kludge assumes that
* the event/cursor/box structures are identical
* in size for both qv and sm. If they change
* radically, get help
*/
#undef QIOCGINFO
#undef QIOCSMSTATE
#undef QIOCINIT
#undef QIOCKPCMD
#undef QIOCADDR
#undef QIOWCURSOR
#undef QIOKERNLOOP
#undef QIOKERNUNLOOP
#undef QIODISPON
#undef QIOVIDEOON
#undef QIODISPOFF
#undef QIOVIDEOOFF
#undef QD_KERN_UNLOOP
#undef HOLD
#define mouse_report bogus_mouse_report
#define _event sm_event
#define _timecoord sm_timecoord
#define _eventqueue sm_eventqueue
#define _cursor sm_cursor
#define _box sm_box
# include <vaxuba/smioctl.h>
#undef mouse_report
#undef _event
#undef _timecoord
#undef _eventqueue
#undef _cursor
#undef _box
static Bool isSMdevice;
static struct sm_info *smInfo;
static struct qv_info *qvInfo;
/*
* magic defines to make the code below less
* ugly
*/
# define vsEventQueue qvEventQueue
# define vsCursor qvCursor
# define vsEvent qvEvent
# define vsTimeCoord qvTimeCoord
# define vsBox qvBox
# define head eHead
# define tail eTail
# define size eSize
# define vse_x x
# define vse_y y
# define vse_time time
# define vse_type type
# define vse_device device
# define vse_key key
# define vse_direction direction
# define VSE_KBTDOWN QV_KBTDOWN
# define VSE_KBTUP QV_KBTUP
# define VSE_KBTRAW QV_KBTRAW
# define VSE_BUTTON QV_BUTTON
#else
static struct qv_info *qvInfo;
static struct qv_info qvInfostore;
static short cursorbitsstore[16];
#endif
static vsEventQueue *queue;
static vsBox *mbox;
static vsCursor *mouse;
static caddr_t smaddr;
static int fdQVSS;
static int qLimit;
static int lastEventTime;
static DevicePtr qvKeyboard;
static DevicePtr qvPointer;
static int hotX, hotY;
static BoxRec constraintBox;
static Bool (*CloseScreen)();
#define MAX_LED 3 /* only 3 LED's can be set by user; Lock LED is controlled by server */
/* ARGSUSED */
static Bool qvssSaveScreen(pScreen, on)
ScreenPtr pScreen;
int on;
{
if (on == SCREEN_SAVER_FORCER)
{
lastEventTime = GetTimeInMillis();
return TRUE;
}
else if (on == SCREEN_SAVER_ON || on == SCREEN_SAVER_CYCLE)
{
#ifdef QIOVIDEOOFF
(void) ioctl(fdQVSS, QIOVIDEOOFF, (char *)NULL);
return TRUE;
#else
return FALSE;
#endif
}
else
{
#ifdef QIOVIDEOON
(void) ioctl(fdQVSS, QIOVIDEOON, (char *)NULL);
return TRUE;
#else
return FALSE;
#endif
}
}
/* ARGSUSED */
static Bool
qvssScreenClose(index, pScreen)
int index;
ScreenPtr pScreen;
{
/* This routine frees all of the dynamically allocated space associate
with a screen. */
(*CloseScreen) (index, pScreen);
if(close(fdQVSS))
{
ErrorF("Closing QVSS yielded %d\n", errno);
return (FALSE);
}
return (TRUE);
}
static
qvssPixelError(index)
int index;
{
ErrorF("Only 0 or 1 are acceptable pixels for device %d\n", index);
}
Bool
qvssScreenInit(index, pScreen, argc, argv)
int index;
ScreenPtr pScreen;
int argc; /* these two may NOT be changed */
char **argv;
{
Bool retval, SpecificB, SpecificW;
ColormapPtr pColormap;
VisualPtr pVisual;
int i;
char *blackValue, *whiteValue;
qvInfo = &qvInfostore;
qvInfo->cursorbits = cursorbitsstore;
if ((fdQVSS = open("/dev/ttyw7", O_RDWR | O_NDELAY, 0)) < 0)
{
ErrorF( "couldn't open console (ttyw7)\n");
return FALSE;
}
i = WSDISPLAYIO_MODE_MAPPED;
if ((ioctl(fdQVSS, WSDISPLAYIO_SMODE, &i)) < 0) {
ErrorF("Couldn't set console graphics mode\n");
return FALSE;
}
smaddr = mmap(0, 128*1024, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
fdQVSS, 0);
if (smaddr < 0) {
ErrorF("Couldn't mmap graphics\n");
return FALSE;
}
#if 0
/* force an init to get the scrollmap right */
ioctl(fdQVSS, QIOCINIT, (char *)NULL);
if (ioctl(fdQVSS, QIOCADDR, (char *)&qvInfo) < 0)
{
ErrorF( "error getting address of QVSS \n");
close(fdQVSS);
return FALSE;
}
#endif
#ifdef QIOVIDEOON
(void) ioctl(fdQVSS, QIOVIDEOON, (char *)NULL);
#endif
#ifdef ULTRIX3_0
/*
* test to see if we're using the sm driver instead
*/
isSMdevice = FALSE;
if ((char *) 0 <= qvInfo->bitmap && qvInfo->bitmap <= (char *) 0x7fffffff) {
smInfo = (struct sm_info *) qvInfo;
isSMdevice = TRUE;
}
#endif
#ifdef ULTRIX3_0
if (isSMdevice) {
mouse = (vsCursor *) &smInfo->mouse;
mbox = (vsBox *) &smInfo->mbox;
queue = (vsEventQueue *) &smInfo->qe;
} else
#endif
{
mouse = (vsCursor *) &qvInfo->mouse;
mbox = (vsBox *) &qvInfo->mbox;
mbox->bottom = 0; /* trash pointer non-interest box 'cause driver won't */
#ifdef ULTRIX3_0
queue = &qvInfo->qe;
#else
/*
the following hack is really pretending a part of one record
is really a record of another type!
*/
queue = (vsEventQueue *) &qvInfo->ibuff;
#endif
}
qLimit = queue->size - 1;
blackValue = NULL;
SpecificB = FALSE;
whiteValue = NULL;
SpecificW = FALSE;
for(i = 1; i < argc; i++)
{
if(strncmp(argv[i], "-bp:", 4) == 0 && atoi(argv[i] + 4) == index)
{
if(++i < argc)
{
blackValue = argv[i];
SpecificB = TRUE;
}
else
UseMsg();
}
if(strncmp(argv[i], "-wp:", 4) == 0 && atoi(argv[i] + 4) == index)
{
if(++i < argc)
{
whiteValue = argv[i];
SpecificW = TRUE;
}
else
UseMsg();
}
if(strcmp(argv[i], "-bp") == 0 && !SpecificB)
{
if(++i < argc)
{
blackValue = argv[i];
}
else
UseMsg();
}
if(strcmp(argv[i], "-wp") == 0 && !SpecificW)
{
if(++i < argc)
{
whiteValue = argv[i];
}
else
UseMsg();
}
}
pScreen->blackPixel = 0;
pScreen->whitePixel = 1;
if(blackValue)
{
if((i = atoi(blackValue)) == 0 || i == 1)
pScreen->blackPixel = i;
else
qvssPixelError(index);
}
if(whiteValue)
{
if((i = atoi(whiteValue)) == 0 || i == 1)
pScreen->whitePixel = i;
else
qvssPixelError(index);
}
/*
* qv screen saver
*/
pScreen->SaveScreen = qvssSaveScreen;
/*
* qv cursor routines
*/
pScreen->RealizeCursor = qvRealizeCursor;
pScreen->UnrealizeCursor = qvUnrealizeCursor;
pScreen->DisplayCursor = qvDisplayCursor;
pScreen->SetCursorPosition = qvSetCursorPosition;
pScreen->CursorLimits = qvCursorLimits;
pScreen->PointerNonInterestBox = qvPointerNonInterestBox;
pScreen->ConstrainCursor = qvConstrainCursor;
pScreen->RecolorCursor = miRecolorCursor;
i = monitorResolution ? monitorResolution : 80;
#ifdef ULTRIX3_0
if (isSMdevice)
retval = mfbScreenInit(pScreen, smaddr, 1024, 864, i, i, 1024);
else
#endif
retval = mfbScreenInit(pScreen, smaddr, 1024, 864, i, i, 1024);
if (!retval)
{
close(fdQVSS);
return FALSE;
}
/*
* qvQueryBestSize gives hints for cursors, as well as
* for pixmaps and tiles, mash the mfb supplied version
*/
pScreen->QueryBestSize = qvQueryBestSize;
/*
* wrap screen close routine with our own
*/
CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = qvssScreenClose;
/*
* create and install the default colormap
*/
if (!mfbCreateDefColormap (pScreen))
{
close (fdQVSS);
return FALSE;
}
return TRUE;
}
/* ARGSUSED */
int
qvssMouseProc(pDev, onoff, argc, argv)
DevicePtr pDev;
int onoff, argc;
char *argv[];
{
BYTE map[4];
switch (onoff)
{
case DEVICE_INIT:
qvPointer = pDev;
pDev->devicePrivate = (pointer) &queue;
map[1] = 1;
map[2] = 2;
map[3] = 3;
InitPointerDeviceStruct(
qvPointer, map, 3, qvGetMotionEvents, qvChangePointerControl,
0);
SetInputCheck(&queue->head, &queue->tail);
break;
case DEVICE_ON:
pDev->on = TRUE;
hotX = hotY = 0;
AddEnabledDevice(fdQVSS);
break;
case DEVICE_OFF:
pDev->on = FALSE;
/* RemoveEnabledDevice(fdQVSS); */
break;
case DEVICE_CLOSE:
break;
}
return Success;
}
#define LK_REPEAT_ON 0xe3
#define LK_REPEAT_OFF 0xe1
int
SetLKAutoRepeat (onoff)
Bool onoff;
{
extern char *AutoRepeatLKMode();
extern char *UpDownLKMode();
struct qv_kpcmd ioc;
register char *divsets;
divsets = onoff ? (char *) AutoRepeatLKMode() : (char *) UpDownLKMode();
ioc.nbytes = 0;
while (ioc.cmd = *divsets++)
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
ioc.cmd = ((onoff > 0) ? LK_REPEAT_ON : LK_REPEAT_OFF);
return(ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc));
}
/* ARGSUSED */
int
qvssKeybdProc(pDev, onoff, argc, argv)
DevicePtr pDev;
int onoff, argc;
char *argv[];
{
KeySymsRec keySyms;
CARD8 modMap[MAP_LENGTH];
switch (onoff)
{
case DEVICE_INIT:
qvKeyboard = pDev;
pDev->devicePrivate = (pointer) & queue;
if (!GetLK201Mappings( &keySyms, modMap))
return BadAlloc;
InitKeyboardDeviceStruct(
qvKeyboard, &keySyms, modMap, qvBell,
qvChangeKeyboardControl);
xfree(keySyms.map);
/* SetLKAutoRepeat(FALSE); */
break;
case DEVICE_ON:
pDev->on = TRUE;
AddEnabledDevice(fdQVSS);
break;
case DEVICE_OFF:
pDev->on = FALSE;
/* RemoveEnabledDevice(fdQVSS); */
break;
case DEVICE_CLOSE:
break;
}
return Success;
}
/*****************
* ProcessInputEvents:
* processes all the pending input events
*****************/
extern int screenIsSaved;
void
ProcessInputEvents()
{
#define DEVICE_KEYBOARD 2
register int i;
register vsEvent * pE;
xEvent x;
int nowInCentiSecs, nowInMilliSecs, adjustCentiSecs;
struct timeval tp;
int needTime = 1;
#ifndef NO_EVENT_COMPRESSION
int j;
#endif
i = queue->head;
while (i != queue->tail)
{
if (screenIsSaved == SCREEN_SAVER_ON)
SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
pE = &queue->events[i];
x.u.keyButtonPointer.rootX = pE->vse_x + hotX;
x.u.keyButtonPointer.rootY = pE->vse_y + hotY;
if (sizeof(pE->vse_time) == 4)
x.u.keyButtonPointer.time = lastEventTime = pE->vse_time;
else {
/*
* The following silly looking code is because the old version of the
* driver only delivers 16 bits worth of centiseconds. We are supposed
* to be keeping time in terms of 32 bits of milliseconds.
*/
if (needTime)
{
needTime = 0;
gettimeofday(&tp, 0);
nowInCentiSecs = ((tp.tv_sec * 100) + (tp.tv_usec / 10000)) & 0xFFFF;
/* same as driver */
nowInMilliSecs = (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
/* beware overflow */
}
if ((adjustCentiSecs = nowInCentiSecs - pE->vse_time) < -20000)
adjustCentiSecs += 0x10000;
else
if (adjustCentiSecs > 20000)
adjustCentiSecs -= 0x10000;
x.u.keyButtonPointer.time = lastEventTime =
nowInMilliSecs - adjustCentiSecs * 10;
}
#ifdef ULTRIX3_0
if (isSMdevice) {
if ((pE->type != MOTION_TYPE) &&
(pE->device == KEYBOARD_DEVICE))
{
x.u.u.detail = pE->key;
switch (pE->type)
{
case BUTTON_DOWN_TYPE:
x.u.u.type = KeyPress;
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
break;
case BUTTON_UP_TYPE:
x.u.u.type = KeyRelease;
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
break;
case BUTTON_RAW_TYPE:
ProcessLK201Input(&x, qvKeyboard);
}
}
else
{
if (pE->type != MOTION_TYPE)
{
if (pE->type == BUTTON_DOWN_TYPE)
x.u.u.type = ButtonPress;
else
x.u.u.type = ButtonRelease;
/* mouse buttons numbered from one */
x.u.u.detail = pE->key;
}
else {
/* tell the server that the mouse moved */
x.u.u.type = MotionNotify;
}
(*qvPointer->processInputProc)(&x, qvPointer, 1);
}
}
else
#endif
{
if ((pE->vse_type == VSE_BUTTON) &&
(pE->vse_device == DEVICE_KEYBOARD))
{ /* better be a button */
x.u.u.detail = pE->vse_key;
switch (pE->vse_direction)
{
case VSE_KBTDOWN:
x.u.u.type = KeyPress;
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
break;
case VSE_KBTUP:
x.u.u.type = KeyRelease;
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
break;
default: /* hopefully BUTTON_RAW_TYPE */
ProcessLK201Input(&x, qvKeyboard);
}
}
else
{
if (pE->vse_type == VSE_BUTTON)
{
if (pE->vse_direction == VSE_KBTDOWN)
x.u.u.type = ButtonPress;
else
x.u.u.type = ButtonRelease;
/* mouse buttons numbered from one */
x.u.u.detail = pE->vse_key + 1;
}
else {
#ifndef NO_EVENT_COMPRESSION
j = (i == qLimit) ? 0 : i + 1;
/*
* to get here we knew that
*
* (vse_type != VSE_BUTTON ||
* vse_device != DEVICE_KEYBOARD) &&
* (vse_type != VSE_BUTTON)
*
* which means that for the next event to be a mouse
* motion, it must satisfy vse_type != VSE_BUTTON
*
* XXX -- We should implement motion history since we are
* throwing device events away....
*/
if (j != queue->tail &&
queue->events[j].vse_type != VSE_BUTTON)
goto next; /* sometimes the dragon wins */
#endif
/* tell the server that the mouse moved */
x.u.u.type = MotionNotify;
}
(*qvPointer->processInputProc)(&x, qvPointer, 1);
}
}
next:
if (i == qLimit)
i = queue->head = 0;
else
i = ++queue->head;
}
#undef DEVICE_KEYBOARD
}
TimeSinceLastInputEvent()
{
if (lastEventTime == 0)
lastEventTime = GetTimeInMillis();
return GetTimeInMillis() - lastEventTime;
}
/* ARGSUSED */
static void
qvBell(loud, pDevice)
int loud;
DevicePtr pDevice;
{
#define LK_ENABLE_BELL 0x23 /* enable bell / set volume */
struct qv_kpcmd ioc;
/* the lk201 volume is between 7 (quiet but audible) and 0 (loud) */
loud = 7 - ((loud / 14) & 7);
ioc.nbytes = 1;
ioc.cmd = LK_ENABLE_BELL;
ioc.par[0] = loud;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
ioc.nbytes = 0;
ioc.cmd = LK_RING_BELL;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
}
static void
ChangeLED(led, on)
int led;
Bool on;
{
struct qv_kpcmd ioc;
switch (led) {
case 1:
ioc.par[0] = LED_1;
break;
case 2:
ioc.par[0] = LED_2;
break;
case 3:
/* the keyboard's LED_3 is the Lock LED, which the server owns.
So the user's LED #3 maps to the keyboard's LED_4. */
ioc.par[0] = LED_4;
break;
default:
return; /* out-of-range LED value */
}
ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
ioc.par[1] = 0;
ioc.nbytes = 1;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
}
SetLockLED (on)
Bool on;
{
struct qv_kpcmd ioc;
ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
ioc.par[0] = LED_3;
ioc.par[1] = 0;
ioc.nbytes = 1;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
}
/* ARGSUSED */
static void
qvChangeKeyboardControl(pDevice, ctrl)
DevicePtr pDevice;
KeybdCtrl *ctrl;
{
#define LK_ENABLE_CLICK 0x1b /* enable keyclick / set volume */
#define LK_DISABLE_CLICK 0x99 /* disable keyclick entirely */
#define LK_ENABLE_BELL 0x23 /* enable bell / set volume */
struct qv_kpcmd ioc;
int i;
if (ctrl->click == 0) /* turn click off */
{
ioc.nbytes = 0;
ioc.cmd = LK_DISABLE_CLICK;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
}
else
{
int volume;
volume = 7 - ((ctrl->click / 14) & 7);
ioc.nbytes = 1;
ioc.cmd = LK_ENABLE_CLICK;
ioc.par[0] = volume;
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
}
/* ctrl->bell: the DIX layer handles the base volume for the bell */
/* ctrl->bell_pitch: as far as I can tell, you can't set this on lk201 */
/* ctrl->bell_duration: as far as I can tell, you can't set this */
/* LEDs */
for (i=1; i<=MAX_LED; i++)
ChangeLED(i, (ctrl->leds & (1 << (i-1))) ? TRUE : FALSE);
/* ctrl->autoRepeat: I'm turning it all on or all off. */
SetLKAutoRepeat(ctrl->autoRepeat);
}
/* ARGSUSED */
static void
qvChangePointerControl(pDevice, ctrl)
DevicePtr pDevice;
PtrCtrl *ctrl;
{
#ifdef ULTRIX3_0
if (isSMdevice)
{
smInfo->mthreshold = ctrl->threshold;
if (!(smInfo->mscale = ctrl->num / ctrl->den))
smInfo->mscale = 1; /* watch for den > num */
}
else
#endif
{
qvInfo->mthreshold = ctrl->threshold;
if (!(qvInfo->mscale = ctrl->num / ctrl->den))
qvInfo->mscale = 1; /* watch for den > num */
}
}
/* ARGSUSED */
static int
qvGetMotionEvents(buff, start, stop, pScr)
CARD32 start, stop;
xTimecoord *buff;
ScreenPtr pScr;
{
return 0;
}
/* ARGSUSED */
static Bool
qvSetCursorPosition( pScr, newx, newy, generateEvent)
ScreenPtr pScr;
int newx;
int newy;
Bool generateEvent;
{
vsCursor cursor;
xEvent motion;
cursor.x = newx - hotX;
cursor.y = newy - hotY;
#if 0
if ( ioctl(fdQVSS, QIOCSMSTATE, (char *)&cursor) < 0)
{
ErrorF( "error warping cursor\n");
return FALSE;
}
#endif
if (generateEvent)
{
if (queue->head != queue->tail)
ProcessInputEvents();
motion.u.keyButtonPointer.rootX = newx;
motion.u.keyButtonPointer.rootY = newy;
motion.u.keyButtonPointer.time = lastEventTime;
motion.u.u.type = MotionNotify;
(*qvPointer->processInputProc) (&motion, qvPointer, 1);
}
return TRUE;
}
static Bool
qvDisplayCursor( pScr, pCurs)
ScreenPtr pScr;
CursorPtr pCurs;
{
char buf[200];
int i, x, y;
/*
* load the cursor
*/
if ((hotX != (int)pCurs->bits->xhot) || (hotY != (int)pCurs->bits->yhot))
{
x = mouse->x + hotX;
y = mouse->y + hotY;
hotX = pCurs->bits->xhot;
hotY = pCurs->bits->yhot;
qvSetCursorPosition(pScr, x, y, FALSE);
qvConstrainCursor(pScr, &constraintBox);
}
#ifdef ULTRIX3_0
if (isSMdevice)
{
if ( ioctl (fdQVSS, QIOWCURSOR, (char *)((short *)pCurs->devPriv[ pScr->myNum]))
< 0)
{
ErrorF( "error writing cursor\n");
return FALSE;
}
#ifdef notdef
for ( i=0; i<16; i++)
smInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
#endif
}
else
#endif
{
for ( i=0; i<16; i++)
qvInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
}
return TRUE;
}
/* ARGSUSED */
static void
qvPointerNonInterestBox( pScr, pBox)
ScreenPtr pScr;
BoxPtr pBox;
{
mbox->bottom = pBox->y2;
mbox->top = pBox->y1;
mbox->left = pBox->x1;
mbox->right = pBox->x2;
}
/* note that this driver does not support dealing with the minimums */
/* ARGSUSED */
static void
qvConstrainCursor( pScr, pBox)
ScreenPtr pScr;
BoxPtr pBox;
{
constraintBox = *pBox;
#ifdef ULTRIX3_0
if (isSMdevice && smInfo)
{
smInfo->min_cur_x = pBox->x1 - hotX;
smInfo->min_cur_y = pBox->y1 - hotY;
smInfo->max_cur_x = pBox->x2 - hotX - 1;
smInfo->max_cur_y = pBox->y2 - hotY - 1;
} else
#endif
if (qvInfo)
{
qvInfo->max_cur_x = pBox->x2 - hotX - 1;
qvInfo->max_cur_y = pBox->y2 - hotY - 1;
}
else
ErrorF( "qvConstrainCursor: info = %x\n", qvInfo);
}
/*
* qv cursor top-left corner cannot go to negative coordinates,
* but sm can.
*/
/* ARGSUSED */static void
qvCursorLimits( pScr, pCurs, pHotBox, pPhysBox)
ScreenPtr pScr;
CursorPtr pCurs;
BoxPtr pHotBox;
BoxPtr pPhysBox; /* return value */
{
#ifdef ULTRIX3_0
if (isSMdevice)
{
pPhysBox->x1 = pHotBox->x1;
pPhysBox->y1 = pHotBox->y1;
}
else
#endif
{
pPhysBox->x1 = max( pHotBox->x1, (int)pCurs->bits->xhot);
pPhysBox->y1 = max( pHotBox->y1, (int)pCurs->bits->yhot);
}
pPhysBox->x2 = min( pHotBox->x2, 1024);
pPhysBox->y2 = min( pHotBox->y2, 864);
}
static Bool
qvRealizeCursor( pScr, pCurs)
ScreenPtr pScr;
CursorPtr pCurs; /* a SERVER-DEPENDENT cursor */
{
unsigned short red, green, blue;
int forecolor, backcolor;
register short *a, *b; /* hardware-defined */
register int * mask; /* server-defined */
register int * src; /* server-defined */
register int i;
int cursorBytes = 32*sizeof(short);
int lastRow = ((pCurs->bits->height < 16) ? pCurs->bits->height : 16);
register unsigned short widthmask = (1<<pCurs->bits->width)-1;
/* used to mask off beyond the edge of the
real mask and source bits
*/
red = pCurs->foreRed;
green = pCurs->foreGreen;
blue = pCurs->foreBlue;
mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
forecolor = red;
red = pCurs->backRed;
green = pCurs->backGreen;
blue = pCurs->backBlue;
mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
backcolor = red;
pCurs->devPriv[ pScr->myNum] = (pointer)xalloc(cursorBytes);
if (!pCurs->devPriv[ pScr->myNum])
return FALSE;
bzero((char *)pCurs->devPriv[ pScr->myNum], cursorBytes);
/*
* munge the SERVER-DEPENDENT, device-independent cursor bits into
* what the device wants, which is 32 contiguous shorts.
*
* cursor hardware has "A" and "B" bitmaps
* logic table is:
*
* A B cursor
*
* 0 0 transparent
* 1 0 xor (not used)
* 0 1 black
* 1 1 white
*/
/*
* "a" bitmap = image
*
* "b" bitmap can be same as "mask", providing "a" is never on when
* "b" is off.
*/
for ( i=0,
a = (short *)pCurs->devPriv[pScr->myNum],
b = ((short *)pCurs->devPriv[pScr->myNum]) + 16,
/* XXX assumes DIX pixmap pad is size of int,
and cursor is < 32 bits wide
*/
src = (int *)pCurs->bits->source,
mask = (int *)pCurs->bits->mask;
i < lastRow;
i++, a++, b++, src++, mask++)
{
#ifdef ULTRIX3_0
if (isSMdevice)
*a = (*src & forecolor) | ((*mask & ~*src) & backcolor);
else
#endif
*a = ((*src & backcolor) | (~*src & forecolor)) & *mask;
*b = *mask;
*a &= widthmask;
*b &= widthmask;
}
return TRUE;
}
static Bool
qvUnrealizeCursor( pScr, pCurs)
ScreenPtr pScr;
CursorPtr pCurs;
{
xfree(pCurs->devPriv[ pScr->myNum]);
return TRUE;
}
static void
qvQueryBestSize(class, pwidth, pheight)
int class;
short *pwidth;
short *pheight;
{
unsigned width, test;
switch(class)
{
case CursorShape:
*pwidth = 16;
*pheight = 16;
break;
case TileShape:
case StippleShape:
width = *pwidth;
if (width != 0) {
/* Return the closest power of two not less than width */
test = 0x80000000;
/* Find the highest 1 bit in the width given */
while(!(test & width))
test >>= 1;
/* If their number is greater than that, bump up to the next
* power of two */
if((test - 1) & width)
test <<= 1;
*pwidth = test;
}
/* We don't care what height they use */
break;
}
}
/* ARGSUSED */
void
qvResolveColor(pred, pgreen, pblue, pVisual)
unsigned short *pred, *pgreen, *pblue;
VisualPtr pVisual;
{
/* Gets intensity from RGB. If intensity is >= half, pick white, else
* pick black. This may well be more trouble than it's worth. */
*pred = *pgreen = *pblue =
(((30L * *pred +
59L * *pgreen +
11L * *pblue) >> 8) >= (((1<<8)-1)*50)) ? ~0 : 0;
}
Bool
qvCreateColormap(pmap)
ColormapPtr pmap;
{
unsigned short red, green, blue;
unsigned long pix;
/* this is a monochrome colormap, it only has two entries, just fill
* them in by hand. If it were a more complex static map, it would be
* worth writing a for loop or three to initialize it */
pix = 0;
red = green = blue = 0;
if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
return FALSE;
pix = 0;
red = green = blue = ~0;
if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
return FALSE;
return TRUE;
}
/* ARGSUSED */
void
qvDestroyColormap(pmap)
ColormapPtr pmap;
{
}
/*
* DDX - specific abort routine. Called by AbortServer().
*/
void
AbortDDX()
{
}
/* Called by GiveUp(). */
void
ddxGiveUp()
{
}
/*ARGSUSED*/
int
ddxProcessArgument (argc, argv, i)
int argc;
char *argv[];
int i;
{
if(!strncmp(argv[i], "-bp:", 4) ||
!strncmp(argv[i], "-wp:", 4) ||
!strcmp(argv[i], "-bp") ||
!strcmp(argv[i], "-wp"))
return 2;
return 0;
}
void
ddxUseMsg()
{
ErrorF("-bp<:screen> color BlackPixel for screen\n");
ErrorF("-wp<:screen> color WhitePixel for screen\n");
}